IDEMPIERE-5567 Support of UUID as Key (FHCA-4195) - ChangeLog - FKRules (#1852)
* IDEMPIERE-5567 Support of UUID as Key (FHCA-4195) - ChangeLog - FKRules * - change warning by IllegalArgumentException - change package visibility to protected * - remove unnecessary code - the Model Cascade is calling the deleteModelCascade for children too * - Implement SysConfig AD_CHANGELOG_SAVE_UUID - reorganize MSysConfig (there were entries out of order) * - Add index for performance on AD_ChangeLog.Record_UU * - Enable change log for tables with multi-key (like _Trl or _Access) * - Enable saving change log for AD_ClientInfo * - when updating a record that doesn't have UUID - assign one
This commit is contained in:
parent
1ff182e605
commit
281333e8b9
|
@ -0,0 +1,190 @@
|
|||
-- IDEMPIERE-5567 Support of UUID - ChangeLog (FHCA-4195)
|
||||
SELECT register_migration_script('202304151832_IDEMPIERE-5567.sql') FROM dual;
|
||||
|
||||
SET SQLBLANKLINES ON
|
||||
SET DEFINE OFF
|
||||
|
||||
-- Apr 15, 2023, 6:32:28 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,SeqNoSelection,IsToolbarButton,IsSecure,FKConstraintType,IsHtml) VALUES (215835,0,'Record UUID',580,'Record_UU',36,'N','N','N','N','N',0,'N',200240,0,0,'Y',TO_TIMESTAMP('2023-04-15 18:32:27','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-04-15 18:32:27','YYYY-MM-DD HH24:MI:SS'),100,203804,'N','N','D','N','N','N','Y','42c26432-ba61-4375-901b-5573a94b3ca3','Y',0,'N','N','N','N')
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:32:30 PM CEST
|
||||
ALTER TABLE AD_ChangeLog ADD Record_UU VARCHAR2(36 CHAR) DEFAULT NULL
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:34:30 PM CEST
|
||||
UPDATE AD_Column SET IsMandatory='N',Updated=TO_TIMESTAMP('2023-04-15 18:34:30','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=8817
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:34:32 PM CEST
|
||||
ALTER TABLE AD_ChangeLog MODIFY Record_ID NUMBER(10) DEFAULT NULL
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:34:32 PM CEST
|
||||
ALTER TABLE AD_ChangeLog MODIFY Record_ID NULL
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:34:44 PM CEST
|
||||
INSERT INTO AD_Field (AD_Field_ID,Name,AD_Tab_ID,AD_Column_ID,IsDisplayed,DisplayLength,SeqNo,IsSameLine,IsHeading,IsFieldOnly,IsEncrypted,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsReadOnly,IsCentrallyMaintained,EntityType,AD_Field_UU,IsDisplayedGrid,SeqNoGrid,ColumnSpan) VALUES (207619,'Record UUID',488,215835,'Y',36,190,'N','N','N','N',0,0,'Y',TO_TIMESTAMP('2023-04-15 18:34:43','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-04-15 18:34:43','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','863e5828-5d78-43d9-bfd6-ef0bd26c6980','Y',190,2)
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:34:50 PM CEST
|
||||
INSERT INTO AD_Field (AD_Field_ID,Name,AD_Tab_ID,AD_Column_ID,IsDisplayed,DisplayLength,SeqNo,IsSameLine,IsHeading,IsFieldOnly,IsEncrypted,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsReadOnly,IsCentrallyMaintained,EntityType,AD_Field_UU,IsDisplayedGrid,SeqNoGrid,ColumnSpan) VALUES (207620,'Record UUID',487,215835,'Y',36,190,'N','N','N','N',0,0,'Y',TO_TIMESTAMP('2023-04-15 18:34:50','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-04-15 18:34:50','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','dab3415a-c850-401f-8b9a-891e60e2999e','Y',190,2)
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:45 PM CEST
|
||||
UPDATE AD_Field SET IsDisplayed='Y', SeqNo=100, XPosition=4,Updated=TO_TIMESTAMP('2023-04-15 18:35:45','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=207619
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:45 PM CEST
|
||||
UPDATE AD_Field SET IsDisplayed='Y', SeqNo=110, XPosition=1,Updated=TO_TIMESTAMP('2023-04-15 18:35:45','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=6779
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:45 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=120,Updated=TO_TIMESTAMP('2023-04-15 18:35:45','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=6774
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:45 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=130,Updated=TO_TIMESTAMP('2023-04-15 18:35:45','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=10946
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:45 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=140,Updated=TO_TIMESTAMP('2023-04-15 18:35:45','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=54397
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:45 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=150,Updated=TO_TIMESTAMP('2023-04-15 18:35:45','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=6780
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:45 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=160,Updated=TO_TIMESTAMP('2023-04-15 18:35:45','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=6773
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:45 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=170,Updated=TO_TIMESTAMP('2023-04-15 18:35:45','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=12356
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:45 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=180,Updated=TO_TIMESTAMP('2023-04-15 18:35:45','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=10948
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:45 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=190,Updated=TO_TIMESTAMP('2023-04-15 18:35:45','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=10947
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:45 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=0,Updated=TO_TIMESTAMP('2023-04-15 18:35:45','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=204473
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:59 PM CEST
|
||||
UPDATE AD_Field SET IsDisplayed='Y', SeqNo=100, XPosition=4,Updated=TO_TIMESTAMP('2023-04-15 18:35:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=207620
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:59 PM CEST
|
||||
UPDATE AD_Field SET IsDisplayed='Y', SeqNo=110, XPosition=1,Updated=TO_TIMESTAMP('2023-04-15 18:35:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=6769
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:59 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=120,Updated=TO_TIMESTAMP('2023-04-15 18:35:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=6764
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:59 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=130,Updated=TO_TIMESTAMP('2023-04-15 18:35:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=10949
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:59 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=140,Updated=TO_TIMESTAMP('2023-04-15 18:35:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=54396
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:59 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=150,Updated=TO_TIMESTAMP('2023-04-15 18:35:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=6770
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:59 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=160,Updated=TO_TIMESTAMP('2023-04-15 18:35:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=6763
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:59 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=170,Updated=TO_TIMESTAMP('2023-04-15 18:35:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=12357
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:59 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=180,Updated=TO_TIMESTAMP('2023-04-15 18:35:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=10951
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:59 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=190,Updated=TO_TIMESTAMP('2023-04-15 18:35:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=10950
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:59 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=0,Updated=TO_TIMESTAMP('2023-04-15 18:35:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=204474
|
||||
;
|
||||
|
||||
-- May 21, 2023, 4:07:46 PM CEST
|
||||
UPDATE AD_Field SET DisplayLogic='@AD_Reference_ID@=19 | @AD_Reference_ID@=30 | @AD_Reference_ID@=18 | @AD_Reference_ID@=21 | @AD_Reference_ID@=25 | @AD_Reference_ID@=31 | @AD_Reference_ID@=35 | @AD_Reference_ID@=33 | @AD_Reference_ID@=32 | @AD_Reference_ID@=53370 | @AD_Reference_ID@=200233 | @AD_Reference_ID@=200234 | @AD_Reference_ID@=200235 | @AD_Reference_ID@=200202 | @AD_Reference_ID@=200240',Updated=TO_TIMESTAMP('2023-05-21 16:07:46','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=202519
|
||||
;
|
||||
|
||||
-- May 21, 2023, 4:13:15 PM CEST
|
||||
UPDATE AD_Val_Rule SET Code='(
|
||||
AD_Ref_List.Value = ''D''
|
||||
/* Cascade/SetNull/Forbid supported for all DB constraints */
|
||||
OR (AD_Ref_List.Value IN (''C'',''S'',''N'') AND @AD_Reference_ID@ IN (18,19,21,25,30,31,32,33,35,53370,200233,200234,200235))
|
||||
/* ModelCascade supported for Table/TableDir/Search/RecordID */
|
||||
OR (AD_Ref_List.Value = ''M'' AND @AD_Reference_ID@ IN (18,19,30,200202,200240))
|
||||
/* ModelSetNull/ModelForbid supported for RecordID */
|
||||
OR (AD_Ref_List.Value IN (''T'',''O'') AND @AD_Reference_ID@ IN (200202,200240))
|
||||
)',Updated=TO_TIMESTAMP('2023-05-21 16:13:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Val_Rule_ID=200064
|
||||
;
|
||||
|
||||
-- May 21, 2023, 4:14:25 PM CEST
|
||||
UPDATE AD_Column SET FieldLength=36, FKConstraintType='D',Updated=TO_TIMESTAMP('2023-05-21 16:14:25','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=215833
|
||||
;
|
||||
|
||||
-- May 22, 2023, 5:37:16 PM CEST
|
||||
INSERT INTO AD_SysConfig (AD_SysConfig_ID,AD_Client_ID,AD_Org_ID,Created,Updated,CreatedBy,UpdatedBy,IsActive,Name,Value,Description,EntityType,ConfigurationLevel,AD_SysConfig_UU) VALUES (200228,0,0,TO_TIMESTAMP('2023-05-22 17:37:15','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2023-05-22 17:37:15','YYYY-MM-DD HH24:MI:SS'),100,100,'Y','AD_CHANGELOG_SAVE_UUID','B','Save the AD_ChangeLog.Record_UU -> B | Just for UUID based tables , A | Always , U | just UUID not ID','D','S','32161230-22c9-43eb-a327-f3b4841eeace')
|
||||
;
|
||||
|
||||
-- May 23, 2023, 5:17:25 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,IsKey) VALUES (0,0,201247,'d0ab3ee4-418c-42e9-acfe-618750685bcc',TO_TIMESTAMP('2023-05-23 17:17:24','YYYY-MM-DD HH24:MI:SS'),100,'D','Y','ad_changelog_record_uu',TO_TIMESTAMP('2023-05-23 17:17:24','YYYY-MM-DD HH24:MI:SS'),100,580,'N','N','N','N')
|
||||
;
|
||||
|
||||
-- May 23, 2023, 5:17:48 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,201686,'6ce73812-0b30-4145-a9c5-ab1c73d4c386',TO_TIMESTAMP('2023-05-23 17:17:47','YYYY-MM-DD HH24:MI:SS'),100,'D','Y',TO_TIMESTAMP('2023-05-23 17:17:47','YYYY-MM-DD HH24:MI:SS'),100,215835,201247,10)
|
||||
;
|
||||
|
||||
-- May 23, 2023, 5:17:53 PM CEST
|
||||
CREATE INDEX ad_changelog_record_uu ON AD_ChangeLog (Record_UU)
|
||||
;
|
||||
|
||||
/*
|
||||
SET SERVEROUTPUT on;
|
||||
|
||||
-- Set Record_UU for existing records
|
||||
DECLARE
|
||||
cmd varchar2(2000);
|
||||
v_cnt numeric;
|
||||
BEGIN
|
||||
FOR r IN (
|
||||
SELECT DISTINCT t.TableName, cl.AD_Table_ID
|
||||
FROM AD_ChangeLog cl
|
||||
JOIN AD_Table t ON (cl.AD_Table_ID=t.AD_Table_ID)
|
||||
WHERE cl.Record_UU IS NULL
|
||||
AND cl.Record_ID IS NOT NULL
|
||||
AND cl.EventChangeLog!='D'
|
||||
) LOOP
|
||||
cmd := 'UPDATE AD_ChangeLog SET Record_UU=(SELECT '
|
||||
|| r.TableName
|
||||
|| '_UU FROM '
|
||||
|| r.TableName
|
||||
|| ' WHERE '
|
||||
|| r.TableName
|
||||
|| '_ID=AD_ChangeLog.Record_ID) WHERE AD_Table_ID='
|
||||
|| r.AD_Table_ID
|
||||
|| ' AND Record_ID IS NOT NULL AND Record_UU IS NULL AND EventChangeLog!=''D''';
|
||||
EXECUTE IMMEDIATE cmd;
|
||||
DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT || ' AD_ChangeLog.Record_UU set in ' || r.TableName);
|
||||
END LOOP;
|
||||
END;
|
||||
/
|
||||
*/
|
||||
|
|
@ -0,0 +1,189 @@
|
|||
-- IDEMPIERE-5567 Support of UUID - ChangeLog (FHCA-4195)
|
||||
SELECT register_migration_script('202304151832_IDEMPIERE-5567.sql') FROM dual;
|
||||
|
||||
-- Apr 15, 2023, 6:32:28 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,SeqNoSelection,IsToolbarButton,IsSecure,FKConstraintType,IsHtml) VALUES (215835,0,'Record UUID',580,'Record_UU',36,'N','N','N','N','N',0,'N',200240,0,0,'Y',TO_TIMESTAMP('2023-04-15 18:32:27','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-04-15 18:32:27','YYYY-MM-DD HH24:MI:SS'),100,203804,'N','N','D','N','N','N','Y','42c26432-ba61-4375-901b-5573a94b3ca3','Y',0,'N','N','N','N')
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:32:30 PM CEST
|
||||
ALTER TABLE AD_ChangeLog ADD COLUMN Record_UU VARCHAR(36) DEFAULT NULL
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:34:30 PM CEST
|
||||
UPDATE AD_Column SET IsMandatory='N',Updated=TO_TIMESTAMP('2023-04-15 18:34:30','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=8817
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:34:32 PM CEST
|
||||
INSERT INTO t_alter_column values('ad_changelog','Record_ID','NUMERIC(10)',null,'NULL')
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:34:32 PM CEST
|
||||
INSERT INTO t_alter_column values('ad_changelog','Record_ID',null,'NULL',null)
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:34:44 PM CEST
|
||||
INSERT INTO AD_Field (AD_Field_ID,Name,AD_Tab_ID,AD_Column_ID,IsDisplayed,DisplayLength,SeqNo,IsSameLine,IsHeading,IsFieldOnly,IsEncrypted,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsReadOnly,IsCentrallyMaintained,EntityType,AD_Field_UU,IsDisplayedGrid,SeqNoGrid,ColumnSpan) VALUES (207619,'Record UUID',488,215835,'Y',36,190,'N','N','N','N',0,0,'Y',TO_TIMESTAMP('2023-04-15 18:34:43','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-04-15 18:34:43','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','863e5828-5d78-43d9-bfd6-ef0bd26c6980','Y',190,2)
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:34:50 PM CEST
|
||||
INSERT INTO AD_Field (AD_Field_ID,Name,AD_Tab_ID,AD_Column_ID,IsDisplayed,DisplayLength,SeqNo,IsSameLine,IsHeading,IsFieldOnly,IsEncrypted,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsReadOnly,IsCentrallyMaintained,EntityType,AD_Field_UU,IsDisplayedGrid,SeqNoGrid,ColumnSpan) VALUES (207620,'Record UUID',487,215835,'Y',36,190,'N','N','N','N',0,0,'Y',TO_TIMESTAMP('2023-04-15 18:34:50','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-04-15 18:34:50','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','dab3415a-c850-401f-8b9a-891e60e2999e','Y',190,2)
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:45 PM CEST
|
||||
UPDATE AD_Field SET IsDisplayed='Y', SeqNo=100, XPosition=4,Updated=TO_TIMESTAMP('2023-04-15 18:35:45','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=207619
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:45 PM CEST
|
||||
UPDATE AD_Field SET IsDisplayed='Y', SeqNo=110, XPosition=1,Updated=TO_TIMESTAMP('2023-04-15 18:35:45','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=6779
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:45 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=120,Updated=TO_TIMESTAMP('2023-04-15 18:35:45','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=6774
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:45 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=130,Updated=TO_TIMESTAMP('2023-04-15 18:35:45','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=10946
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:45 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=140,Updated=TO_TIMESTAMP('2023-04-15 18:35:45','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=54397
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:45 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=150,Updated=TO_TIMESTAMP('2023-04-15 18:35:45','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=6780
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:45 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=160,Updated=TO_TIMESTAMP('2023-04-15 18:35:45','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=6773
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:45 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=170,Updated=TO_TIMESTAMP('2023-04-15 18:35:45','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=12356
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:45 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=180,Updated=TO_TIMESTAMP('2023-04-15 18:35:45','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=10948
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:45 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=190,Updated=TO_TIMESTAMP('2023-04-15 18:35:45','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=10947
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:45 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=0,Updated=TO_TIMESTAMP('2023-04-15 18:35:45','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=204473
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:59 PM CEST
|
||||
UPDATE AD_Field SET IsDisplayed='Y', SeqNo=100, XPosition=4,Updated=TO_TIMESTAMP('2023-04-15 18:35:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=207620
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:59 PM CEST
|
||||
UPDATE AD_Field SET IsDisplayed='Y', SeqNo=110, XPosition=1,Updated=TO_TIMESTAMP('2023-04-15 18:35:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=6769
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:59 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=120,Updated=TO_TIMESTAMP('2023-04-15 18:35:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=6764
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:59 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=130,Updated=TO_TIMESTAMP('2023-04-15 18:35:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=10949
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:59 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=140,Updated=TO_TIMESTAMP('2023-04-15 18:35:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=54396
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:59 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=150,Updated=TO_TIMESTAMP('2023-04-15 18:35:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=6770
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:59 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=160,Updated=TO_TIMESTAMP('2023-04-15 18:35:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=6763
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:59 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=170,Updated=TO_TIMESTAMP('2023-04-15 18:35:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=12357
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:59 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=180,Updated=TO_TIMESTAMP('2023-04-15 18:35:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=10951
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:59 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=190,Updated=TO_TIMESTAMP('2023-04-15 18:35:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=10950
|
||||
;
|
||||
|
||||
-- Apr 15, 2023, 6:35:59 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=0,Updated=TO_TIMESTAMP('2023-04-15 18:35:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=204474
|
||||
;
|
||||
|
||||
-- May 21, 2023, 4:07:46 PM CEST
|
||||
UPDATE AD_Field SET DisplayLogic='@AD_Reference_ID@=19 | @AD_Reference_ID@=30 | @AD_Reference_ID@=18 | @AD_Reference_ID@=21 | @AD_Reference_ID@=25 | @AD_Reference_ID@=31 | @AD_Reference_ID@=35 | @AD_Reference_ID@=33 | @AD_Reference_ID@=32 | @AD_Reference_ID@=53370 | @AD_Reference_ID@=200233 | @AD_Reference_ID@=200234 | @AD_Reference_ID@=200235 | @AD_Reference_ID@=200202 | @AD_Reference_ID@=200240',Updated=TO_TIMESTAMP('2023-05-21 16:07:46','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=202519
|
||||
;
|
||||
|
||||
-- May 21, 2023, 4:13:15 PM CEST
|
||||
UPDATE AD_Val_Rule SET Code='(
|
||||
AD_Ref_List.Value = ''D''
|
||||
/* Cascade/SetNull/Forbid supported for all DB constraints */
|
||||
OR (AD_Ref_List.Value IN (''C'',''S'',''N'') AND @AD_Reference_ID@ IN (18,19,21,25,30,31,32,33,35,53370,200233,200234,200235))
|
||||
/* ModelCascade supported for Table/TableDir/Search/RecordID */
|
||||
OR (AD_Ref_List.Value = ''M'' AND @AD_Reference_ID@ IN (18,19,30,200202,200240))
|
||||
/* ModelSetNull/ModelForbid supported for RecordID */
|
||||
OR (AD_Ref_List.Value IN (''T'',''O'') AND @AD_Reference_ID@ IN (200202,200240))
|
||||
)',Updated=TO_TIMESTAMP('2023-05-21 16:13:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Val_Rule_ID=200064
|
||||
;
|
||||
|
||||
-- May 21, 2023, 4:14:25 PM CEST
|
||||
UPDATE AD_Column SET FieldLength=36, FKConstraintType='D',Updated=TO_TIMESTAMP('2023-05-21 16:14:25','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=215833
|
||||
;
|
||||
|
||||
-- May 22, 2023, 5:37:16 PM CEST
|
||||
INSERT INTO AD_SysConfig (AD_SysConfig_ID,AD_Client_ID,AD_Org_ID,Created,Updated,CreatedBy,UpdatedBy,IsActive,Name,Value,Description,EntityType,ConfigurationLevel,AD_SysConfig_UU) VALUES (200228,0,0,TO_TIMESTAMP('2023-05-22 17:37:15','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2023-05-22 17:37:15','YYYY-MM-DD HH24:MI:SS'),100,100,'Y','AD_CHANGELOG_SAVE_UUID','B','Save the AD_ChangeLog.Record_UU -> B | Just for UUID based tables , A | Always , U | just UUID not ID','D','S','32161230-22c9-43eb-a327-f3b4841eeace')
|
||||
;
|
||||
|
||||
-- May 23, 2023, 5:17:25 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,IsKey) VALUES (0,0,201247,'d0ab3ee4-418c-42e9-acfe-618750685bcc',TO_TIMESTAMP('2023-05-23 17:17:24','YYYY-MM-DD HH24:MI:SS'),100,'D','Y','ad_changelog_record_uu',TO_TIMESTAMP('2023-05-23 17:17:24','YYYY-MM-DD HH24:MI:SS'),100,580,'N','N','N','N')
|
||||
;
|
||||
|
||||
-- May 23, 2023, 5:17:48 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,201686,'6ce73812-0b30-4145-a9c5-ab1c73d4c386',TO_TIMESTAMP('2023-05-23 17:17:47','YYYY-MM-DD HH24:MI:SS'),100,'D','Y',TO_TIMESTAMP('2023-05-23 17:17:47','YYYY-MM-DD HH24:MI:SS'),100,215835,201247,10)
|
||||
;
|
||||
|
||||
-- May 23, 2023, 5:17:53 PM CEST
|
||||
CREATE INDEX ad_changelog_record_uu ON AD_ChangeLog (Record_UU)
|
||||
;
|
||||
|
||||
/*
|
||||
-- Set Record_UU for existing records
|
||||
DO $$
|
||||
DECLARE
|
||||
cmd varchar(2000);
|
||||
r record;
|
||||
v_cnt numeric;
|
||||
BEGIN
|
||||
FOR r IN
|
||||
SELECT DISTINCT t.TableName, cl.AD_Table_ID
|
||||
FROM AD_ChangeLog cl
|
||||
JOIN AD_Table t ON (cl.AD_Table_ID=t.AD_Table_ID)
|
||||
WHERE cl.Record_UU IS NULL
|
||||
AND cl.Record_ID IS NOT NULL
|
||||
AND cl.EventChangeLog!='D'
|
||||
LOOP
|
||||
cmd := 'UPDATE AD_ChangeLog SET Record_UU=(SELECT '
|
||||
|| r.TableName
|
||||
|| '_UU FROM '
|
||||
|| r.TableName
|
||||
|| ' WHERE '
|
||||
|| r.TableName
|
||||
|| '_ID=AD_ChangeLog.Record_ID) WHERE AD_Table_ID='
|
||||
|| r.AD_Table_ID
|
||||
|| ' AND Record_ID IS NOT NULL AND Record_UU IS NULL AND EventChangeLog!=''D''';
|
||||
EXECUTE cmd;
|
||||
GET DIAGNOSTICS v_cnt = ROW_COUNT;
|
||||
RAISE NOTICE '% AD_ChangeLog.Record_UU set in %', v_cnt, r.TableName;
|
||||
END LOOP;
|
||||
END;
|
||||
$$
|
||||
;
|
||||
*/
|
||||
|
|
@ -113,7 +113,7 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable
|
|||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 2604313946261586651L;
|
||||
private static final long serialVersionUID = 4674027561845549215L;
|
||||
|
||||
public static final String DEFAULT_STATUS_MESSAGE = "NavigateOrUpdate";
|
||||
|
||||
|
@ -2437,6 +2437,16 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable
|
|||
return m_mTable.getKeyID(m_currentRow);
|
||||
} // getRecord_ID
|
||||
|
||||
/**
|
||||
* Get Current Table UUID
|
||||
* @return Record_UU
|
||||
*/
|
||||
public String getRecord_UU()
|
||||
{
|
||||
UUID uuid = m_mTable.getUUID(m_currentRow);
|
||||
return (uuid == null ? null : uuid.toString());
|
||||
} // getRecord_UU
|
||||
|
||||
/**
|
||||
* Get Key ID of row
|
||||
* @param row row number
|
||||
|
|
|
@ -236,6 +236,15 @@ public interface I_AD_ChangeLog
|
|||
*/
|
||||
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 Redo */
|
||||
public static final String COLUMNNAME_Redo = "Redo";
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import java.util.logging.Level;
|
|||
|
||||
import org.compiere.util.CLogger;
|
||||
import org.compiere.util.DB;
|
||||
import org.compiere.util.Util;
|
||||
|
||||
/**
|
||||
* Change Log Model
|
||||
|
@ -37,7 +38,7 @@ public class MChangeLog extends X_AD_ChangeLog
|
|||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 7262833610411402160L;
|
||||
private static final long serialVersionUID = 3082084206319959526L;
|
||||
|
||||
/**
|
||||
* Do we track changes for this table
|
||||
|
@ -170,6 +171,33 @@ public class MChangeLog extends X_AD_ChangeLog
|
|||
int AD_Table_ID, int AD_Column_ID, int Record_ID,
|
||||
int AD_Client_ID, int AD_Org_ID,
|
||||
Object OldValue, Object NewValue, String event)
|
||||
{
|
||||
this(ctx, AD_ChangeLog_ID, TrxName, AD_Session_ID,
|
||||
AD_Table_ID, AD_Column_ID, Record_ID, null,
|
||||
AD_Client_ID, AD_Org_ID,
|
||||
OldValue, NewValue, event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Full Constructor
|
||||
* @param ctx context
|
||||
* @param AD_ChangeLog_ID 0 for new change log
|
||||
* @param TrxName transaction
|
||||
* @param AD_Session_ID session
|
||||
* @param AD_Table_ID table
|
||||
* @param AD_Column_ID column
|
||||
* @param Record_ID record
|
||||
* @param Record_UU record UUID
|
||||
* @param AD_Client_ID client
|
||||
* @param AD_Org_ID org
|
||||
* @param OldValue old
|
||||
* @param NewValue new
|
||||
*/
|
||||
public MChangeLog (Properties ctx,
|
||||
int AD_ChangeLog_ID, String TrxName, int AD_Session_ID,
|
||||
int AD_Table_ID, int AD_Column_ID, int Record_ID, String Record_UU,
|
||||
int AD_Client_ID, int AD_Org_ID,
|
||||
Object OldValue, Object NewValue, String event)
|
||||
{
|
||||
this (ctx, 0, TrxName);
|
||||
if (AD_ChangeLog_ID == 0)
|
||||
|
@ -184,7 +212,16 @@ public class MChangeLog extends X_AD_ChangeLog
|
|||
//
|
||||
setAD_Table_ID (AD_Table_ID);
|
||||
setAD_Column_ID (AD_Column_ID);
|
||||
String saveUUID = MSysConfig.getValue(MSysConfig.AD_CHANGELOG_SAVE_UUID, "B");
|
||||
// B - just based UUID tables (default)
|
||||
// A - always
|
||||
// U - just UUID, not ID
|
||||
if (Record_ID > 0 && (!"U".equals(saveUUID) || Util.isEmpty(Record_UU))) {
|
||||
setRecord_ID (Record_ID);
|
||||
}
|
||||
if ("U".equals(saveUUID) || "A".equals(saveUUID) || ("B".equals(saveUUID) && (Record_ID <= 0 || MTable.get(AD_Table_ID).isUUIDKeyTable()))) {
|
||||
setRecord_UU (Record_UU);
|
||||
}
|
||||
//
|
||||
setClientOrg (AD_Client_ID, AD_Org_ID);
|
||||
//
|
||||
|
|
|
@ -82,7 +82,7 @@ public final class MLookup extends Lookup implements Serializable
|
|||
}
|
||||
|
||||
// Don't load Search or CreatedBy/UpdatedBy
|
||||
if (m_info.DisplayType == DisplayType.Search
|
||||
if (m_info.DisplayType == DisplayType.Search || m_info.DisplayType == DisplayType.SearchUU
|
||||
|| m_info.IsCreadedUpdatedBy)
|
||||
return;
|
||||
// Don't load Parents/Keys
|
||||
|
|
|
@ -46,8 +46,7 @@ public class MSession extends X_AD_Session implements ImmutablePOSupport
|
|||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 480745219310430126L;
|
||||
|
||||
private static final long serialVersionUID = -5836154187760734691L;
|
||||
|
||||
/**
|
||||
* Get existing or create local session
|
||||
|
@ -323,7 +322,7 @@ public class MSession extends X_AD_Session implements ImmutablePOSupport
|
|||
Object OldValue, Object NewValue)
|
||||
{
|
||||
return changeLog(TrxName, AD_ChangeLog_ID, AD_Table_ID, AD_Column_ID,
|
||||
Record_ID, AD_Client_ID, AD_Org_ID, OldValue, NewValue,
|
||||
Record_ID, null, AD_Client_ID, AD_Org_ID, OldValue, NewValue,
|
||||
(String) null);
|
||||
} // changeLog
|
||||
|
||||
|
@ -345,6 +344,31 @@ public class MSession extends X_AD_Session implements ImmutablePOSupport
|
|||
int AD_Table_ID, int AD_Column_ID, int Record_ID,
|
||||
int AD_Client_ID, int AD_Org_ID,
|
||||
Object OldValue, Object NewValue, String event)
|
||||
{
|
||||
return changeLog(TrxName, AD_ChangeLog_ID, AD_Table_ID, AD_Column_ID,
|
||||
Record_ID, null, AD_Client_ID, AD_Org_ID, OldValue, NewValue,
|
||||
(String) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Change Log only if table is logged
|
||||
* @param TrxName transaction name
|
||||
* @param AD_ChangeLog_ID 0 for new change log
|
||||
* @param AD_Table_ID table
|
||||
* @param AD_Column_ID column
|
||||
* @param Record_ID record
|
||||
* @param Record_UU record UUID
|
||||
* @param AD_Client_ID client
|
||||
* @param AD_Org_ID org
|
||||
* @param OldValue old
|
||||
* @param NewValue new
|
||||
* @return saved change log or null
|
||||
*/
|
||||
public MChangeLog changeLog (
|
||||
String TrxName, int AD_ChangeLog_ID,
|
||||
int AD_Table_ID, int AD_Column_ID, int Record_ID, String Record_UU,
|
||||
int AD_Client_ID, int AD_Org_ID,
|
||||
Object OldValue, Object NewValue, String event)
|
||||
{
|
||||
// Null handling
|
||||
if (OldValue == null && NewValue == null)
|
||||
|
@ -372,7 +396,7 @@ public class MSession extends X_AD_Session implements ImmutablePOSupport
|
|||
PO.setCrossTenantSafe();
|
||||
MChangeLog cl = new MChangeLog(getCtx(),
|
||||
AD_ChangeLog_ID, TrxName, getAD_Session_ID(),
|
||||
AD_Table_ID, AD_Column_ID, Record_ID, AD_Client_ID, AD_Org_ID,
|
||||
AD_Table_ID, AD_Column_ID, Record_ID, Record_UU, AD_Client_ID, AD_Org_ID,
|
||||
OldValue, NewValue, event);
|
||||
if (cl.save())
|
||||
return cl;
|
||||
|
|
|
@ -44,8 +44,9 @@ public class MSysConfig extends X_AD_SysConfig
|
|||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -1169550637760344445L;
|
||||
private static final long serialVersionUID = 1700160594551368619L;
|
||||
|
||||
public static final String AD_CHANGELOG_SAVE_UUID = "AD_CHANGELOG_SAVE_UUID";
|
||||
public static final String ADDRESS_VALIDATION = "ADDRESS_VALIDATION";
|
||||
public static final String ALERT_SEND_ATTACHMENT_AS_XLS = "ALERT_SEND_ATTACHMENT_AS_XLS";
|
||||
public static final String ALLOCATION_DESCRIPTION = "ALLOCATION_DESCRIPTION";
|
||||
|
@ -85,11 +86,11 @@ public class MSysConfig extends X_AD_SysConfig
|
|||
public static final String CHECK_CREDIT_ON_PREPAY_ORDER = "CHECK_CREDIT_ON_PREPAY_ORDER";
|
||||
public static final String CLIENT_ACCOUNTING = "CLIENT_ACCOUNTING";
|
||||
public static final String DASHBOARD_LAYOUT_ORIENTATION = "DASHBOARD_LAYOUT_ORIENTATION";
|
||||
public static final String DEFAULT_COA_PATH = "DEFAULT_COA_PATH";
|
||||
public static final String DEFAULT_ENTITYTYPE = "DEFAULT_ENTITYTYPE"; // used as default in entity type columns with get_sysconfig
|
||||
public static final String DB_READ_REPLICA_NORMAL_MAX_ITERATIONS = "DB_READ_REPLICA_NORMAL_MAX_ITERATIONS";
|
||||
public static final String DB_READ_REPLICA_NORMAL_TIMEOUT_IN_MILLISECONDS = "DB_READ_REPLICA_NORMAL_TIMEOUT_IN_MILLISECONDS";
|
||||
public static final String DB_READ_REPLICA_URLS = "DB_READ_REPLICA_URLS";
|
||||
public static final String DEFAULT_COA_PATH = "DEFAULT_COA_PATH";
|
||||
public static final String DEFAULT_ENTITYTYPE = "DEFAULT_ENTITYTYPE"; // used as default in entity type columns with get_sysconfig
|
||||
public static final String DICTIONARY_ID_PASSWORD = "DICTIONARY_ID_PASSWORD";
|
||||
public static final String DICTIONARY_ID_USE_CENTRALIZED_ID = "DICTIONARY_ID_USE_CENTRALIZED_ID";
|
||||
public static final String DICTIONARY_ID_USER = "DICTIONARY_ID_USER";
|
||||
|
@ -144,10 +145,10 @@ public class MSysConfig extends X_AD_SysConfig
|
|||
public static final String MESSAGES_AT_TENANT_LEVEL = "MESSAGES_AT_TENANT_LEVEL";
|
||||
public static final String MFA_NTP_TIMEOUT_IN_MILLISECONDS = "MFA_NTP_TIMEOUT_IN_MILLISECONDS";
|
||||
public static final String MFA_REGISTERED_DEVICE_EXPIRATION_DAYS = "MFA_REGISTERED_DEVICE_EXPIRATION_DAYS";
|
||||
public static final String MONITOR_INITIAL_WAIT_FOR_CLUSTER_IN_SECONDS = "MONITOR_INITIAL_WAIT_FOR_CLUSTER_IN_SECONDS";
|
||||
public static final String MONITOR_MAX_WAIT_FOR_CLUSTER_IN_SECONDS = "MONITOR_MAX_WAIT_FOR_CLUSTER_IN_SECONDS";
|
||||
public static final String MFG_ValidateCostsDifferenceOnCreate = "MFG_ValidateCostsDifferenceOnCreate";
|
||||
public static final String MFG_ValidateCostsOnCreate = "MFG_ValidateCostsOnCreate";
|
||||
public static final String MONITOR_INITIAL_WAIT_FOR_CLUSTER_IN_SECONDS = "MONITOR_INITIAL_WAIT_FOR_CLUSTER_IN_SECONDS";
|
||||
public static final String MONITOR_MAX_WAIT_FOR_CLUSTER_IN_SECONDS = "MONITOR_MAX_WAIT_FOR_CLUSTER_IN_SECONDS";
|
||||
public static final String MSEQUENCE_GETNEXT_TIMEOUT = "MSEQUENCE_GETNEXT_TIMEOUT";
|
||||
public static final String PAYMENT_OVERWRITE_DOCUMENTNO_WITH_CHECK_ON_PAYMENT = "PAYMENT_OVERWRITE_DOCUMENTNO_WITH_CHECK_ON_PAYMENT";
|
||||
public static final String PAYMENT_OVERWRITE_DOCUMENTNO_WITH_CHECK_ON_RECEIPT = "PAYMENT_OVERWRITE_DOCUMENTNO_WITH_CHECK_ON_RECEIPT";
|
||||
|
@ -242,8 +243,8 @@ public class MSysConfig extends X_AD_SysConfig
|
|||
public static final String ZK_SEARCH_AUTO_COMPLETE_MAX_ROWS = "ZK_SEARCH_AUTO_COMPLETE_MAX_ROWS";
|
||||
public static final String ZK_SEQ_DEFAULT_VALUE_PANEL = "ZK_SEQ_DEFAULT_VALUE_PANEL";
|
||||
public static final String ZK_SESSION_TIMEOUT_IN_SECONDS = "ZK_SESSION_TIMEOUT_IN_SECONDS";
|
||||
public static final String ZK_THEME_USE_FONT_ICON_FOR_IMAGE = "ZK_THEME_USE_FONT_ICON_FOR_IMAGE";
|
||||
public static final String ZK_THEME = "ZK_THEME";
|
||||
public static final String ZK_THEME_USE_FONT_ICON_FOR_IMAGE = "ZK_THEME_USE_FONT_ICON_FOR_IMAGE";
|
||||
public static final String ZK_TOOLBAR_SHOW_MORE_VERTICAL = "ZK_TOOLBAR_SHOW_MORE_VERTICAL";
|
||||
public static final String ZK_USE_PDF_JS_VIEWER = "ZK_USE_PDF_JS_VIEWER";
|
||||
public static final String ZOOM_ACROSS_QUERY_TIMEOUT = "ZOOM_ACROSS_QUERY_TIMEOUT";
|
||||
|
|
|
@ -878,6 +878,7 @@ public class MTable extends X_AD_Table implements ImmutablePOSupport
|
|||
return (tablename.equals("AD_Org") ||
|
||||
tablename.equals("AD_OrgInfo") ||
|
||||
tablename.equals("AD_Client") || // IDEMPIERE-668
|
||||
tablename.equals("AD_ClientInfo") ||
|
||||
tablename.equals("AD_AllClients_V") ||
|
||||
tablename.equals("AD_ReportView") ||
|
||||
tablename.equals("AD_Role") ||
|
||||
|
|
|
@ -2336,11 +2336,6 @@ public abstract class PO
|
|||
*/
|
||||
public boolean save()
|
||||
{
|
||||
checkImmutable();
|
||||
|
||||
checkValidContext();
|
||||
checkCrossTenant(true);
|
||||
checkRecordIDCrossTenant();
|
||||
CLogger.resetLast();
|
||||
boolean newRecord = is_new(); // save locally as load resets
|
||||
if (!newRecord && !is_Changed())
|
||||
|
@ -2349,6 +2344,12 @@ public abstract class PO
|
|||
return true;
|
||||
}
|
||||
|
||||
checkImmutable();
|
||||
checkValidContext();
|
||||
checkCrossTenant(true);
|
||||
checkRecordIDCrossTenant();
|
||||
checkRecordUUCrossTenant();
|
||||
|
||||
if (m_setErrorsFilled) {
|
||||
for (int i = 0; i < m_setErrors.length; i++) {
|
||||
ValueNamePair setError = m_setErrors[i];
|
||||
|
@ -2830,6 +2831,18 @@ public abstract class PO
|
|||
log.fine("No Session found");
|
||||
int AD_ChangeLog_ID = 0;
|
||||
|
||||
//uuid secondary key - when updating, if the record doesn't have UUID, assign one
|
||||
int uuidIndex = p_info.getColumnIndex(getUUIDColumnName());
|
||||
if (uuidIndex >= 0)
|
||||
{
|
||||
String value = (String)get_Value(uuidIndex);
|
||||
if (p_info.getColumn(uuidIndex).FieldLength == 36 && (value == null || value.length() == 0))
|
||||
{
|
||||
UUID uuid = UUID.randomUUID();
|
||||
set_ValueNoCheck(p_info.getColumnName(uuidIndex), uuid.toString());
|
||||
}
|
||||
}
|
||||
|
||||
int size = get_ColumnCount();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
|
@ -3009,7 +3022,6 @@ public abstract class PO
|
|||
|
||||
// Change Log - Only
|
||||
if (session != null
|
||||
&& m_IDs.length == 1
|
||||
&& p_info.isAllowLogging(i) // logging allowed
|
||||
&& !p_info.isEncrypted(i) // not encrypted
|
||||
&& !p_info.isVirtualColumn(i) // no virtual column
|
||||
|
@ -3026,7 +3038,7 @@ public abstract class PO
|
|||
MChangeLog cLog = session.changeLog (
|
||||
m_trxName, AD_ChangeLog_ID,
|
||||
p_info.getAD_Table_ID(), p_info.getColumn(i).AD_Column_ID,
|
||||
get_ID(), getAD_Client_ID(), getAD_Org_ID(), oldV, newV, MChangeLog.EVENTCHANGELOG_Update);
|
||||
(m_IDs.length == 1 ? get_ID() : 0), get_UUID(), getAD_Client_ID(), getAD_Org_ID(), oldV, newV, MChangeLog.EVENTCHANGELOG_Update);
|
||||
if (cLog != null)
|
||||
AD_ChangeLog_ID = cLog.getAD_ChangeLog_ID();
|
||||
}
|
||||
|
@ -3355,29 +3367,33 @@ public abstract class PO
|
|||
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()));
|
||||
StringBuilder sql = new StringBuilder("SELECT ").append(m_KeyColumns[0]).append(" FROM ").append(p_info.getTableName()).append(" WHERE ").append(getUUIDColumnName()).append("=?");
|
||||
int id = DB.getSQLValueEx(get_TrxName(), sql.toString(), get_ValueAsString(getUUIDColumnName()));
|
||||
m_IDs[0] = Integer.valueOf(id);
|
||||
set_ValueNoCheck(m_KeyColumns[0], m_IDs[0]);
|
||||
}
|
||||
|
||||
if (!Env.isUseCentralizedId(p_info.getTableName()))
|
||||
{
|
||||
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))
|
||||
)
|
||||
&& ( insertLog.equalsIgnoreCase("Y")
|
||||
|| ( insertLog.equalsIgnoreCase("K")
|
||||
&& ( p_info.getColumn(ki).IsKey
|
||||
|| p_info.getColumn(ki).ColumnName.equals(PO.getUUIDColumnName(p_info.getTableName()))))))
|
||||
{
|
||||
int id = (m_IDs.length == 1 ? get_ID() : 0);
|
||||
// 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);
|
||||
(m_IDs.length == 1 ? get_ID() : 0), get_UUID(), getAD_Client_ID(), getAD_Org_ID(), null, (id == 0 ? get_UUID() : id), MChangeLog.EVENTCHANGELOG_Insert);
|
||||
if (cLog != null)
|
||||
AD_ChangeLog_ID = cLog.getAD_ChangeLog_ID();
|
||||
}
|
||||
|
@ -3637,7 +3653,6 @@ public abstract class PO
|
|||
// Change Log - Only
|
||||
String insertLog = MSysConfig.getValue(MSysConfig.SYSTEM_INSERT_CHANGELOG, "Y", getAD_Client_ID());
|
||||
if (!generateScriptOnly && session != null
|
||||
&& m_IDs.length == 1
|
||||
&& p_info.isAllowLogging(i) // logging allowed
|
||||
&& !p_info.isEncrypted(i) // not encrypted
|
||||
&& !p_info.isVirtualColumn(i) // no virtual column
|
||||
|
@ -3650,7 +3665,7 @@ public abstract class PO
|
|||
MChangeLog cLog = session.changeLog (
|
||||
m_trxName, AD_ChangeLog_ID,
|
||||
p_info.getAD_Table_ID(), p_info.getColumn(i).AD_Column_ID,
|
||||
get_ID(), getAD_Client_ID(), getAD_Org_ID(), null, value, MChangeLog.EVENTCHANGELOG_Insert);
|
||||
(m_IDs.length == 1 ? get_ID() : 0), get_UUID(), getAD_Client_ID(), getAD_Org_ID(), null, value, MChangeLog.EVENTCHANGELOG_Insert);
|
||||
if (cLog != null)
|
||||
AD_ChangeLog_ID = cLog.getAD_ChangeLog_ID();
|
||||
}
|
||||
|
@ -3843,16 +3858,17 @@ public abstract class PO
|
|||
*/
|
||||
public boolean delete (boolean force)
|
||||
{
|
||||
checkImmutable();
|
||||
|
||||
checkValidContext();
|
||||
checkCrossTenant(true);
|
||||
CLogger.resetLast();
|
||||
if (is_new())
|
||||
return true;
|
||||
|
||||
checkImmutable();
|
||||
checkValidContext();
|
||||
checkCrossTenant(true);
|
||||
|
||||
int AD_Table_ID = p_info.getAD_Table_ID();
|
||||
int Record_ID = get_ID();
|
||||
String Record_UU = get_UUID();
|
||||
|
||||
if (!force)
|
||||
{
|
||||
|
@ -3951,6 +3967,8 @@ public abstract class PO
|
|||
}
|
||||
// Delete Restrict AD_Table_ID/Record_ID (Requests, ..)
|
||||
String errorMsg = PO_Record.exists(AD_Table_ID, Record_ID, m_trxName);
|
||||
if (errorMsg == null && Record_UU != null)
|
||||
errorMsg = PO_Record.exists(AD_Table_ID, Record_UU, m_trxName);
|
||||
if (errorMsg != null)
|
||||
{
|
||||
log.saveError("CannotDelete", errorMsg);
|
||||
|
@ -4000,9 +4018,14 @@ public abstract class PO
|
|||
//delete cascade only for single key column record
|
||||
PO_Record.deleteModelCascade(p_info.getTableName(), Record_ID, localTrxName);
|
||||
// Delete Cascade AD_Table_ID/Record_ID (Attachments, ..)
|
||||
PO_Record.deleteRecordIdCascade(AD_Table_ID, Record_ID, localTrxName);
|
||||
PO_Record.deleteRecordCascade(AD_Table_ID, Record_ID, localTrxName);
|
||||
// Set referencing Record_ID Null AD_Table_ID/Record_ID
|
||||
PO_Record.setRecordIdNull(AD_Table_ID, Record_ID, localTrxName);
|
||||
PO_Record.setRecordNull(AD_Table_ID, Record_ID, localTrxName);
|
||||
}
|
||||
if (Record_UU != null) {
|
||||
PO_Record.deleteModelCascade(p_info.getTableName(), Record_UU, localTrxName);
|
||||
PO_Record.deleteRecordCascade(AD_Table_ID, Record_UU, localTrxName);
|
||||
PO_Record.setRecordNull(AD_Table_ID, Record_UU, localTrxName);
|
||||
}
|
||||
|
||||
// The Delete Statement
|
||||
|
@ -4082,7 +4105,7 @@ public abstract class PO
|
|||
MChangeLog cLog = session.changeLog (
|
||||
m_trxName != null ? m_trxName : localTrxName, AD_ChangeLog_ID,
|
||||
AD_Table_ID, p_info.getColumn(i).AD_Column_ID,
|
||||
Record_ID, getAD_Client_ID(), getAD_Org_ID(), value, null, MChangeLog.EVENTCHANGELOG_Delete);
|
||||
(m_IDs.length == 1 ? Record_ID : 0), Record_UU, getAD_Client_ID(), getAD_Org_ID(), value, null, MChangeLog.EVENTCHANGELOG_Delete);
|
||||
if (cLog != null)
|
||||
AD_ChangeLog_ID = cLog.getAD_ChangeLog_ID();
|
||||
}
|
||||
|
@ -5765,6 +5788,52 @@ public abstract class PO
|
|||
throw new AdempiereException("Cross tenant ID " + recordId + " not allowed in " + ft.getTableName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify Foreign key based on AD_Table_ID+Record_UU for cross tenant
|
||||
* @return true if all the foreign keys are valid
|
||||
*/
|
||||
private void checkRecordUUCrossTenant() {
|
||||
if (isSafeCrossTenant.get())
|
||||
return;
|
||||
int idxRecordUU = p_info.getColumnIndex("Record_UU");
|
||||
if (idxRecordUU < 0)
|
||||
return;
|
||||
int idxTableId = p_info.getColumnIndex("AD_Table_ID");
|
||||
if (idxTableId < 0)
|
||||
return;
|
||||
if ( ! (is_new() || is_ValueChanged(idxTableId) || is_ValueChanged(idxRecordUU)))
|
||||
return;
|
||||
int tableId = get_ValueAsInt(idxTableId);
|
||||
if (tableId <= 0)
|
||||
return;
|
||||
String recordUU = get_ValueAsString(idxRecordUU);
|
||||
if (Util.isEmpty(recordUU))
|
||||
return;
|
||||
MTable ft = MTable.get(getCtx(), tableId);
|
||||
if (!ft.hasUUIDKey())
|
||||
return; // no UUID key in table
|
||||
boolean systemAccess = false;
|
||||
String accessLevel = ft.getAccessLevel();
|
||||
if ( MTable.ACCESSLEVEL_All.equals(accessLevel)
|
||||
|| MTable.ACCESSLEVEL_SystemOnly.equals(accessLevel)
|
||||
|| MTable.ACCESSLEVEL_SystemPlusClient.equals(accessLevel)) {
|
||||
systemAccess = true;
|
||||
}
|
||||
StringBuilder sql = new StringBuilder("SELECT AD_Client_ID FROM ")
|
||||
.append(ft.getTableName())
|
||||
.append(" WHERE ")
|
||||
.append(PO.getUUIDColumnName(ft.getTableName()))
|
||||
.append("=?");
|
||||
int pocid = DB.getSQLValue(get_TrxName(), sql.toString(), recordUU);
|
||||
if (pocid < 0)
|
||||
throw new AdempiereException("Foreign UUID " + recordUU + " not found in " + ft.getTableName());
|
||||
if (pocid == 0 && !systemAccess)
|
||||
throw new AdempiereException("System UUID " + recordUU + " cannot be used in " + ft.getTableName());
|
||||
int curcid = getAD_Client_ID();
|
||||
if (pocid > 0 && pocid != curcid)
|
||||
throw new AdempiereException("Cross tenant UUID " + recordUU + " not allowed in " + ft.getTableName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of indexes for the foreign columns, null if none
|
||||
* @return array of int indexes
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
*****************************************************************************/
|
||||
package org.compiere.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
@ -39,92 +40,73 @@ public class PO_Record
|
|||
/* Cache for arrays of KeyNamePair<AD_Table_ID, TableName> for types of deletion: Cascade, Set Null, No Action */
|
||||
private static final CCache<String, KeyNamePair[]> s_po_record_tables_cache = new CCache<>(null, "PORecordTables", 100, 120, false);
|
||||
|
||||
/** Parent Tables */
|
||||
private static int[] s_parents = new int[]{
|
||||
X_C_Order.Table_ID
|
||||
};
|
||||
private static String[] s_parentNames = new String[]{
|
||||
X_C_Order.Table_Name
|
||||
};
|
||||
private static int[] s_parentChilds = new int[]{
|
||||
X_C_OrderLine.Table_ID
|
||||
};
|
||||
private static String[] s_parentChildNames = new String[]{
|
||||
X_C_OrderLine.Table_Name
|
||||
};
|
||||
|
||||
/** Logger */
|
||||
private static CLogger log = CLogger.getCLogger (PO_Record.class);
|
||||
|
||||
/**
|
||||
* Delete Cascade including (selected)parent relationships
|
||||
* @param AD_Table_ID table
|
||||
* @param Record_ID record
|
||||
* @param Record_IDorUU record ID (int) or UUID (String)
|
||||
* @param trxName transaction
|
||||
* @return false if could not be deleted
|
||||
*/
|
||||
static boolean deleteRecordIdCascade (int AD_Table_ID, int Record_ID, String trxName)
|
||||
protected static boolean deleteRecordCascade (int AD_Table_ID, Serializable Record_IDorUU, String trxName)
|
||||
{
|
||||
KeyNamePair[] cascades = getTablesWithRecordIDColumn(MColumn.FKCONSTRAINTTYPE_ModelCascade, trxName);
|
||||
int refId;
|
||||
String columnName;
|
||||
if (Record_IDorUU instanceof Integer) {
|
||||
refId = DisplayType.RecordID;
|
||||
columnName = "Record_ID";
|
||||
} else if (Record_IDorUU instanceof String) {
|
||||
refId = DisplayType.RecordUU;
|
||||
columnName = "Record_UU";
|
||||
} else {
|
||||
throw new IllegalArgumentException(Record_IDorUU.getClass().getName() + " not supported for ID/UUID");
|
||||
}
|
||||
KeyNamePair[] cascades = getTablesWithConstraintType(refId, MColumn.FKCONSTRAINTTYPE_ModelCascade, trxName);
|
||||
// Table Loop
|
||||
StringBuilder whereClause = new StringBuilder("AD_Table_ID=? AND ").append(columnName).append("=?");
|
||||
for (KeyNamePair table : cascades)
|
||||
{
|
||||
// DELETE FROM table WHERE AD_Table_ID=#1 AND Record_ID=#2
|
||||
List<PO> poList = new Query(Env.getCtx(), table.getName(), "AD_Table_ID=? AND Record_ID=?", trxName)
|
||||
.setParameters(AD_Table_ID, Record_ID)
|
||||
List<PO> poList = new Query(Env.getCtx(), table.getName(), whereClause.toString(), trxName)
|
||||
.setParameters(AD_Table_ID, Record_IDorUU)
|
||||
.list();
|
||||
|
||||
int count = 0;
|
||||
for(PO po : poList)
|
||||
{
|
||||
if (po.get_Table_ID() == AD_Table_ID && po.get_ID() == Record_ID)
|
||||
if ( po.get_Table_ID() == AD_Table_ID
|
||||
&& ( (Record_IDorUU instanceof Integer && po.get_ID() == (Integer)Record_IDorUU)
|
||||
|| (Record_IDorUU instanceof String && Record_IDorUU.equals(po.get_UUID()))
|
||||
)
|
||||
)
|
||||
continue;
|
||||
po.deleteEx(true);
|
||||
count++;
|
||||
}
|
||||
if (count > 0)
|
||||
if (log.isLoggable(Level.CONFIG)) log.config(table.getName() + " (" + AD_Table_ID + "/" + Record_ID + ") #" + count);
|
||||
}
|
||||
// Parent Loop
|
||||
for (int i = 0; i < s_parents.length; i++)
|
||||
{
|
||||
if (s_parents[i] == AD_Table_ID)
|
||||
{
|
||||
int AD_Table_IDchild = s_parentChilds[i];
|
||||
for (KeyNamePair table : cascades)
|
||||
{
|
||||
String whereClause = " AD_Table_ID=? AND Record_ID IN (SELECT "
|
||||
+ s_parentChildNames[i] + "_ID FROM "
|
||||
+ s_parentChildNames[i] + " WHERE "
|
||||
+ s_parentNames[i] + "_ID=?) ";
|
||||
List<PO> poList = new Query(Env.getCtx(), table.getName(), whereClause, trxName)
|
||||
.setParameters(AD_Table_IDchild, Record_ID)
|
||||
.list();
|
||||
|
||||
int count = 0;
|
||||
for(PO po : poList)
|
||||
{
|
||||
po.deleteEx(true);
|
||||
count++;
|
||||
}
|
||||
if(count > 0) {
|
||||
if (log.isLoggable(Level.CONFIG)) log.config(table.getName() + " " + s_parentNames[i]
|
||||
+ " (" + AD_Table_ID + "/" + Record_ID + ") #" + count);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (log.isLoggable(Level.CONFIG)) log.config(table.getName() + " (" + AD_Table_ID + "/" + Record_IDorUU + ") #" + count);
|
||||
}
|
||||
return true;
|
||||
} // deleteCascade
|
||||
} // deleteRecordIdCascade
|
||||
|
||||
//IDEMPIERE-2060
|
||||
/**
|
||||
* @param tableName
|
||||
* @param Record_ID
|
||||
* @param Record_IDorUU record ID (int) or UUID (String)
|
||||
* @param trxName
|
||||
*/
|
||||
public static void deleteModelCascade(String tableName, int Record_ID, String trxName) {
|
||||
KeyNamePair[] tables = getTablesWithModelCascade(tableName, trxName);
|
||||
public static void deleteModelCascade(String tableName, Serializable Record_IDorUU, String trxName) {
|
||||
int refId;
|
||||
if (Record_IDorUU instanceof Integer) {
|
||||
refId = DisplayType.RecordID;
|
||||
} else if (Record_IDorUU instanceof String) {
|
||||
refId = DisplayType.RecordUU;
|
||||
} else {
|
||||
throw new IllegalArgumentException(Record_IDorUU.getClass().getName() + " not supported for ID/UUID");
|
||||
}
|
||||
KeyNamePair[] tables = getTablesWithModelCascade(refId, tableName, trxName);
|
||||
for (KeyNamePair table : tables) {
|
||||
int dependentTableId = table.getKey();
|
||||
String dependentColumnName = table.getName();
|
||||
|
@ -132,7 +114,7 @@ public class PO_Record
|
|||
List<PO> poList = new Query(Env.getCtx(),
|
||||
MTable.get(dependentTableId).getTableName(),
|
||||
dependentWhere,
|
||||
trxName).setParameters(Record_ID).list();
|
||||
trxName).setParameters(Record_IDorUU).list();
|
||||
for (PO po : poList) {
|
||||
po.deleteEx(true, trxName);
|
||||
}
|
||||
|
@ -140,12 +122,27 @@ public class PO_Record
|
|||
}
|
||||
|
||||
/**
|
||||
* @param refId AD_Reference_ID - Record_ID or Record_UU
|
||||
* @param tableName
|
||||
* @param trxName
|
||||
* @return
|
||||
*/
|
||||
private static KeyNamePair[] getTablesWithModelCascade(String tableName, String trxName) {
|
||||
StringBuilder key = new StringBuilder(MColumn.FKCONSTRAINTTYPE_ModelCascade).append("|").append(tableName);
|
||||
private static KeyNamePair[] getTablesWithModelCascade(int refId, String tableName, String trxName) {
|
||||
int refTableDirId;
|
||||
int refTableId;
|
||||
int refTableSearchId;
|
||||
if (refId == DisplayType.RecordID) {
|
||||
refTableDirId = DisplayType.TableDir;
|
||||
refTableId = DisplayType.Table;
|
||||
refTableSearchId = DisplayType.Search;
|
||||
} else if (refId == DisplayType.RecordUU) {
|
||||
refTableDirId = DisplayType.TableDirUU;
|
||||
refTableId = DisplayType.TableUU;
|
||||
refTableSearchId = DisplayType.SearchUU;
|
||||
} else {
|
||||
throw new IllegalArgumentException(refId + " not supported for ID/UUID");
|
||||
}
|
||||
StringBuilder key = new StringBuilder(MColumn.FKCONSTRAINTTYPE_ModelCascade).append("|").append(refId).append("|").append(tableName);
|
||||
KeyNamePair[] tables = s_po_record_tables_cache.get(key.toString());
|
||||
if (tables != null)
|
||||
return tables;
|
||||
|
@ -159,12 +156,13 @@ public class PO_Record
|
|||
+ "WHERE t.IsView = 'N' "
|
||||
+ " AND t.IsActive = 'Y' "
|
||||
+ " AND c.IsActive = 'Y' "
|
||||
+ " AND ( ( c.AD_Reference_ID = " + DisplayType.TableDir
|
||||
+ " AND ( ( c.AD_Reference_ID = ? "
|
||||
+ " AND c.ColumnName = ? || '_ID' ) "
|
||||
+ " OR ( c.AD_Reference_ID IN ( " + DisplayType.Table + ", " + DisplayType.Search + " ) "
|
||||
+ " OR ( c.AD_Reference_ID IN (? , ?) "
|
||||
+ " AND ( tr.TableName = ? OR ( tr.TableName IS NULL AND c.ColumnName = ? || '_ID' ) ) ) ) "
|
||||
+ " AND c.FKConstraintType = '" + MColumn.FKCONSTRAINTTYPE_ModelCascade + "' ";
|
||||
List<List<Object>> dependents = DB.getSQLArrayObjectsEx(trxName, sql, tableName, tableName, tableName);
|
||||
+ " AND c.FKConstraintType = ?";
|
||||
List<List<Object>> dependents = DB.getSQLArrayObjectsEx(trxName, sql,
|
||||
refTableDirId, tableName, refTableId, refTableSearchId, tableName, tableName, MColumn.FKCONSTRAINTTYPE_ModelCascade);
|
||||
if (dependents != null) {
|
||||
tables = new KeyNamePair[dependents.size()];
|
||||
for (int i=0; i<dependents.size(); i++) {
|
||||
|
@ -184,30 +182,50 @@ public class PO_Record
|
|||
/**
|
||||
* If a referencing Record ID or Record UU exists to the deleted record, set it to NULL
|
||||
* @param AD_Table_ID
|
||||
* @param Record_ID
|
||||
* @param Record_IDorUU record ID (int) or UUID (String)
|
||||
* @param trxName
|
||||
*/
|
||||
public static void setRecordIdNull(int AD_Table_ID, int Record_ID, String trxName){
|
||||
KeyNamePair[] tables = getTablesWithRecordIDColumn(MColumn.FKCONSTRAINTTYPE_ModelSetNull, trxName);
|
||||
public static void setRecordNull(int AD_Table_ID, Serializable Record_IDorUU, String trxName){
|
||||
int refId;
|
||||
String columnName;
|
||||
if (Record_IDorUU instanceof Integer) {
|
||||
refId = DisplayType.RecordID;
|
||||
columnName = "Record_ID";
|
||||
} else if (Record_IDorUU instanceof String) {
|
||||
refId = DisplayType.RecordUU;
|
||||
columnName = "Record_UU";
|
||||
} else {
|
||||
throw new IllegalArgumentException(Record_IDorUU.getClass().getName() + " not supported for ID/UUID");
|
||||
}
|
||||
KeyNamePair[] tables = getTablesWithConstraintType(refId, MColumn.FKCONSTRAINTTYPE_ModelSetNull, trxName);
|
||||
// Table loop
|
||||
StringBuilder whereClause = new StringBuilder("AD_Table_ID=? AND ").append(columnName).append("=?");
|
||||
for (KeyNamePair table : tables) {
|
||||
List<PO> poList = new Query(Env.getCtx(), table.getName(), " AD_Table_ID = ? AND Record_ID = ? ", trxName)
|
||||
.setParameters(AD_Table_ID, Record_ID)
|
||||
List<PO> poList = new Query(Env.getCtx(), table.getName(), whereClause.toString(), trxName)
|
||||
.setParameters(AD_Table_ID, Record_IDorUU)
|
||||
.list();
|
||||
|
||||
int count = 0;
|
||||
for(PO po : poList) {
|
||||
if (po.get_Table_ID() == AD_Table_ID && po.get_ID() == Record_ID)
|
||||
if ( po.get_Table_ID() == AD_Table_ID
|
||||
&& ( (Record_IDorUU instanceof Integer && po.get_ID() == (Integer) Record_IDorUU)
|
||||
|| (Record_IDorUU instanceof String && Record_IDorUU.equals(po.get_UUID()))
|
||||
)
|
||||
)
|
||||
continue;
|
||||
if (po.isColumnMandatory(po.get_ColumnIndex("Record_ID")))
|
||||
po.set_Value("Record_ID", 0);
|
||||
if (po.isColumnMandatory(po.get_ColumnIndex(columnName))) {
|
||||
if (Record_IDorUU instanceof Integer)
|
||||
po.set_Value(columnName, 0);
|
||||
else
|
||||
po.set_Value("Record_ID", null);
|
||||
po.set_Value(columnName, "");
|
||||
} else {
|
||||
po.set_Value(columnName, null);
|
||||
}
|
||||
po.saveEx(trxName);
|
||||
count++;
|
||||
}
|
||||
if (count > 0) {
|
||||
if (log.isLoggable(Level.CONFIG)) log.config(table.getName() + " (" + AD_Table_ID + "/" + Record_ID + ") #" + count);
|
||||
if (log.isLoggable(Level.CONFIG)) log.config(table.getName() + " (" + AD_Table_ID + "/" + Record_IDorUU + ") #" + count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -215,22 +233,34 @@ public class PO_Record
|
|||
/**
|
||||
* An entry Exists for restrict table/record combination
|
||||
* @param AD_Table_ID table
|
||||
* @param Record_ID record
|
||||
* @param Record_IDorUU record ID (int) or UUID (String)
|
||||
* @param trxName transaction
|
||||
* @return error message (Table Name) or null
|
||||
*/
|
||||
static String exists (int AD_Table_ID, int Record_ID, String trxName)
|
||||
protected static String exists (int AD_Table_ID, Serializable Record_IDorUU, String trxName)
|
||||
{
|
||||
KeyNamePair[] restricts = getTablesWithRecordIDColumn(MColumn.FKCONSTRAINTTYPE_ModelNoAction_ForbidDeletion, trxName);
|
||||
int refId;
|
||||
String columnName;
|
||||
if (Record_IDorUU instanceof Integer) {
|
||||
refId = DisplayType.RecordID;
|
||||
columnName = "Record_ID";
|
||||
} else if (Record_IDorUU instanceof String) {
|
||||
refId = DisplayType.RecordUU;
|
||||
columnName = "Record_UU";
|
||||
} else {
|
||||
log.warning(Record_IDorUU.getClass().getName() + " not supported for ID/UUID");
|
||||
return null;
|
||||
}
|
||||
KeyNamePair[] restricts = getTablesWithConstraintType(refId, MColumn.FKCONSTRAINTTYPE_ModelNoAction_ForbidDeletion, trxName);
|
||||
// Table Loop only
|
||||
for (int i = 0; i < restricts.length; i++)
|
||||
{
|
||||
// SELECT 1 FROM table WHERE AD_Table_ID=#1 AND Record_ID=#2 FETCH FIRST 1 ROWS ONLY
|
||||
StringBuilder sqlb = new StringBuilder ("SELECT 1 FROM ")
|
||||
.append(restricts[i].getName())
|
||||
.append(" WHERE AD_Table_ID=? AND Record_ID=?");
|
||||
.append(" WHERE AD_Table_ID=? AND ").append(columnName).append("=?");
|
||||
String sql = DB.getDatabase().addPagingSQL(sqlb.toString(), 1, 1);
|
||||
int no = DB.getSQLValueEx(trxName, sql.toString(), AD_Table_ID, Record_ID);
|
||||
int no = DB.getSQLValueEx(trxName, sql.toString(), AD_Table_ID, Record_IDorUU);
|
||||
if (no == 1)
|
||||
return Msg.getMsg(Env.getCtx(), "DeleteErrorDependent") + " -> " + restricts[i].getName();
|
||||
}
|
||||
|
@ -238,26 +268,37 @@ public class PO_Record
|
|||
} // exists
|
||||
|
||||
/**
|
||||
* Get array of tables which has a Record_ID column with the defined Constraint Type
|
||||
* Get array of tables which has a refId column with the defined Constraint Type
|
||||
* @param refId AD_Reference_ID - Record_ID or Record_UU
|
||||
* @param constraintType - FKConstraintType of AD_Column
|
||||
* @param trxName
|
||||
* @return array of KeyNamePair<AD_Table_ID, TableName>
|
||||
*/
|
||||
private static KeyNamePair[] getTablesWithRecordIDColumn(String constraintType, String trxName) {
|
||||
KeyNamePair[] tables = s_po_record_tables_cache.get(constraintType);
|
||||
private static KeyNamePair[] getTablesWithConstraintType(int refId, String constraintType, String trxName) {
|
||||
String columnName;
|
||||
if (refId == DisplayType.RecordID) {
|
||||
columnName = "Record_ID";
|
||||
} else if (refId == DisplayType.RecordUU) {
|
||||
columnName = "Record_UU";
|
||||
} else {
|
||||
log.warning(refId + " not supported for ID/UUID");
|
||||
return null;
|
||||
}
|
||||
StringBuilder key = new StringBuilder(constraintType).append("|").append(refId);
|
||||
KeyNamePair[] tables = s_po_record_tables_cache.get(key.toString());
|
||||
if (tables != null)
|
||||
return tables;
|
||||
List<MTable> listTables = new Query(Env.getCtx(), MTable.Table_Name, "c.AD_Reference_ID=? AND c.FKConstraintType=? AND AD_Table.IsView='N'", trxName)
|
||||
List<MTable> listTables = new Query(Env.getCtx(), MTable.Table_Name, "c.AD_Reference_ID=? AND c.FKConstraintType=? AND AD_Table.IsView='N' AND c.ColumnName=?", trxName)
|
||||
.addJoinClause("JOIN AD_Column c ON (c.AD_Table_ID=AD_Table.AD_Table_ID)")
|
||||
.setOnlyActiveRecords(true)
|
||||
.setParameters(DisplayType.RecordID, constraintType)
|
||||
.setParameters(refId, constraintType, columnName)
|
||||
.list();
|
||||
tables = new KeyNamePair[listTables.size()];
|
||||
for (int i=0; i<listTables.size(); i++) {
|
||||
MTable table = listTables.get(i);
|
||||
tables[i] = new KeyNamePair(table.getAD_Table_ID(), table.getTableName());
|
||||
}
|
||||
s_po_record_tables_cache.put(constraintType, tables);
|
||||
s_po_record_tables_cache.put(key.toString(), tables);
|
||||
return tables;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ public class X_AD_ChangeLog extends PO implements I_AD_ChangeLog, I_Persistent
|
|||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 20230409L;
|
||||
private static final long serialVersionUID = 20230415L;
|
||||
|
||||
/** Standard Constructor */
|
||||
public X_AD_ChangeLog (Properties ctx, int AD_ChangeLog_ID, String trxName)
|
||||
|
@ -44,7 +44,6 @@ public class X_AD_ChangeLog extends PO implements I_AD_ChangeLog, I_Persistent
|
|||
setAD_Session_ID (0);
|
||||
setAD_Table_ID (0);
|
||||
setIsCustomization (false);
|
||||
setRecord_ID (0);
|
||||
} */
|
||||
}
|
||||
|
||||
|
@ -59,7 +58,6 @@ public class X_AD_ChangeLog extends PO implements I_AD_ChangeLog, I_Persistent
|
|||
setAD_Session_ID (0);
|
||||
setAD_Table_ID (0);
|
||||
setIsCustomization (false);
|
||||
setRecord_ID (0);
|
||||
} */
|
||||
}
|
||||
|
||||
|
@ -74,7 +72,6 @@ public class X_AD_ChangeLog extends PO implements I_AD_ChangeLog, I_Persistent
|
|||
setAD_Session_ID (0);
|
||||
setAD_Table_ID (0);
|
||||
setIsCustomization (false);
|
||||
setRecord_ID (0);
|
||||
} */
|
||||
}
|
||||
|
||||
|
@ -89,7 +86,6 @@ public class X_AD_ChangeLog extends PO implements I_AD_ChangeLog, I_Persistent
|
|||
setAD_Session_ID (0);
|
||||
setAD_Table_ID (0);
|
||||
setIsCustomization (false);
|
||||
setRecord_ID (0);
|
||||
} */
|
||||
}
|
||||
|
||||
|
@ -368,6 +364,21 @@ public class X_AD_ChangeLog extends PO implements I_AD_ChangeLog, I_Persistent
|
|||
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);
|
||||
}
|
||||
|
||||
/** Set Redo.
|
||||
@param Redo Redo
|
||||
*/
|
||||
|
|
|
@ -46,6 +46,7 @@ import org.compiere.util.DisplayType;
|
|||
import org.compiere.util.Env;
|
||||
import org.compiere.util.Msg;
|
||||
import org.compiere.util.NamePair;
|
||||
import org.compiere.util.Util;
|
||||
import org.zkoss.zk.ui.event.Event;
|
||||
import org.zkoss.zk.ui.event.EventListener;
|
||||
import org.zkoss.zk.ui.event.Events;
|
||||
|
@ -62,10 +63,15 @@ import org.zkoss.zul.South;
|
|||
*/
|
||||
public class WFieldRecordInfo extends Window implements EventListener<Event>
|
||||
{
|
||||
private static final long serialVersionUID = 3859352394520596098L;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 439310027130417727L;
|
||||
|
||||
private int AD_Table_ID;
|
||||
private int AD_Column_ID;
|
||||
private int Record_ID;
|
||||
private String Record_UU;
|
||||
|
||||
/**
|
||||
* Record Info
|
||||
|
@ -73,8 +79,9 @@ public class WFieldRecordInfo extends Window implements EventListener<Event>
|
|||
* @param AD_Table_ID
|
||||
* @param AD_Column_ID
|
||||
* @param Record_ID
|
||||
* @param Record_UU
|
||||
*/
|
||||
public WFieldRecordInfo (String title, int AD_Table_ID, int AD_Column_ID, int Record_ID)
|
||||
public WFieldRecordInfo (String title, int AD_Table_ID, int AD_Column_ID, int Record_ID, String Record_UU)
|
||||
{
|
||||
super ();
|
||||
this.setTitle(title);
|
||||
|
@ -99,6 +106,7 @@ public class WFieldRecordInfo extends Window implements EventListener<Event>
|
|||
this.AD_Table_ID = AD_Table_ID;
|
||||
this.AD_Column_ID = AD_Column_ID;
|
||||
this.Record_ID = Record_ID;
|
||||
this.Record_UU = Record_UU;
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -186,13 +194,13 @@ public class WFieldRecordInfo extends Window implements EventListener<Event>
|
|||
if (!MRole.PREFERENCETYPE_Client.equals(MRole.getDefault().getPreferenceType()))
|
||||
return false;
|
||||
|
||||
if (Record_ID == 0)
|
||||
if (Record_ID == 0 && Util.isEmpty(Record_UU))
|
||||
return false;
|
||||
|
||||
// Data
|
||||
String sql = "SELECT AD_Column_ID, Updated, UpdatedBy, OldValue, NewValue "
|
||||
+ "FROM AD_ChangeLog "
|
||||
+ "WHERE AD_Table_ID=? AND Record_ID=? AND AD_Column_ID=? "
|
||||
+ "WHERE AD_Table_ID=? AND (Record_ID=? OR Record_UU=?) AND AD_Column_ID=? "
|
||||
+ "ORDER BY Updated DESC";
|
||||
PreparedStatement pstmt = null;
|
||||
ResultSet rs = null;
|
||||
|
@ -201,7 +209,8 @@ public class WFieldRecordInfo extends Window implements EventListener<Event>
|
|||
pstmt = DB.prepareStatement (sql, null);
|
||||
pstmt.setInt (1, AD_Table_ID);
|
||||
pstmt.setInt (2, Record_ID);
|
||||
pstmt.setInt (3, AD_Column_ID);
|
||||
pstmt.setString (3, Record_UU);
|
||||
pstmt.setInt (4, AD_Column_ID);
|
||||
rs = pstmt.executeQuery ();
|
||||
while (rs.next ())
|
||||
{
|
||||
|
@ -379,7 +388,8 @@ public class WFieldRecordInfo extends Window implements EventListener<Event>
|
|||
public static void start(GridField gridField) {
|
||||
new WFieldRecordInfo(gridField.getColumnName(),
|
||||
gridField.getGridTab().getAD_Table_ID(), gridField.getAD_Column_ID(),
|
||||
gridField.getGridTab().getRecord_ID());
|
||||
gridField.getGridTab().getRecord_ID(),
|
||||
gridField.getGridTab().getRecord_UU());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -317,6 +317,7 @@ public class WRecordInfo extends Window implements EventListener<Event>
|
|||
int Record_ID = -1;
|
||||
if (dse.Record_ID instanceof Integer)
|
||||
Record_ID = ((Integer)dse.Record_ID).intValue();
|
||||
String Record_UU = null;
|
||||
|
||||
MTable dbtable = null;
|
||||
if (dse.AD_Table_ID != 0)
|
||||
|
@ -327,7 +328,6 @@ public class WRecordInfo extends Window implements EventListener<Event>
|
|||
PO po = gridTable.getPO(dse.getCurrentRow());
|
||||
if (po != null) {
|
||||
String uuidcol = po.getUUIDColumnName();
|
||||
String uuid = null;
|
||||
if (po.is_new()) {
|
||||
if (Record_ID == 0 && MTable.isZeroIDTable(dbtable.getTableName())) {
|
||||
// Need to read the UUID directly from database because the PO cannot be used with zero ID records
|
||||
|
@ -338,13 +338,13 @@ public class WRecordInfo extends Window implements EventListener<Event>
|
|||
.append(" WHERE ")
|
||||
.append(dbtable.getTableName())
|
||||
.append("_ID=0");
|
||||
uuid = DB.getSQLValueString(null, sql.toString());
|
||||
Record_UU = DB.getSQLValueString(null, sql.toString());
|
||||
}
|
||||
} else {
|
||||
uuid = po.get_UUID();
|
||||
Record_UU = po.get_UUID();
|
||||
}
|
||||
if (!Util.isEmpty(uuid)) {
|
||||
StringBuilder uuinfo = new StringBuilder(uuidcol).append("=").append(uuid);
|
||||
if (!Util.isEmpty(Record_UU)) {
|
||||
StringBuilder uuinfo = new StringBuilder(uuidcol).append("=").append(Record_UU);
|
||||
if (! m_info.toString().contains(uuinfo))
|
||||
m_info.append("\n ").append(uuinfo);
|
||||
}
|
||||
|
@ -365,7 +365,7 @@ public class WRecordInfo extends Window implements EventListener<Event>
|
|||
});
|
||||
}
|
||||
m_permalink.setVisible(po.get_KeyColumns().length == 1);
|
||||
final String whereClause = po.get_WhereClause(true, uuid);
|
||||
final String whereClause = po.get_WhereClause(true, Record_UU);
|
||||
m_copySelect.addEventListener(Events.ON_CLICK, new EventListener<Event>() {
|
||||
public void onEvent(Event event) throws Exception {
|
||||
StringBuffer query = new StringBuffer("navigator.clipboard.writeText(\"SELECT * FROM ")
|
||||
|
@ -396,13 +396,13 @@ public class WRecordInfo extends Window implements EventListener<Event>
|
|||
if (!MRole.PREFERENCETYPE_Client.equals(MRole.getDefault().getPreferenceType()))
|
||||
return false;
|
||||
|
||||
if (Record_ID <= 0)
|
||||
if (Record_ID <= 0 && Util.isEmpty(Record_UU))
|
||||
return false;
|
||||
|
||||
// Data
|
||||
String sql = "SELECT AD_Column_ID, Updated, UpdatedBy, OldValue, NewValue "
|
||||
+ "FROM AD_ChangeLog "
|
||||
+ "WHERE AD_Table_ID=? AND Record_ID=? "
|
||||
+ "WHERE AD_Table_ID=? AND (Record_ID=? OR Record_UU=?) "
|
||||
+ "ORDER BY Updated DESC";
|
||||
PreparedStatement pstmt = null;
|
||||
ResultSet rs = null;
|
||||
|
@ -411,6 +411,7 @@ public class WRecordInfo extends Window implements EventListener<Event>
|
|||
pstmt = DB.prepareStatement (sql, null);
|
||||
pstmt.setInt (1, dse.AD_Table_ID);
|
||||
pstmt.setInt (2, Record_ID);
|
||||
pstmt.setString (3, Record_UU);
|
||||
rs = pstmt.executeQuery ();
|
||||
while (rs.next ())
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue