From c73000c38bfda7a18269d09eededb1bd5d38323b Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Wed, 14 May 2014 14:44:06 -0500 Subject: [PATCH] 1003856 IDEMPIERE-1951 Integrate commit from hengsin -> Run report as a background job. Peer review implementation from Elaine. --- .../oracle/201403311258_Ticket_1003856.sql | 184 +++++ .../201403311258_Ticket_1003856.sql | 181 +++++ .../org/compiere/model/I_AD_PInstance.java | 22 + .../src/org/compiere/model/MClient.java | 50 ++ .../src/org/compiere/model/MPInstance.java | 28 +- .../src/org/compiere/model/MSysConfig.java | 6 + .../org/compiere/model/X_AD_PInstance.java | 53 +- .../compiere/process/ServerProcessCtl.java | 53 +- .../org/compiere/report/ReportStarter.java | 9 +- .../server/org/compiere/server/Scheduler.java | 107 ++- .../webui/apps/AbstractProcessDialog.java | 761 ++++++++++++++++++ .../adempiere/webui/apps/ProcessDialog.java | 566 ++++--------- .../webui/apps/ProcessModalDialog.java | 363 +-------- .../webui/dashboard/DPRunningJobs.java | 282 +++++++ .../adempiere/webui/panel/WAttachment.java | 1 + .../default/zul/dashboard/runningJobs.zul | 2 + org.adempiere.ui.zk/zul/runningJobs.zul | 11 + 17 files changed, 1880 insertions(+), 799 deletions(-) create mode 100644 migration/i2.0z/oracle/201403311258_Ticket_1003856.sql create mode 100644 migration/i2.0z/postgresql/201403311258_Ticket_1003856.sql create mode 100644 org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/AbstractProcessDialog.java create mode 100644 org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/dashboard/DPRunningJobs.java create mode 100644 org.adempiere.ui.zk/theme/default/zul/dashboard/runningJobs.zul create mode 100644 org.adempiere.ui.zk/zul/runningJobs.zul diff --git a/migration/i2.0z/oracle/201403311258_Ticket_1003856.sql b/migration/i2.0z/oracle/201403311258_Ticket_1003856.sql new file mode 100644 index 0000000000..776c441fce --- /dev/null +++ b/migration/i2.0z/oracle/201403311258_Ticket_1003856.sql @@ -0,0 +1,184 @@ +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- Mar 28, 2014 6:34:26 PM SGT +-- Ticket #1003856: Run report as a background job +INSERT INTO AD_Element (ColumnName,AD_Element_ID,Name,PrintName,AD_Element_UU,Created,Updated,AD_Org_ID,CreatedBy,UpdatedBy,IsActive,AD_Client_ID,EntityType) VALUES ('IsRunAsJob',202694,'Run as Job','Run as Job','c52c9e5a-da3e-401d-8f52-e58f557a56f2',TO_DATE('2014-03-28 18:34:24','YYYY-MM-DD HH24:MI:SS'),TO_DATE('2014-03-28 18:34:24','YYYY-MM-DD HH24:MI:SS'),0,100,100,'Y',0,'D') +; + +-- Mar 28, 2014 6:35:05 PM SGT +INSERT INTO AD_Column (SeqNoSelection,IsSyncDatabase,Version,AD_Column_ID,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsParent,FieldLength,IsSelectionColumn,IsKey,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsUpdateable,ColumnName,DefaultValue,Name,IsAllowCopy,Updated,CreatedBy,AD_Org_ID,IsActive,Created,UpdatedBy,IsToolbarButton,IsAlwaysUpdateable,AD_Client_ID,IsEncrypted,IsSecure,FKConstraintType,AD_Element_ID,AD_Reference_ID,AD_Table_ID,EntityType) VALUES (0,'N',0,211199,'Y','N','N',0,'N',1,'N','N','N','Y','e67be641-2f1b-4c6b-9c8a-a6788940a686','Y','IsRunAsJob','N','Run as Job','Y',TO_DATE('2014-03-28 18:35:03','YYYY-MM-DD HH24:MI:SS'),100,0,'Y',TO_DATE('2014-03-28 18:35:03','YYYY-MM-DD HH24:MI:SS'),100,'N','N',0,'N','N','N',202694,20,282,'D') +; + +-- Mar 28, 2014 6:38:03 PM SGT +INSERT INTO AD_Element (ColumnName,AD_Element_ID,Name,PrintName,AD_Element_UU,Created,Updated,AD_Org_ID,CreatedBy,UpdatedBy,IsActive,AD_Client_ID,EntityType) VALUES ('IsJobProcessing',202695,'Job Processing','Job Processing','54265662-ebe2-4521-ba7e-8a9f9a96bcab',TO_DATE('2014-03-28 18:38:02','YYYY-MM-DD HH24:MI:SS'),TO_DATE('2014-03-28 18:38:02','YYYY-MM-DD HH24:MI:SS'),0,100,100,'Y',0,'D') +; + +-- Mar 28, 2014 6:38:22 PM SGT +INSERT INTO AD_Column (SeqNoSelection,IsSyncDatabase,Version,AD_Column_ID,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsParent,FieldLength,IsSelectionColumn,IsKey,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsUpdateable,ColumnName,DefaultValue,Name,IsAllowCopy,Updated,CreatedBy,AD_Org_ID,IsActive,Created,UpdatedBy,IsToolbarButton,IsAlwaysUpdateable,AD_Client_ID,IsEncrypted,IsSecure,FKConstraintType,AD_Element_ID,AD_Reference_ID,AD_Table_ID,EntityType) VALUES (0,'N',0,211200,'Y','N','N',0,'N',1,'N','N','N','Y','922b7724-599a-49c8-a053-0f8f4b8e2156','Y','IsJobProcessing','N','Job Processing','Y',TO_DATE('2014-03-28 18:38:21','YYYY-MM-DD HH24:MI:SS'),100,0,'Y',TO_DATE('2014-03-28 18:38:21','YYYY-MM-DD HH24:MI:SS'),100,'N','N',0,'N','N','N',202695,20,282,'D') +; + +-- Mar 28, 2014 6:38:42 PM SGT +INSERT INTO AD_Column (SeqNoSelection,IsSyncDatabase,Version,AD_Column_ID,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsParent,FieldLength,IsSelectionColumn,IsKey,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsUpdateable,ColumnName,Description,Help,Name,IsAllowCopy,Updated,CreatedBy,AD_Org_ID,IsActive,Created,UpdatedBy,IsToolbarButton,IsAlwaysUpdateable,AD_Client_ID,IsEncrypted,IsSecure,AD_Element_ID,AD_Reference_ID,AD_Reference_Value_ID,AD_Table_ID,EntityType) VALUES (0,'N',0,211201,'N','N','N',0,'N',2,'N','N','N','Y','5c07ac2d-8342-4e86-ae06-5109f872a16b','Y','NotificationType','Type of Notifications','Emails or Notification sent out for Request Updates, etc.','Notification Type','Y',TO_DATE('2014-03-28 18:38:41','YYYY-MM-DD HH24:MI:SS'),100,0,'Y',TO_DATE('2014-03-28 18:38:41','YYYY-MM-DD HH24:MI:SS'),100,'N','N',0,'N','N',2755,17,200026,282,'D') +; + +-- Mar 28, 2014 6:43:27 PM SGT +ALTER TABLE AD_PInstance ADD IsRunAsJob CHAR(1) DEFAULT 'N' +; + +-- Mar 28, 2014 6:43:44 PM SGT +ALTER TABLE AD_PInstance ADD IsJobProcessing CHAR(1) DEFAULT 'N' +; + +-- Mar 28, 2014 6:43:51 PM SGT +ALTER TABLE AD_PInstance ADD NotificationType VARCHAR2(2) DEFAULT NULL +; + +-- Mar 28, 2014 6:44:35 PM SGT +INSERT INTO AD_Field (IsEncrypted,AD_Tab_ID,DisplayLength,IsSameLine,IsHeading,SeqNo,IsCentrallyMaintained,AD_Field_ID,IsReadOnly,EntityType,Name,AD_Field_UU,IsDisplayed,IsFieldOnly,UpdatedBy,AD_Org_ID,Created,CreatedBy,Updated,IsActive,IsDisplayedGrid,AD_Client_ID,ColumnSpan,AD_Column_ID) VALUES ('N',663,36,'N','N',110,'Y',202844,'N','D','AD_PInstance_UU','3540b3cc-efe6-4509-bafc-a15c59c9d7f8','N','N',100,0,TO_DATE('2014-03-28 18:44:34','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2014-03-28 18:44:34','YYYY-MM-DD HH24:MI:SS'),'Y','N',0,2,60451) +; + +-- Mar 28, 2014 6:44:36 PM SGT +INSERT INTO AD_Field (IsEncrypted,AD_Tab_ID,DisplayLength,IsSameLine,IsHeading,SeqNo,IsCentrallyMaintained,AD_Field_ID,IsReadOnly,EntityType,Name,AD_Field_UU,IsDisplayed,IsFieldOnly,UpdatedBy,AD_Org_ID,Created,CreatedBy,Updated,IsActive,XPosition,AD_Client_ID,ColumnSpan,AD_Column_ID) VALUES ('N',663,1,'N','N',120,'Y',202845,'N','D','Run as Job','72ecc44d-a61b-44b9-a94a-14bd270dbf22','Y','N',100,0,TO_DATE('2014-03-28 18:44:35','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2014-03-28 18:44:35','YYYY-MM-DD HH24:MI:SS'),'Y',2,0,2,211199) +; + +-- Mar 28, 2014 6:44:37 PM SGT +INSERT INTO AD_Field (IsEncrypted,AD_Tab_ID,DisplayLength,IsSameLine,IsHeading,SeqNo,IsCentrallyMaintained,AD_Field_ID,IsReadOnly,EntityType,Name,AD_Field_UU,IsDisplayed,IsFieldOnly,UpdatedBy,AD_Org_ID,Created,CreatedBy,Updated,IsActive,XPosition,AD_Client_ID,ColumnSpan,AD_Column_ID) VALUES ('N',663,1,'N','N',130,'Y',202846,'N','D','Job Processing','96118891-6592-4f41-8ba0-05057e17d60e','Y','N',100,0,TO_DATE('2014-03-28 18:44:36','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2014-03-28 18:44:36','YYYY-MM-DD HH24:MI:SS'),'Y',2,0,2,211200) +; + +-- Mar 28, 2014 6:44:38 PM SGT +INSERT INTO AD_Field (IsEncrypted,AD_Tab_ID,DisplayLength,IsSameLine,IsHeading,SeqNo,IsCentrallyMaintained,AD_Field_ID,IsReadOnly,Help,EntityType,Description,Name,AD_Field_UU,IsDisplayed,IsFieldOnly,UpdatedBy,AD_Org_ID,Created,CreatedBy,Updated,IsActive,AD_Client_ID,ColumnSpan,AD_Column_ID) VALUES ('N',663,2,'N','N',140,'Y',202847,'N','Emails or Notification sent out for Request Updates, etc.','D','Type of Notifications','Notification Type','d76699c8-2abe-4f62-9e10-6e10fd5dba20','Y','N',100,0,TO_DATE('2014-03-28 18:44:37','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2014-03-28 18:44:37','YYYY-MM-DD HH24:MI:SS'),'Y',0,2,211201) +; + +-- Mar 28, 2014 6:45:04 PM SGT +UPDATE AD_Field SET SeqNo=0,IsDisplayed='N' WHERE AD_Field_ID=202844 +; + +-- Mar 28, 2014 6:45:04 PM SGT +UPDATE AD_Field SET SeqNo=110,IsDisplayed='Y' WHERE AD_Field_ID=202845 +; + +-- Mar 28, 2014 6:45:04 PM SGT +UPDATE AD_Field SET SeqNo=120,IsDisplayed='Y' WHERE AD_Field_ID=202847 +; + +-- Mar 28, 2014 6:45:11 PM SGT +UPDATE AD_Field SET SeqNoGrid=110,IsDisplayedGrid='Y' WHERE AD_Field_ID=202845 +; + +-- Mar 28, 2014 6:45:11 PM SGT +UPDATE AD_Field SET SeqNoGrid=120,IsDisplayedGrid='Y' WHERE AD_Field_ID=202847 +; + +-- Mar 28, 2014 6:45:11 PM SGT +UPDATE AD_Field SET SeqNoGrid=130,IsDisplayedGrid='Y' WHERE AD_Field_ID=202846 +; + +-- Mar 28, 2014 6:46:01 PM SGT +INSERT INTO AD_FieldGroup (FieldGroupType,EntityType,IsCollapsedByDefault,Name,AD_FieldGroup_UU,AD_FieldGroup_ID,Created,CreatedBy,Updated,AD_Org_ID,UpdatedBy,IsActive,AD_Client_ID) VALUES ('C','D','N','Background Job','3be13370-89e4-42b3-8220-370ce497466a',200018,TO_DATE('2014-03-28 18:46:00','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2014-03-28 18:46:00','YYYY-MM-DD HH24:MI:SS'),0,100,'Y',0) +; + +-- Mar 28, 2014 6:46:18 PM SGT +UPDATE AD_Field SET AD_FieldGroup_ID=200018,Updated=TO_DATE('2014-03-28 18:46:18','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=202847 +; + +-- Mar 28, 2014 6:46:22 PM SGT +UPDATE AD_Field SET AD_FieldGroup_ID=200018,Updated=TO_DATE('2014-03-28 18:46:22','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=202845 +; + +-- Mar 28, 2014 6:46:28 PM SGT +UPDATE AD_Field SET AD_FieldGroup_ID=200018,Updated=TO_DATE('2014-03-28 18:46:28','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=202846 +; + +-- Mar 28, 2014 6:46:44 PM SGT +UPDATE AD_Field SET IsSameLine='Y', XPosition=4,Updated=TO_DATE('2014-03-28 18:46:44','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=202847 +; + +-- Mar 28, 2014 6:49:07 PM SGT +INSERT INTO AD_SysConfig (AD_SysConfig_ID,ConfigurationLevel,Value,AD_SysConfig_UU,Updated,Created,AD_Org_ID,CreatedBy,IsActive,UpdatedBy,Name,AD_Client_ID,EntityType) VALUES (200047,'C','Y','feb88039-2fe8-47e5-a7be-c3a634674f0b',TO_DATE('2014-03-28 18:49:06','YYYY-MM-DD HH24:MI:SS'),TO_DATE('2014-03-28 18:49:06','YYYY-MM-DD HH24:MI:SS'),0,100,'Y',100,'BACKGROUND_JOB_ALLOWED',0,'D') +; + +-- Mar 28, 2014 6:49:31 PM SGT +INSERT INTO AD_SysConfig (AD_SysConfig_ID,ConfigurationLevel,Value,AD_SysConfig_UU,Updated,Created,AD_Org_ID,CreatedBy,IsActive,UpdatedBy,Name,AD_Client_ID,EntityType) VALUES (200048,'C','N','f2fd6f9b-d8bb-4ade-9857-78ba68951776',TO_DATE('2014-03-28 18:49:30','YYYY-MM-DD HH24:MI:SS'),TO_DATE('2014-03-28 18:49:30','YYYY-MM-DD HH24:MI:SS'),0,100,'Y',100,'BACKGROUND_JOB_BY_DEFAULT',0,'D') +; + +-- Mar 28, 2014 6:50:36 PM SGT +INSERT INTO AD_SysConfig (AD_SysConfig_ID,ConfigurationLevel,Value,AD_SysConfig_UU,Updated,Created,AD_Org_ID,CreatedBy,IsActive,UpdatedBy,Name,AD_Client_ID,EntityType) VALUES (200049,'S','20','0a24332e-a83a-465a-903f-6f3d7caea306',TO_DATE('2014-03-28 18:50:35','YYYY-MM-DD HH24:MI:SS'),TO_DATE('2014-03-28 18:50:35','YYYY-MM-DD HH24:MI:SS'),0,100,'Y',100,'BACKGROUND_JOB_MAX_IN_SYSTEM',0,'D') +; + +-- Mar 28, 2014 6:51:09 PM SGT +INSERT INTO AD_SysConfig (AD_SysConfig_ID,ConfigurationLevel,Value,AD_SysConfig_UU,Updated,Created,AD_Org_ID,CreatedBy,IsActive,UpdatedBy,Name,AD_Client_ID,EntityType) VALUES (200050,'C','10','d2d149e8-e642-4691-8ed3-8a875ee9b1ed',TO_DATE('2014-03-28 18:51:08','YYYY-MM-DD HH24:MI:SS'),TO_DATE('2014-03-28 18:51:08','YYYY-MM-DD HH24:MI:SS'),0,100,'Y',100,'BACKGROUND_JOB_MAX_PER_CLIENT',0,'D') +; + +-- Mar 28, 2014 6:52:26 PM SGT +INSERT INTO AD_SysConfig (AD_SysConfig_ID,ConfigurationLevel,Value,AD_SysConfig_UU,Updated,Created,AD_Org_ID,CreatedBy,IsActive,UpdatedBy,Name,AD_Client_ID,EntityType) VALUES (200051,'C','10','b0697150-68d7-4cfe-b103-f626db07793a',TO_DATE('2014-03-28 18:52:25','YYYY-MM-DD HH24:MI:SS'),TO_DATE('2014-03-28 18:52:25','YYYY-MM-DD HH24:MI:SS'),0,100,'Y',100,'BACKGROUND_JOB_MAX_PER_USER',0,'D') +; + +-- Mar 28, 2014 6:53:28 PM SGT +UPDATE AD_SysConfig SET Value='5',Updated=TO_DATE('2014-03-28 18:53:28','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_SysConfig_ID=200051 +; + +-- Mar 28, 2014 6:54:11 PM SGT +UPDATE AD_SysConfig SET ConfigurationLevel='S',Updated=TO_DATE('2014-03-28 18:54:11','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_SysConfig_ID=200050 +; + +-- Mar 28, 2014 6:58:22 PM SGT +INSERT INTO PA_DashboardContent (Line,PA_DashboardContent_ID,ColumnNo,IsCollapsible,GoalDisplay,Description,Name,PA_DashboardContent_UU,IsShowInDashboard,AD_Org_ID,Created,CreatedBy,Updated,AD_Client_ID,UpdatedBy,IsActive,IsEmbedReportContent,IsCollapsedByDefault,AD_Role_ID,IsShowinLogin,ZulFilePath,AD_User_ID) VALUES (3.000000000000,200002,0,'Y','T','Running Jobs','Running Jobs','e3fb872e-ce14-4029-830b-2d21a556fc60','Y',0,TO_DATE('2014-03-28 18:58:20','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2014-03-28 18:58:20','YYYY-MM-DD HH24:MI:SS'),0,100,'Y','N','N',0,'Y','/zul/runningJobs.zul',0) +; + +-- Mar 28, 2014 7:57:19 PM SGT +-- Ticket #1003856: Run report as a background job +UPDATE AD_Column SET AD_Reference_Value_ID=344,Updated=TO_DATE('2014-03-28 19:57:19','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=211201 +; + +-- Mar 28, 2014 7:58:52 PM SGT +INSERT INTO AD_Message (MsgType,MsgText,AD_Message_ID,AD_Message_UU,Value,IsActive,Updated,CreatedBy,UpdatedBy,Created,EntityType,AD_Client_ID,AD_Org_ID) VALUES ('E','Exceed maximum number of running jobs allowed per user',200263,'82593e5f-86c6-45c5-bc38-4d9d5b2c8609','BackgroundJobExceedMaxPerUser','Y',TO_DATE('2014-03-28 19:58:49','YYYY-MM-DD HH24:MI:SS'),100,100,TO_DATE('2014-03-28 19:58:49','YYYY-MM-DD HH24:MI:SS'),'D',0,0) +; + +-- Mar 28, 2014 7:59:12 PM SGT +INSERT INTO AD_Message (MsgType,MsgText,AD_Message_ID,AD_Message_UU,Value,IsActive,Updated,CreatedBy,UpdatedBy,Created,EntityType,AD_Client_ID,AD_Org_ID) VALUES ('E','Exceed maximum number of running jobs allowed per client',200264,'fcebfad5-8283-498e-a835-b42bf0a0219a','BackgroundJobExceedMaxPerClient','Y',TO_DATE('2014-03-28 19:59:11','YYYY-MM-DD HH24:MI:SS'),100,100,TO_DATE('2014-03-28 19:59:11','YYYY-MM-DD HH24:MI:SS'),'D',0,0) +; + +-- Mar 28, 2014 7:59:51 PM SGT +INSERT INTO AD_Message (MsgType,MsgText,AD_Message_ID,AD_Message_UU,Value,IsActive,Updated,CreatedBy,UpdatedBy,Created,EntityType,AD_Client_ID,AD_Org_ID) VALUES ('E','Exceed maximum number of running jobs allowed in the system',200265,'405ea4c2-5a19-42fa-a5ff-f22601453f7f','BackgroundJobExceedMaxInSystem','Y',TO_DATE('2014-03-28 19:59:50','YYYY-MM-DD HH24:MI:SS'),100,100,TO_DATE('2014-03-28 19:59:50','YYYY-MM-DD HH24:MI:SS'),'D',0,0) +; + +-- Mar 28, 2014 8:00:19 PM SGT +INSERT INTO AD_Message (MsgType,MsgText,AD_Message_ID,AD_Message_UU,Value,IsActive,Updated,CreatedBy,UpdatedBy,Created,EntityType,AD_Client_ID,AD_Org_ID) VALUES ('I','The process has been scheduled as job. The status of the process will be sent as notification to owner of the process.',200266,'dc68fd3b-0ce8-416c-a286-37f192a90f7d','BackgroundJobScheduled','Y',TO_DATE('2014-03-28 20:00:18','YYYY-MM-DD HH24:MI:SS'),100,100,TO_DATE('2014-03-28 20:00:18','YYYY-MM-DD HH24:MI:SS'),'D',0,0) +; + +-- Mar 28, 2014 9:03:01 PM SGT +-- Ticket #1003856: Run report as a background job +INSERT INTO AD_Message (MsgType,MsgText,AD_Message_ID,AD_Message_UU,Value,IsActive,Updated,CreatedBy,UpdatedBy,Created,EntityType,AD_Client_ID,AD_Org_ID) VALUES ('I','Background Job',200267,'530545f2-f32c-4072-8bd1-d9ca65f31f65','BackgroundJob','Y',TO_DATE('2014-03-28 21:02:59','YYYY-MM-DD HH24:MI:SS'),100,100,TO_DATE('2014-03-28 21:02:59','YYYY-MM-DD HH24:MI:SS'),'D',0,0) +; + +-- Mar 31, 2014 5:54:16 PM SGT +-- Ticket #1003856: Run report as a background job +DELETE FROM AD_Field_Trl WHERE AD_Field_ID=202846 +; + +-- Mar 31, 2014 5:54:16 PM SGT +DELETE FROM AD_Field WHERE AD_Field_ID=202846 +; + +-- Mar 31, 2014 5:54:49 PM SGT +DELETE FROM AD_Column_Trl WHERE AD_Column_ID=211200 +; + +-- Mar 31, 2014 5:54:49 PM SGT +DELETE FROM AD_Column WHERE AD_Column_ID=211200 +; + +-- Mar 31, 2014 5:54:56 PM SGT +DELETE FROM AD_Element_Trl WHERE AD_Element_ID=202695 +; + +-- Mar 31, 2014 5:54:56 PM SGT +DELETE FROM AD_Element WHERE AD_Element_ID=202695 +; + +ALTER TABLE AD_PInstance DROP COLUMN IsJobProcessing +; + +SELECT register_migration_script('201403311258_Ticket_1003856.sql') FROM dual +; \ No newline at end of file diff --git a/migration/i2.0z/postgresql/201403311258_Ticket_1003856.sql b/migration/i2.0z/postgresql/201403311258_Ticket_1003856.sql new file mode 100644 index 0000000000..7e512469fa --- /dev/null +++ b/migration/i2.0z/postgresql/201403311258_Ticket_1003856.sql @@ -0,0 +1,181 @@ +-- Mar 28, 2014 6:34:26 PM SGT +-- Ticket #1003856: Run report as a background job +INSERT INTO AD_Element (ColumnName,AD_Element_ID,Name,PrintName,AD_Element_UU,Created,Updated,AD_Org_ID,CreatedBy,UpdatedBy,IsActive,AD_Client_ID,EntityType) VALUES ('IsRunAsJob',202694,'Run as Job','Run as Job','c52c9e5a-da3e-401d-8f52-e58f557a56f2',TO_TIMESTAMP('2014-03-28 18:34:24','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2014-03-28 18:34:24','YYYY-MM-DD HH24:MI:SS'),0,100,100,'Y',0,'D') +; + +-- Mar 28, 2014 6:35:05 PM SGT +INSERT INTO AD_Column (SeqNoSelection,IsSyncDatabase,Version,AD_Column_ID,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsParent,FieldLength,IsSelectionColumn,IsKey,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsUpdateable,ColumnName,DefaultValue,Name,IsAllowCopy,Updated,CreatedBy,AD_Org_ID,IsActive,Created,UpdatedBy,IsToolbarButton,IsAlwaysUpdateable,AD_Client_ID,IsEncrypted,IsSecure,FKConstraintType,AD_Element_ID,AD_Reference_ID,AD_Table_ID,EntityType) VALUES (0,'N',0,211199,'Y','N','N',0,'N',1,'N','N','N','Y','e67be641-2f1b-4c6b-9c8a-a6788940a686','Y','IsRunAsJob','N','Run as Job','Y',TO_TIMESTAMP('2014-03-28 18:35:03','YYYY-MM-DD HH24:MI:SS'),100,0,'Y',TO_TIMESTAMP('2014-03-28 18:35:03','YYYY-MM-DD HH24:MI:SS'),100,'N','N',0,'N','N','N',202694,20,282,'D') +; + +-- Mar 28, 2014 6:38:03 PM SGT +INSERT INTO AD_Element (ColumnName,AD_Element_ID,Name,PrintName,AD_Element_UU,Created,Updated,AD_Org_ID,CreatedBy,UpdatedBy,IsActive,AD_Client_ID,EntityType) VALUES ('IsJobProcessing',202695,'Job Processing','Job Processing','54265662-ebe2-4521-ba7e-8a9f9a96bcab',TO_TIMESTAMP('2014-03-28 18:38:02','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2014-03-28 18:38:02','YYYY-MM-DD HH24:MI:SS'),0,100,100,'Y',0,'D') +; + +-- Mar 28, 2014 6:38:22 PM SGT +INSERT INTO AD_Column (SeqNoSelection,IsSyncDatabase,Version,AD_Column_ID,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsParent,FieldLength,IsSelectionColumn,IsKey,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsUpdateable,ColumnName,DefaultValue,Name,IsAllowCopy,Updated,CreatedBy,AD_Org_ID,IsActive,Created,UpdatedBy,IsToolbarButton,IsAlwaysUpdateable,AD_Client_ID,IsEncrypted,IsSecure,FKConstraintType,AD_Element_ID,AD_Reference_ID,AD_Table_ID,EntityType) VALUES (0,'N',0,211200,'Y','N','N',0,'N',1,'N','N','N','Y','922b7724-599a-49c8-a053-0f8f4b8e2156','Y','IsJobProcessing','N','Job Processing','Y',TO_TIMESTAMP('2014-03-28 18:38:21','YYYY-MM-DD HH24:MI:SS'),100,0,'Y',TO_TIMESTAMP('2014-03-28 18:38:21','YYYY-MM-DD HH24:MI:SS'),100,'N','N',0,'N','N','N',202695,20,282,'D') +; + +-- Mar 28, 2014 6:38:42 PM SGT +INSERT INTO AD_Column (SeqNoSelection,IsSyncDatabase,Version,AD_Column_ID,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsParent,FieldLength,IsSelectionColumn,IsKey,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsUpdateable,ColumnName,Description,Help,Name,IsAllowCopy,Updated,CreatedBy,AD_Org_ID,IsActive,Created,UpdatedBy,IsToolbarButton,IsAlwaysUpdateable,AD_Client_ID,IsEncrypted,IsSecure,AD_Element_ID,AD_Reference_ID,AD_Reference_Value_ID,AD_Table_ID,EntityType) VALUES (0,'N',0,211201,'N','N','N',0,'N',2,'N','N','N','Y','5c07ac2d-8342-4e86-ae06-5109f872a16b','Y','NotificationType','Type of Notifications','Emails or Notification sent out for Request Updates, etc.','Notification Type','Y',TO_TIMESTAMP('2014-03-28 18:38:41','YYYY-MM-DD HH24:MI:SS'),100,0,'Y',TO_TIMESTAMP('2014-03-28 18:38:41','YYYY-MM-DD HH24:MI:SS'),100,'N','N',0,'N','N',2755,17,200026,282,'D') +; + +-- Mar 28, 2014 6:43:27 PM SGT +ALTER TABLE AD_PInstance ADD COLUMN IsRunAsJob CHAR(1) DEFAULT 'N' +; + +-- Mar 28, 2014 6:43:44 PM SGT +ALTER TABLE AD_PInstance ADD COLUMN IsJobProcessing CHAR(1) DEFAULT 'N' +; + +-- Mar 28, 2014 6:43:51 PM SGT +ALTER TABLE AD_PInstance ADD COLUMN NotificationType VARCHAR(2) DEFAULT NULL +; + +-- Mar 28, 2014 6:44:35 PM SGT +INSERT INTO AD_Field (IsEncrypted,AD_Tab_ID,DisplayLength,IsSameLine,IsHeading,SeqNo,IsCentrallyMaintained,AD_Field_ID,IsReadOnly,EntityType,Name,AD_Field_UU,IsDisplayed,IsFieldOnly,UpdatedBy,AD_Org_ID,Created,CreatedBy,Updated,IsActive,IsDisplayedGrid,AD_Client_ID,ColumnSpan,AD_Column_ID) VALUES ('N',663,36,'N','N',110,'Y',202844,'N','D','AD_PInstance_UU','3540b3cc-efe6-4509-bafc-a15c59c9d7f8','N','N',100,0,TO_TIMESTAMP('2014-03-28 18:44:34','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2014-03-28 18:44:34','YYYY-MM-DD HH24:MI:SS'),'Y','N',0,2,60451) +; + +-- Mar 28, 2014 6:44:36 PM SGT +INSERT INTO AD_Field (IsEncrypted,AD_Tab_ID,DisplayLength,IsSameLine,IsHeading,SeqNo,IsCentrallyMaintained,AD_Field_ID,IsReadOnly,EntityType,Name,AD_Field_UU,IsDisplayed,IsFieldOnly,UpdatedBy,AD_Org_ID,Created,CreatedBy,Updated,IsActive,XPosition,AD_Client_ID,ColumnSpan,AD_Column_ID) VALUES ('N',663,1,'N','N',120,'Y',202845,'N','D','Run as Job','72ecc44d-a61b-44b9-a94a-14bd270dbf22','Y','N',100,0,TO_TIMESTAMP('2014-03-28 18:44:35','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2014-03-28 18:44:35','YYYY-MM-DD HH24:MI:SS'),'Y',2,0,2,211199) +; + +-- Mar 28, 2014 6:44:37 PM SGT +INSERT INTO AD_Field (IsEncrypted,AD_Tab_ID,DisplayLength,IsSameLine,IsHeading,SeqNo,IsCentrallyMaintained,AD_Field_ID,IsReadOnly,EntityType,Name,AD_Field_UU,IsDisplayed,IsFieldOnly,UpdatedBy,AD_Org_ID,Created,CreatedBy,Updated,IsActive,XPosition,AD_Client_ID,ColumnSpan,AD_Column_ID) VALUES ('N',663,1,'N','N',130,'Y',202846,'N','D','Job Processing','96118891-6592-4f41-8ba0-05057e17d60e','Y','N',100,0,TO_TIMESTAMP('2014-03-28 18:44:36','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2014-03-28 18:44:36','YYYY-MM-DD HH24:MI:SS'),'Y',2,0,2,211200) +; + +-- Mar 28, 2014 6:44:38 PM SGT +INSERT INTO AD_Field (IsEncrypted,AD_Tab_ID,DisplayLength,IsSameLine,IsHeading,SeqNo,IsCentrallyMaintained,AD_Field_ID,IsReadOnly,Help,EntityType,Description,Name,AD_Field_UU,IsDisplayed,IsFieldOnly,UpdatedBy,AD_Org_ID,Created,CreatedBy,Updated,IsActive,AD_Client_ID,ColumnSpan,AD_Column_ID) VALUES ('N',663,2,'N','N',140,'Y',202847,'N','Emails or Notification sent out for Request Updates, etc.','D','Type of Notifications','Notification Type','d76699c8-2abe-4f62-9e10-6e10fd5dba20','Y','N',100,0,TO_TIMESTAMP('2014-03-28 18:44:37','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2014-03-28 18:44:37','YYYY-MM-DD HH24:MI:SS'),'Y',0,2,211201) +; + +-- Mar 28, 2014 6:45:04 PM SGT +UPDATE AD_Field SET SeqNo=0,IsDisplayed='N' WHERE AD_Field_ID=202844 +; + +-- Mar 28, 2014 6:45:04 PM SGT +UPDATE AD_Field SET SeqNo=110,IsDisplayed='Y' WHERE AD_Field_ID=202845 +; + +-- Mar 28, 2014 6:45:04 PM SGT +UPDATE AD_Field SET SeqNo=120,IsDisplayed='Y' WHERE AD_Field_ID=202847 +; + +-- Mar 28, 2014 6:45:11 PM SGT +UPDATE AD_Field SET SeqNoGrid=110,IsDisplayedGrid='Y' WHERE AD_Field_ID=202845 +; + +-- Mar 28, 2014 6:45:11 PM SGT +UPDATE AD_Field SET SeqNoGrid=120,IsDisplayedGrid='Y' WHERE AD_Field_ID=202847 +; + +-- Mar 28, 2014 6:45:11 PM SGT +UPDATE AD_Field SET SeqNoGrid=130,IsDisplayedGrid='Y' WHERE AD_Field_ID=202846 +; + +-- Mar 28, 2014 6:46:01 PM SGT +INSERT INTO AD_FieldGroup (FieldGroupType,EntityType,IsCollapsedByDefault,Name,AD_FieldGroup_UU,AD_FieldGroup_ID,Created,CreatedBy,Updated,AD_Org_ID,UpdatedBy,IsActive,AD_Client_ID) VALUES ('C','D','N','Background Job','3be13370-89e4-42b3-8220-370ce497466a',200018,TO_TIMESTAMP('2014-03-28 18:46:00','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2014-03-28 18:46:00','YYYY-MM-DD HH24:MI:SS'),0,100,'Y',0) +; + +-- Mar 28, 2014 6:46:18 PM SGT +UPDATE AD_Field SET AD_FieldGroup_ID=200018,Updated=TO_TIMESTAMP('2014-03-28 18:46:18','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=202847 +; + +-- Mar 28, 2014 6:46:22 PM SGT +UPDATE AD_Field SET AD_FieldGroup_ID=200018,Updated=TO_TIMESTAMP('2014-03-28 18:46:22','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=202845 +; + +-- Mar 28, 2014 6:46:28 PM SGT +UPDATE AD_Field SET AD_FieldGroup_ID=200018,Updated=TO_TIMESTAMP('2014-03-28 18:46:28','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=202846 +; + +-- Mar 28, 2014 6:46:44 PM SGT +UPDATE AD_Field SET IsSameLine='Y', XPosition=4,Updated=TO_TIMESTAMP('2014-03-28 18:46:44','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=202847 +; + +-- Mar 28, 2014 6:49:07 PM SGT +INSERT INTO AD_SysConfig (AD_SysConfig_ID,ConfigurationLevel,Value,AD_SysConfig_UU,Updated,Created,AD_Org_ID,CreatedBy,IsActive,UpdatedBy,Name,AD_Client_ID,EntityType) VALUES (200047,'C','Y','feb88039-2fe8-47e5-a7be-c3a634674f0b',TO_TIMESTAMP('2014-03-28 18:49:06','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2014-03-28 18:49:06','YYYY-MM-DD HH24:MI:SS'),0,100,'Y',100,'BACKGROUND_JOB_ALLOWED',0,'D') +; + +-- Mar 28, 2014 6:49:31 PM SGT +INSERT INTO AD_SysConfig (AD_SysConfig_ID,ConfigurationLevel,Value,AD_SysConfig_UU,Updated,Created,AD_Org_ID,CreatedBy,IsActive,UpdatedBy,Name,AD_Client_ID,EntityType) VALUES (200048,'C','N','f2fd6f9b-d8bb-4ade-9857-78ba68951776',TO_TIMESTAMP('2014-03-28 18:49:30','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2014-03-28 18:49:30','YYYY-MM-DD HH24:MI:SS'),0,100,'Y',100,'BACKGROUND_JOB_BY_DEFAULT',0,'D') +; + +-- Mar 28, 2014 6:50:36 PM SGT +INSERT INTO AD_SysConfig (AD_SysConfig_ID,ConfigurationLevel,Value,AD_SysConfig_UU,Updated,Created,AD_Org_ID,CreatedBy,IsActive,UpdatedBy,Name,AD_Client_ID,EntityType) VALUES (200049,'S','20','0a24332e-a83a-465a-903f-6f3d7caea306',TO_TIMESTAMP('2014-03-28 18:50:35','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2014-03-28 18:50:35','YYYY-MM-DD HH24:MI:SS'),0,100,'Y',100,'BACKGROUND_JOB_MAX_IN_SYSTEM',0,'D') +; + +-- Mar 28, 2014 6:51:09 PM SGT +INSERT INTO AD_SysConfig (AD_SysConfig_ID,ConfigurationLevel,Value,AD_SysConfig_UU,Updated,Created,AD_Org_ID,CreatedBy,IsActive,UpdatedBy,Name,AD_Client_ID,EntityType) VALUES (200050,'C','10','d2d149e8-e642-4691-8ed3-8a875ee9b1ed',TO_TIMESTAMP('2014-03-28 18:51:08','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2014-03-28 18:51:08','YYYY-MM-DD HH24:MI:SS'),0,100,'Y',100,'BACKGROUND_JOB_MAX_PER_CLIENT',0,'D') +; + +-- Mar 28, 2014 6:52:26 PM SGT +INSERT INTO AD_SysConfig (AD_SysConfig_ID,ConfigurationLevel,Value,AD_SysConfig_UU,Updated,Created,AD_Org_ID,CreatedBy,IsActive,UpdatedBy,Name,AD_Client_ID,EntityType) VALUES (200051,'C','10','b0697150-68d7-4cfe-b103-f626db07793a',TO_TIMESTAMP('2014-03-28 18:52:25','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2014-03-28 18:52:25','YYYY-MM-DD HH24:MI:SS'),0,100,'Y',100,'BACKGROUND_JOB_MAX_PER_USER',0,'D') +; + +-- Mar 28, 2014 6:53:28 PM SGT +UPDATE AD_SysConfig SET Value='5',Updated=TO_TIMESTAMP('2014-03-28 18:53:28','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_SysConfig_ID=200051 +; + +-- Mar 28, 2014 6:54:11 PM SGT +UPDATE AD_SysConfig SET ConfigurationLevel='S',Updated=TO_TIMESTAMP('2014-03-28 18:54:11','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_SysConfig_ID=200050 +; + +-- Mar 28, 2014 6:58:22 PM SGT +INSERT INTO PA_DashboardContent (Line,PA_DashboardContent_ID,ColumnNo,IsCollapsible,GoalDisplay,Description,Name,PA_DashboardContent_UU,IsShowInDashboard,AD_Org_ID,Created,CreatedBy,Updated,AD_Client_ID,UpdatedBy,IsActive,IsEmbedReportContent,IsCollapsedByDefault,AD_Role_ID,IsShowinLogin,ZulFilePath,AD_User_ID) VALUES (3.000000000000,200002,0,'Y','T','Running Jobs','Running Jobs','e3fb872e-ce14-4029-830b-2d21a556fc60','Y',0,TO_TIMESTAMP('2014-03-28 18:58:20','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2014-03-28 18:58:20','YYYY-MM-DD HH24:MI:SS'),0,100,'Y','N','N',0,'Y','/zul/runningJobs.zul',0) +; + +-- Mar 28, 2014 7:57:19 PM SGT +-- Ticket #1003856: Run report as a background job +UPDATE AD_Column SET AD_Reference_Value_ID=344,Updated=TO_TIMESTAMP('2014-03-28 19:57:19','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=211201 +; + +-- Mar 28, 2014 7:58:52 PM SGT +INSERT INTO AD_Message (MsgType,MsgText,AD_Message_ID,AD_Message_UU,Value,IsActive,Updated,CreatedBy,UpdatedBy,Created,EntityType,AD_Client_ID,AD_Org_ID) VALUES ('E','Exceed maximum number of running jobs allowed per user',200263,'82593e5f-86c6-45c5-bc38-4d9d5b2c8609','BackgroundJobExceedMaxPerUser','Y',TO_TIMESTAMP('2014-03-28 19:58:49','YYYY-MM-DD HH24:MI:SS'),100,100,TO_TIMESTAMP('2014-03-28 19:58:49','YYYY-MM-DD HH24:MI:SS'),'D',0,0) +; + +-- Mar 28, 2014 7:59:12 PM SGT +INSERT INTO AD_Message (MsgType,MsgText,AD_Message_ID,AD_Message_UU,Value,IsActive,Updated,CreatedBy,UpdatedBy,Created,EntityType,AD_Client_ID,AD_Org_ID) VALUES ('E','Exceed maximum number of running jobs allowed per client',200264,'fcebfad5-8283-498e-a835-b42bf0a0219a','BackgroundJobExceedMaxPerClient','Y',TO_TIMESTAMP('2014-03-28 19:59:11','YYYY-MM-DD HH24:MI:SS'),100,100,TO_TIMESTAMP('2014-03-28 19:59:11','YYYY-MM-DD HH24:MI:SS'),'D',0,0) +; + +-- Mar 28, 2014 7:59:51 PM SGT +INSERT INTO AD_Message (MsgType,MsgText,AD_Message_ID,AD_Message_UU,Value,IsActive,Updated,CreatedBy,UpdatedBy,Created,EntityType,AD_Client_ID,AD_Org_ID) VALUES ('E','Exceed maximum number of running jobs allowed in the system',200265,'405ea4c2-5a19-42fa-a5ff-f22601453f7f','BackgroundJobExceedMaxInSystem','Y',TO_TIMESTAMP('2014-03-28 19:59:50','YYYY-MM-DD HH24:MI:SS'),100,100,TO_TIMESTAMP('2014-03-28 19:59:50','YYYY-MM-DD HH24:MI:SS'),'D',0,0) +; + +-- Mar 28, 2014 8:00:19 PM SGT +INSERT INTO AD_Message (MsgType,MsgText,AD_Message_ID,AD_Message_UU,Value,IsActive,Updated,CreatedBy,UpdatedBy,Created,EntityType,AD_Client_ID,AD_Org_ID) VALUES ('I','The process has been scheduled as job. The status of the process will be sent as notification to owner of the process.',200266,'dc68fd3b-0ce8-416c-a286-37f192a90f7d','BackgroundJobScheduled','Y',TO_TIMESTAMP('2014-03-28 20:00:18','YYYY-MM-DD HH24:MI:SS'),100,100,TO_TIMESTAMP('2014-03-28 20:00:18','YYYY-MM-DD HH24:MI:SS'),'D',0,0) +; + +-- Mar 28, 2014 9:03:01 PM SGT +-- Ticket #1003856: Run report as a background job +INSERT INTO AD_Message (MsgType,MsgText,AD_Message_ID,AD_Message_UU,Value,IsActive,Updated,CreatedBy,UpdatedBy,Created,EntityType,AD_Client_ID,AD_Org_ID) VALUES ('I','Background Job',200267,'530545f2-f32c-4072-8bd1-d9ca65f31f65','BackgroundJob','Y',TO_TIMESTAMP('2014-03-28 21:02:59','YYYY-MM-DD HH24:MI:SS'),100,100,TO_TIMESTAMP('2014-03-28 21:02:59','YYYY-MM-DD HH24:MI:SS'),'D',0,0) +; + +-- Mar 31, 2014 5:54:16 PM SGT +-- Ticket #1003856: Run report as a background job +DELETE FROM AD_Field_Trl WHERE AD_Field_ID=202846 +; + +-- Mar 31, 2014 5:54:16 PM SGT +DELETE FROM AD_Field WHERE AD_Field_ID=202846 +; + +-- Mar 31, 2014 5:54:49 PM SGT +DELETE FROM AD_Column_Trl WHERE AD_Column_ID=211200 +; + +-- Mar 31, 2014 5:54:49 PM SGT +DELETE FROM AD_Column WHERE AD_Column_ID=211200 +; + +-- Mar 31, 2014 5:54:56 PM SGT +DELETE FROM AD_Element_Trl WHERE AD_Element_ID=202695 +; + +-- Mar 31, 2014 5:54:56 PM SGT +DELETE FROM AD_Element WHERE AD_Element_ID=202695 +; + +ALTER TABLE AD_PInstance DROP COLUMN IsJobProcessing +; + +SELECT register_migration_script('201403311258_Ticket_1003856.sql') FROM dual +; \ No newline at end of file diff --git a/org.adempiere.base/src/org/compiere/model/I_AD_PInstance.java b/org.adempiere.base/src/org/compiere/model/I_AD_PInstance.java index dd041cd8de..02306a6a52 100644 --- a/org.adempiere.base/src/org/compiere/model/I_AD_PInstance.java +++ b/org.adempiere.base/src/org/compiere/model/I_AD_PInstance.java @@ -174,6 +174,28 @@ public interface I_AD_PInstance */ public String getName(); + /** Column name IsRunAsJob */ + public static final String COLUMNNAME_IsRunAsJob = "IsRunAsJob"; + + /** Set Run as Job */ + public void setIsRunAsJob (boolean IsRunAsJob); + + /** Get Run as Job */ + public boolean isRunAsJob(); + + /** Column name NotificationType */ + public static final String COLUMNNAME_NotificationType = "NotificationType"; + + /** Set Notification Type. + * Type of Notifications + */ + public void setNotificationType (String NotificationType); + + /** Get Notification Type. + * Type of Notifications + */ + public String getNotificationType(); + /** Column name Record_ID */ public static final String COLUMNNAME_Record_ID = "Record_ID"; diff --git a/org.adempiere.base/src/org/compiere/model/MClient.java b/org.adempiere.base/src/org/compiere/model/MClient.java index 2fb39a3175..aa2067c268 100644 --- a/org.adempiere.base/src/org/compiere/model/MClient.java +++ b/org.adempiere.base/src/org/compiere/model/MClient.java @@ -554,6 +554,56 @@ public class MClient extends X_AD_Client } } // sendEMail + /** + * Send EMail from User + * @param from sender + * @param to recipient + * @param subject subject + * @param message message + * @param attachment optional attachment + * @return true if sent + */ + public boolean sendEMailAttachments (MUser from, MUser to, + String subject, String message, List attachments) + { + return sendEMailAttachments(from, to, subject, message, attachments, false); + } + + /** + * Send EMail from User + * @param from sender + * @param to recipient + * @param subject subject + * @param message message + * @param attachment optional attachment + * @param isHtml + * @return true if sent + */ + public boolean sendEMailAttachments (MUser from, MUser to, + String subject, String message, List attachments, boolean isHtml) + { + EMail email = createEMail(from, to, subject, message, isHtml); + if (email == null) + return false; + + if (attachments != null && !attachments.isEmpty()) + { + for (File attachment : attachments) + email.addAttachment(attachment); + } + InternetAddress emailFrom = email.getFrom(); + try + { + return sendEmailNow(from, to, email); + } + catch (Exception ex) + { + log.severe(getName() + " - from " + emailFrom + + " to " + to + ": " + ex.getLocalizedMessage()); + return false; + } + } // sendEMail + /** * Send EMail from Request User - no trace * @param to recipient email address diff --git a/org.adempiere.base/src/org/compiere/model/MPInstance.java b/org.adempiere.base/src/org/compiere/model/MPInstance.java index 7619823d30..26855eab54 100644 --- a/org.adempiere.base/src/org/compiere/model/MPInstance.java +++ b/org.adempiere.base/src/org/compiere/model/MPInstance.java @@ -21,14 +21,21 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Timestamp; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Properties; import java.util.logging.Level; +import org.adempiere.base.Service; +import org.adempiere.base.event.EventManager; import org.compiere.util.CLogger; import org.compiere.util.DB; import org.compiere.util.Env; import org.compiere.util.Msg; +import org.idempiere.distributed.IMessageService; +import org.idempiere.distributed.ITopic; +import org.osgi.service.event.Event; /** * Process Instance Model @@ -45,7 +52,9 @@ public class MPInstance extends X_AD_PInstance /** * */ - private static final long serialVersionUID = -3952972645135787655L; + private static final long serialVersionUID = -4047766735041088419L; + + public static final String ON_RUNNING_JOB_CHANGED_TOPIC = "onRunningJobChanged"; private static CLogger s_log = CLogger.getCLogger (MPInstance.class); @@ -353,6 +362,23 @@ public class MPInstance extends X_AD_PInstance return ip; } + public static void publishChangedEvent(int AD_User_ID) { + IMessageService service = Service.locator().locate(IMessageService.class).getService(); + if (service != null) { + ITopic topic = service.getTopic(ON_RUNNING_JOB_CHANGED_TOPIC); + topic.publish(AD_User_ID); + } else { + postOnChangedEvent(AD_User_ID); + } + } + + public static void postOnChangedEvent(int AD_User_ID) { + Map properties = new HashMap(); + properties.put("AD_User_ID", AD_User_ID); + Event event = new Event(ON_RUNNING_JOB_CHANGED_TOPIC, properties); + EventManager.getInstance().postEvent(event); + } + public static List get(Properties ctx, int AD_Process_ID, int AD_User_ID) { List list = new ArrayList(); List paramsStrAdded = new ArrayList(); diff --git a/org.adempiere.base/src/org/compiere/model/MSysConfig.java b/org.adempiere.base/src/org/compiere/model/MSysConfig.java index 67479184e6..0e11db4059 100644 --- a/org.adempiere.base/src/org/compiere/model/MSysConfig.java +++ b/org.adempiere.base/src/org/compiere/model/MSysConfig.java @@ -122,6 +122,12 @@ public class MSysConfig extends X_AD_SysConfig public static final String TAX_SAVE_REQUEST_RESPONSE_LOG = "TAX_SAVE_REQUEST_RESPONSE_LOG"; public static final String ADDRESS_SAVE_REQUEST_RESPONSE_LOG = "ADDRESS_SAVE_REQUEST_RESPONSE_LOG"; public static final String VALIDATE_MATCHING_TO_ORDERED_QTY = "VALIDATE_MATCHING_TO_ORDERED_QTY"; + + public static final String BACKGROUND_JOB_ALLOWED = "BACKGROUND_JOB_ALLOWED"; + public static final String BACKGROUND_JOB_BY_DEFAULT = "BACKGROUND_JOB_BY_DEFAULT"; + public static final String BACKGROUND_JOB_MAX_IN_SYSTEM = "BACKGROUND_JOB_MAX_IN_SYSTEM"; + public static final String BACKGROUND_JOB_MAX_PER_CLIENT = "BACKGROUND_JOB_MAX_PER_CLIENT"; + public static final String BACKGROUND_JOB_MAX_PER_USER = "BACKGROUND_JOB_MAX_PER_USER"; public static final String DPVIEWS_SHOWINFOACCOUNT = "DPViews_ShowInfoAccount"; public static final String DPVIEWS_SHOWINFOSCHEDULE = "DPViews_ShowInfoSchedule"; diff --git a/org.adempiere.base/src/org/compiere/model/X_AD_PInstance.java b/org.adempiere.base/src/org/compiere/model/X_AD_PInstance.java index 1dd50b1e0b..4b73e5acd1 100644 --- a/org.adempiere.base/src/org/compiere/model/X_AD_PInstance.java +++ b/org.adempiere.base/src/org/compiere/model/X_AD_PInstance.java @@ -30,7 +30,7 @@ public class X_AD_PInstance extends PO implements I_AD_PInstance, I_Persistent /** * */ - private static final long serialVersionUID = 20140404L; + private static final long serialVersionUID = 20140331L; /** Standard Constructor */ public X_AD_PInstance (Properties ctx, int AD_PInstance_ID, String trxName) @@ -41,6 +41,8 @@ public class X_AD_PInstance extends PO implements I_AD_PInstance, I_Persistent setAD_PInstance_ID (0); setAD_Process_ID (0); setIsProcessing (false); + setIsRunAsJob (false); +// N setRecord_ID (0); } */ } @@ -226,6 +228,55 @@ public class X_AD_PInstance extends PO implements I_AD_PInstance, I_Persistent return (String)get_Value(COLUMNNAME_Name); } + /** Set Run as Job. + @param IsRunAsJob Run as Job */ + public void setIsRunAsJob (boolean IsRunAsJob) + { + set_Value (COLUMNNAME_IsRunAsJob, Boolean.valueOf(IsRunAsJob)); + } + + /** Get Run as Job. + @return Run as Job */ + public boolean isRunAsJob () + { + Object oo = get_Value(COLUMNNAME_IsRunAsJob); + if (oo != null) + { + if (oo instanceof Boolean) + return ((Boolean)oo).booleanValue(); + return "Y".equals(oo); + } + return false; + } + + /** NotificationType AD_Reference_ID=344 */ + public static final int NOTIFICATIONTYPE_AD_Reference_ID=344; + /** EMail = E */ + public static final String NOTIFICATIONTYPE_EMail = "E"; + /** Notice = N */ + public static final String NOTIFICATIONTYPE_Notice = "N"; + /** None = X */ + public static final String NOTIFICATIONTYPE_None = "X"; + /** EMail+Notice = B */ + public static final String NOTIFICATIONTYPE_EMailPlusNotice = "B"; + /** Set Notification Type. + @param NotificationType + Type of Notifications + */ + public void setNotificationType (String NotificationType) + { + + set_Value (COLUMNNAME_NotificationType, NotificationType); + } + + /** Get Notification Type. + @return Type of Notifications + */ + public String getNotificationType () + { + return (String)get_Value(COLUMNNAME_NotificationType); + } + /** Set Record ID. @param Record_ID Direct internal record ID diff --git a/org.adempiere.base/src/org/compiere/process/ServerProcessCtl.java b/org.adempiere.base/src/org/compiere/process/ServerProcessCtl.java index 1d098e7405..3e9caa739f 100644 --- a/org.adempiere.base/src/org/compiere/process/ServerProcessCtl.java +++ b/org.adempiere.base/src/org/compiere/process/ServerProcessCtl.java @@ -61,31 +61,38 @@ public class ServerProcessCtl implements Runnable { if (log.isLoggable(Level.FINE)) log.fine("ServerProcess - " + pi); MPInstance instance = null; - try - { - instance = new MPInstance(Env.getCtx(), pi.getAD_Process_ID(), pi.getRecord_ID()); - } - catch (Exception e) - { - pi.setSummary (e.getLocalizedMessage()); - pi.setError (true); - log.warning(pi.toString()); - return null; - } - catch (Error e) - { - pi.setSummary (e.getLocalizedMessage()); - pi.setError (true); - log.warning(pi.toString()); - return null; - } - if (!instance.save()) + if (pi.getAD_PInstance_ID() <= 0) { - pi.setSummary (Msg.getMsg(Env.getCtx(), "ProcessNoInstance")); - pi.setError (true); - return null; + try + { + instance = new MPInstance(Env.getCtx(), pi.getAD_Process_ID(), pi.getRecord_ID()); + } + catch (Exception e) + { + pi.setSummary (e.getLocalizedMessage()); + pi.setError (true); + log.warning(pi.toString()); + return null; + } + catch (Error e) + { + pi.setSummary (e.getLocalizedMessage()); + pi.setError (true); + log.warning(pi.toString()); + return null; + } + if (!instance.save()) + { + pi.setSummary (Msg.getMsg(Env.getCtx(), "ProcessNoInstance")); + pi.setError (true); + return null; + } + pi.setAD_PInstance_ID (instance.getAD_PInstance_ID()); + } + else + { + instance = new MPInstance(Env.getCtx(), pi.getAD_PInstance_ID(), null); } - pi.setAD_PInstance_ID (instance.getAD_PInstance_ID()); // execute ServerProcessCtl worker = new ServerProcessCtl(pi, trx); diff --git a/org.adempiere.report.jasper/src/org/compiere/report/ReportStarter.java b/org.adempiere.report.jasper/src/org/compiere/report/ReportStarter.java index 6ddb441dcb..d4af2c36c3 100644 --- a/org.adempiere.report.jasper/src/org/compiere/report/ReportStarter.java +++ b/org.adempiere.report.jasper/src/org/compiere/report/ReportStarter.java @@ -626,7 +626,7 @@ public class ReportStarter implements ProcessCall, ClientProcess if (!processInfo.isExport()) { - if (reportData.isDirectPrint()) + if (reportData.isDirectPrint() || processInfo.isBatch()) { if (log.isLoggable(Level.INFO)) log.info( "ReportStarter.startProcess print report -" + jasperPrint.getName()); //RF 1906632 @@ -666,8 +666,6 @@ public class ReportStarter implements ProcessCall, ClientProcess } else { - // You can use JasperPrint to create PDF - // Used For the PH try { File PDF = File.createTempFile(makePrefix(jasperPrint.getName()), ".pdf"); @@ -684,10 +682,7 @@ public class ReportStarter implements ProcessCall, ClientProcess { log.severe("ReportStarter.startProcess: Can not make PDF File - "+ e.getMessage()); } - } - - // You can use JasperPrint to create PDF - // JasperExportManager.exportReportToPdfFile(jasperPrint, "BasicReport.pdf"); + } } else { if (log.isLoggable(Level.INFO)) log.info( "ReportStarter.startProcess run report -"+jasperPrint.getName()); JRViewerProvider viewerLauncher = Service.locator().locate(JRViewerProvider.class).getService(); diff --git a/org.adempiere.server/src/main/server/org/compiere/server/Scheduler.java b/org.adempiere.server/src/main/server/org/compiere/server/Scheduler.java index 6c35cf1039..8900526e1b 100644 --- a/org.adempiere.server/src/main/server/org/compiere/server/Scheduler.java +++ b/org.adempiere.server/src/main/server/org/compiere/server/Scheduler.java @@ -23,6 +23,8 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; import java.util.Properties; import java.util.logging.Level; @@ -157,7 +159,7 @@ public class Scheduler extends AdempiereServer { if (log.isLoggable(Level.INFO)) log.info(process.toString()); - boolean isReport = (process.isReport() || process.getAD_ReportView_ID() > 0); + boolean isReport = (process.isReport() || process.getAD_ReportView_ID() > 0 || process.getJasperReport() != null || process.getAD_PrintFormat_ID() > 0); // Process (see also MWFActivity.performWork int AD_Table_ID = m_model.getAD_Table_ID(); @@ -170,9 +172,11 @@ public class Scheduler extends AdempiereServer pi.setAD_User_ID(getAD_User_ID()); pi.setAD_Client_ID(m_model.getAD_Client_ID()); pi.setAD_PInstance_ID(pInstance.getAD_PInstance_ID()); + pi.setIsBatch(true); MUser from = new MUser(getCtx(), pi.getAD_User_ID(), null); - if ( !process.processIt(pi, m_trx) ) // note, this call close the transaction, don't use m_trx below + ServerProcessCtl.process(pi, m_trx); + if ( pi.isError() ) // note, this call close the transaction, don't use m_trx below { // notify supervisor if error int supervisor = m_model.getSupervisor_ID(); @@ -195,9 +199,16 @@ public class Scheduler extends AdempiereServer MNote note = new MNote(getCtx(), AD_Message_ID, supervisor, null); note.setClientOrg(m_model.getAD_Client_ID(), m_model.getAD_Org_ID()); note.setTextMsg(pi.getSummary()); - //note.setDescription(); note.setRecord(MPInstance.Table_ID, pi.getAD_PInstance_ID()); note.saveEx(); + String log = pi.getLogInfo(true); + if (log != null && log.trim().length() > 0) { + MAttachment attachment = new MAttachment (getCtx(), MNote.Table_ID, note.getAD_Note_ID(), null); + attachment.setClientOrg(m_model.getAD_Client_ID(), m_model.getAD_Org_ID()); + attachment.setTextMsg(m_model.getName()); + attachment.addEntry("ProcessLog.html", log.getBytes("UTF-8")); + attachment.saveEx(); + } } } } @@ -207,38 +218,45 @@ public class Scheduler extends AdempiereServer if (userIDs.length > 0) { ProcessInfoUtil.setLogFromDB(pi); + List fileList = new ArrayList(); + if (isReport) { + // Report + ReportEngine re = ReportEngine.get(m_schedulerctx, pi); + + if(re != null && re.getPrintFormat().getJasperProcess_ID() > 0) + { + // We have a Jasper Print Format + // ============================== + ProcessInfo jasperpi = new ProcessInfo ("", re.getPrintFormat().getJasperProcess_ID()); + jasperpi.setIsBatch(true); + ServerProcessCtl.process(jasperpi, null); + fileList.add(jasperpi.getPDFReport()); + } + else if (process.getJasperReport() != null) + { + fileList.add(pi.getPDFReport()); + } + else + { + // Standard Print Format (Non-Jasper) + // ================================== + if (re == null) + return "Cannot create Report AD_Process_ID=" + process.getAD_Process_ID() + + " - " + process.getName(); + fileList.add(re.getPDF()); + } + } + if (pi.isExport() && pi.getExportFile() != null) + { + fileList.add(pi.getExportFile()); + } + for (int i = 0; i < userIDs.length; i++) { MUser user = new MUser(getCtx(), userIDs[i].intValue(), null); boolean email = user.isNotificationEMail(); boolean notice = user.isNotificationNote(); - - File report = null; - if (isReport) { - // Report - ReportEngine re = ReportEngine.get(m_schedulerctx, pi); - - if(process.getJasperReport() != null - || (re != null && re.getPrintFormat().getJasperProcess_ID() > 0)) - { - // We have a Jasper Print Format - // ============================== - ProcessInfo jasperpi = new ProcessInfo ("", process.getAD_Process_ID()); - jasperpi.setIsBatch(true); - ServerProcessCtl.process(jasperpi, null); - report = jasperpi.getPDFReport(); - } - else - { - // Standard Print Format (Non-Jasper) - // ================================== - if (re == null) - return "Cannot create Report AD_Process_ID=" + process.getAD_Process_ID() - + " - " + process.getName(); - report = re.getPDF(); - } - } - + if (notice) { int AD_Message_ID = 441; // ProcessOK if (isReport) @@ -250,29 +268,42 @@ public class Scheduler extends AdempiereServer note.setDescription(m_model.getDescription()); note.setRecord(AD_Table_ID, Record_ID); } else { - note.setTextMsg(pi.getSummary()); - // note.setDescription(); + note.setTextMsg(m_model.getName() + "\n" + pi.getSummary()); note.setRecord(MPInstance.Table_ID, pi.getAD_PInstance_ID()); } if (note.save()) { - if (isReport) { + MAttachment attachment = null; + if (fileList != null && !fileList.isEmpty()) { // Attachment - MAttachment attachment = new MAttachment (getCtx(), MNote.Table_ID, note.getAD_Note_ID(), null); + attachment = new MAttachment (getCtx(), MNote.Table_ID, note.getAD_Note_ID(), null); attachment.setClientOrg(m_model.getAD_Client_ID(), m_model.getAD_Org_ID()); - attachment.addEntry(report); attachment.setTextMsg(m_model.getName()); + for (File entry : fileList) + attachment.addEntry(entry); + + } + String log = pi.getLogInfo(true); + if (log != null && log.trim().length() > 0) { + if (attachment == null) { + attachment = new MAttachment (getCtx(), MNote.Table_ID, note.getAD_Note_ID(), null); + attachment.setClientOrg(m_model.getAD_Client_ID(), m_model.getAD_Org_ID()); + attachment.setTextMsg(m_model.getName()); + } + attachment.addEntry("ProcessLog.html", log.getBytes("UTF-8")); attachment.saveEx(); } + if (attachment != null) + attachment.saveEx(); } } if (email) { MClient client = MClient.get(m_model.getCtx(), m_model.getAD_Client_ID()); - if (isReport) { - client.sendEMail(from, user, m_model.getName(), m_model.getDescription(), report); + if (fileList != null && !fileList.isEmpty()) { + client.sendEMailAttachments(from, user, m_model.getName(), m_model.getDescription(), fileList); } else { - client.sendEMail(from, user, process.getName(), pi.getSummary() + " " + pi.getLogInfo(), null); + client.sendEMail(from, user, m_model.getName(), pi.getSummary() + " " + pi.getLogInfo(), null); } } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/AbstractProcessDialog.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/AbstractProcessDialog.java new file mode 100644 index 0000000000..c94fcb08c1 --- /dev/null +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/AbstractProcessDialog.java @@ -0,0 +1,761 @@ +/****************************************************************************** + * Copyright (C) 2014 Elaine Tan * + * Copyright (C) 2014 Trek Global + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ + +package org.adempiere.webui.apps; + +import java.io.File; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; + +import org.adempiere.util.Callback; +import org.adempiere.util.ContextRunnable; +import org.adempiere.util.IProcessUI; +import org.adempiere.util.ServerContext; +import org.adempiere.webui.component.Checkbox; +import org.adempiere.webui.component.Column; +import org.adempiere.webui.component.Columns; +import org.adempiere.webui.component.ComboItem; +import org.adempiere.webui.component.Combobox; +import org.adempiere.webui.component.Grid; +import org.adempiere.webui.component.GridFactory; +import org.adempiere.webui.component.Label; +import org.adempiere.webui.component.Panel; +import org.adempiere.webui.component.Row; +import org.adempiere.webui.component.Rows; +import org.adempiere.webui.component.Window; +import org.adempiere.webui.editor.WTableDirEditor; +import org.adempiere.webui.process.WProcessInfo; +import org.adempiere.webui.window.FDialog; +import org.adempiere.webui.window.MultiFileDownloadDialog; +import org.compiere.Adempiere; +import org.compiere.model.MAttachment; +import org.compiere.model.MClient; +import org.compiere.model.MLookup; +import org.compiere.model.MLookupFactory; +import org.compiere.model.MLookupInfo; +import org.compiere.model.MNote; +import org.compiere.model.MPInstance; +import org.compiere.model.MProcess; +import org.compiere.model.MSysConfig; +import org.compiere.model.MUser; +import org.compiere.model.Query; +import org.compiere.print.ReportEngine; +import org.compiere.process.ProcessInfo; +import org.compiere.process.ProcessInfoUtil; +import org.compiere.process.ServerProcessCtl; +import org.compiere.util.CLogger; +import org.compiere.util.DB; +import org.compiere.util.Env; +import org.compiere.util.Msg; +import org.compiere.util.Trx; +import org.zkoss.zk.au.out.AuEcho; +import org.zkoss.zk.ui.Component; +import org.zkoss.zk.ui.Desktop; +import org.zkoss.zk.ui.Executions; +import org.zkoss.zk.ui.event.Event; +import org.zkoss.zk.ui.event.EventListener; +import org.zkoss.zk.ui.event.Events; +import org.zkoss.zk.ui.util.Clients; +import org.zkoss.zul.Div; +import org.zkoss.zul.Html; +import org.zkoss.zul.Space; + +public abstract class AbstractProcessDialog extends Window implements IProcessUI, EventListener +{ + /** + * + */ + private static final long serialVersionUID = 2190456247109646320L; + + private static final String ON_COMPLETE = "onComplete"; + private static final String ON_STATUS_UPDATE = "onStatusUpdate"; + + private static CLogger log = CLogger.getCLogger(AbstractProcessDialog.class); + + private int m_WindowNo; + private Properties m_ctx; + private int m_AD_Process_ID; + private ProcessInfo m_pi = null; + private boolean m_disposeOnComplete; + + private Html message = null; + private Panel centerPanel = null; + + private ProcessParameterPanel parameterPanel = null; + private Checkbox runAsJobField = null; + private WTableDirEditor notificationTypeField = null; + + private BusyDialog progressWindow; + + private String m_Name = null; + private StringBuffer m_messageText = new StringBuffer(); + private String m_ShowHelp = null; // Determine if a Help Process Window is shown + private String initialMessage; + + private boolean m_valid = true; + private boolean m_cancel = false; + + private Future future; + private List downloadFiles; + private boolean m_locked = false; + + protected AbstractProcessDialog() + { + super(); + message = new Html(); + centerPanel = new Panel(); + } + + protected boolean init(Properties ctx, int WindowNo, int AD_Process_ID, ProcessInfo pi, String innerWidth, boolean autoStart, boolean isDisposeOnComplete) + { + m_ctx = ctx; + m_WindowNo = WindowNo; + m_AD_Process_ID = AD_Process_ID; + setProcessInfo(pi); + m_disposeOnComplete = isDisposeOnComplete; + + log.config(""); + // + boolean trl = !Env.isBaseLanguage(m_ctx, "AD_Process"); + String sql = "SELECT Name, Description, Help, IsReport, ShowHelp " + + "FROM AD_Process " + + "WHERE AD_Process_ID=?"; + if (trl) + sql = "SELECT t.Name, t.Description, t.Help, p.IsReport, p.ShowHelp " + + "FROM AD_Process p, AD_Process_Trl t " + + "WHERE p.AD_Process_ID=t.AD_Process_ID" + + " AND p.AD_Process_ID=? AND t.AD_Language=?"; + + PreparedStatement pstmt = null; + ResultSet rs = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, AD_Process_ID); + if (trl) + pstmt.setString(2, Env.getAD_Language(m_ctx)); + rs = pstmt.executeQuery(); + if (rs.next()) + { + m_Name = rs.getString(1); + m_ShowHelp = rs.getString(5); + // + m_messageText.append(""); + String s = rs.getString(2); // Description + if (rs.wasNull()) + m_messageText.append(Msg.getMsg(m_ctx, "StartProcess?")); + else + m_messageText.append(s); + m_messageText.append(""); + + s = rs.getString(3); // Help + if (!rs.wasNull()) + m_messageText.append("

").append(s).append("

"); + } + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + return false; + } + finally + { + DB.close(rs, pstmt); + } + + if (m_Name == null) + return false; + // + this.setTitle(m_Name); + initialMessage = m_messageText.toString(); + message.setContent(initialMessage); + + // Move from APanel.actionButton + if (m_pi == null) + m_pi = new WProcessInfo(m_Name, AD_Process_ID); + m_pi.setAD_User_ID (Env.getAD_User_ID(Env.getCtx())); + m_pi.setAD_Client_ID(Env.getAD_Client_ID(Env.getCtx())); + m_pi.setTitle(m_Name); + parameterPanel = new ProcessParameterPanel(m_WindowNo, m_pi, innerWidth); + centerPanel.getChildren().clear(); + if ( parameterPanel.init() ) { + centerPanel.appendChild(parameterPanel); + } else { + if (m_ShowHelp != null && m_ShowHelp.equals("N")) + autoStart = true; + + if (autoStart) + { + autoStart(); + return true; + } + } + + // Check if the process is a silent one + if (isValid() && m_ShowHelp != null && m_ShowHelp.equals("S")) + { + autoStart(); + return true; + } + + MProcess process = new MProcess(m_ctx, m_AD_Process_ID, null); + boolean isReport = (process.isReport() || process.getAD_ReportView_ID() > 0); + if (isReport && MSysConfig.getBooleanValue(MSysConfig.BACKGROUND_JOB_ALLOWED, false)) + { + Grid grid = GridFactory.newGridLayout(); + centerPanel.appendChild(grid); + grid.setInnerWidth(innerWidth); + + Columns columns = new Columns(); + grid.appendChild(columns); + Column col = new Column(); + col.setWidth("30%"); + columns.appendChild(col); + col = new Column(); + col.setWidth("70%"); + columns.appendChild(col); + + Rows rows = new Rows(); + grid.appendChild(rows); + + Row row = new Row(); + rows.appendChild(row); + + row.appendChild(new Space()); + runAsJobField = new Checkbox(); + runAsJobField.setLabel(Msg.getElement(m_ctx, MPInstance.COLUMNNAME_IsRunAsJob)); + row.appendChild(runAsJobField); + runAsJobField.addEventListener(Events.ON_CHECK, this); + + row = new Row(); + rows.appendChild(row); + + Div div = new Div(); + div.setStyle("text-align: right;"); + div.appendChild(new Label(Msg.getElement(m_ctx, MPInstance.COLUMNNAME_NotificationType))); + row.appendChild(div); + + MLookupInfo info = MLookupFactory.getLookup_List(Env.getLanguage(m_ctx), MPInstance.NOTIFICATIONTYPE_AD_Reference_ID); + notificationTypeField = new WTableDirEditor(MPInstance.COLUMNNAME_NotificationType, true, false, true, new MLookup(info, 0)); + Combobox combobox = notificationTypeField.getComponent(); + List items = combobox.getItems(); + for (int i = 0; i < items.size(); i++) { + ComboItem item = (ComboItem)items.get(i); + if (MPInstance.NOTIFICATIONTYPE_None.equals(item.getValue())) + combobox.removeItemAt(i); + } + + MUser user = MUser.get(m_ctx); + String notificationType = user.getNotificationType(); + if (!MPInstance.NOTIFICATIONTYPE_None.equals(notificationType)) + notificationTypeField.setValue(notificationType); + + row.appendChild(notificationTypeField.getComponent()); + runAsJobField.setChecked(MSysConfig.getBooleanValue(MSysConfig.BACKGROUND_JOB_BY_DEFAULT, false)); + notificationTypeField.getComponent().getParent().setVisible(runAsJobField.isChecked()); + } + + return true; + } + + protected void autoStart() + { + startProcess0(); + } + + public void onEvent(Event event) + { + Component component = event.getTarget(); + if (component == runAsJobField && event.getName().equals(Events.ON_CHECK)) + notificationTypeField.getComponent().getParent().setVisible(runAsJobField.isChecked()); + else if (event.getName().equals(ON_COMPLETE)) + onComplete(); + else if (event.getName().equals(ON_STATUS_UPDATE)) + onStatusUpdate(event); + } + + protected void startProcess() + { + if (!parameterPanel.validateParameters()) + return; + + startProcess0(); + } + + protected void cancelProcess() + { + m_cancel = true; + this.dispose(); + } + + protected BusyDialog createBusyDialog() + { + progressWindow = new BusyDialog(); + this.appendChild(progressWindow); + return progressWindow; + } + + protected void closeBusyDialog() + { + if (progressWindow != null) { + progressWindow.dispose(); + progressWindow = null; + } + } + + @Override + public void dispose() + { + m_valid = false; + } // dispose + + private void startProcess0() + { + if (!isBackgroundJob()) + getProcessInfo().setPrintPreview(true); + + lockUI(getProcessInfo()); + + downloadFiles = new ArrayList(); + + //use echo, otherwise lock ui wouldn't work + Clients.response(new AuEcho(this, isBackgroundJob() ? "runBackgroundJob" : "runProcess", this)); + } + + public void runProcess() + { + future = Adempiere.getThreadPoolExecutor().submit(new DesktopRunnable(new ProcessDialogRunnable(null), getDesktop())); + } + + public void runBackgroundJob() + { + Properties m_ctx = getCtx(); + ProcessInfo m_pi = getProcessInfo(); + MPInstance instance = null; + + try + { + int AD_Client_ID = Env.getAD_Client_ID(m_ctx); + int AD_User_ID = Env.getAD_User_ID(m_ctx); + + int count = new Query(m_ctx, MPInstance.Table_Name, "NVL(AD_User_ID,0)=? AND IsProcessing='Y'", null) + .setOnlyActiveRecords(true) + .setClient_ID() + .setParameters(AD_User_ID) + .count(); + if (count >= MSysConfig.getIntValue(MSysConfig.BACKGROUND_JOB_MAX_PER_USER, 5, AD_Client_ID)) + throw new IllegalStateException(Msg.getMsg(m_ctx, "BackgroundJobExceedMaxPerUser")); + + count = new Query(m_ctx, MPInstance.Table_Name, "IsProcessing='Y'", null) + .setOnlyActiveRecords(true) + .setClient_ID() + .count(); + if (count >= MSysConfig.getIntValue(MSysConfig.BACKGROUND_JOB_MAX_PER_CLIENT, 10, AD_Client_ID)) + throw new IllegalStateException(Msg.getMsg(m_ctx, "BackgroundJobExceedMaxPerClient")); + + count = new Query(m_ctx, MPInstance.Table_Name, "IsProcessing='Y'", null) + .setOnlyActiveRecords(true) + .count(); + if (count >= MSysConfig.getIntValue(MSysConfig.BACKGROUND_JOB_MAX_IN_SYSTEM, 20)) + throw new IllegalStateException(Msg.getMsg(m_ctx, "BackgroundJobExceedMaxInSystem")); + + instance = new MPInstance(m_ctx, m_pi.getAD_Process_ID(), m_pi.getRecord_ID()); + instance.setIsRunAsJob(true); + instance.setIsProcessing(true); + instance.setNotificationType(getNotificationType()); + instance.saveEx(); + + m_pi.setAD_PInstance_ID(instance.getAD_PInstance_ID()); + getParameterPanel().saveParameters(); + + MPInstance.publishChangedEvent(AD_User_ID); + Adempiere.getThreadPoolExecutor().schedule(new BackgroundJobRunnable(getCtx()), 1000, TimeUnit.MILLISECONDS); + + m_pi.setSummary(Msg.getMsg(m_ctx, "BackgroundJobScheduled")); + } catch (Exception e) { + m_pi.setSummary(e.getLocalizedMessage()); + m_pi.setError(true); + + if (instance != null) + { + instance.setIsProcessing(false); + instance.saveEx(); + } + } + finally { + unlockUI(m_pi); + + if (m_disposeOnComplete) + dispose(); + } + } + + private void onComplete() + { + ProcessInfo m_pi = getProcessInfo(); + + if (future != null) { + try { + future.get(); + } catch (Exception e) { + log.log(Level.SEVERE, e.getLocalizedMessage(), e); + if (!m_pi.isError()) { + m_pi.setSummary(e.getLocalizedMessage(), true); + } + } + } + future = null; + unlockUI(m_pi); + if (downloadFiles.size() > 0) { + MultiFileDownloadDialog downloadDialog = new MultiFileDownloadDialog(downloadFiles.toArray(new File[0])); + downloadDialog.setPage(getPage()); + downloadDialog.setTitle(m_pi.getTitle()); + Events.postEvent(downloadDialog, new Event(MultiFileDownloadDialog.ON_SHOW)); + } + + if (m_disposeOnComplete) + dispose(); + } + + private void onStatusUpdate(Event event) + { + String message = (String) event.getData(); + if (progressWindow != null) + progressWindow.statusUpdate(message); + } + + @Override + public void lockUI(ProcessInfo pi) { + if (m_locked || Executions.getCurrent() == null) + return; + m_locked = true; + showBusyDialog(); + } + + public abstract void showBusyDialog(); + + @Override + public void unlockUI(ProcessInfo pi) { + if (!m_locked) + return; + m_locked = false; + + if (Executions.getCurrent() == null) + { + Executions.schedule(getDesktop(), new EventListener() + { + @Override + public void onEvent(Event event) throws Exception { + doUnlockUI(); + } + }, new Event("onUnLockUI")); + } else { + doUnlockUI(); + } + } + + private void doUnlockUI() + { + hideBusyDialog(); + updateUI(); + } + + public abstract void hideBusyDialog(); + + public abstract void updateUI(); + + @Override + public boolean isUILocked() { + return m_locked; + } + + @Override + public void statusUpdate(String message) { + Desktop desktop = getDesktop(); + if (desktop != null && desktop.isAlive()) + Executions.schedule(desktop, this, new Event(ON_STATUS_UPDATE, this, message)); + } + + @Override + public void ask(final String message, final Callback callback) { + Executions.schedule(getDesktop(), new EventListener() { + @Override + public void onEvent(Event event) throws Exception { + FDialog.ask(getWindowNo(), null, message, callback); + } + }, new Event("onAsk")); + } + + @Override + public void download(File file) { + downloadFiles.add(file); + } + + /** + * + * @return ProcessInfo + */ + public ProcessInfo getProcessInfo() { + return m_pi; + } + + public void setProcessInfo(ProcessInfo pi) { + m_pi = pi; + } + + /** + * is dialog still valid + * @return boolean + */ + public boolean isValid() + { + return m_valid; + } + + /** + * @return true if user have press the cancel button to close the dialog + */ + public boolean isCancel() + { + return m_cancel; + } + + public Properties getCtx() + { + return m_ctx; + } + + public int getWindowNo() + { + return m_WindowNo; + } + + public int getAD_Process_ID() + { + return m_AD_Process_ID; + } + + public Html getMessage() + { + return message; + } + + public Panel getCenterPanel() + { + return centerPanel; + } + + public ProcessParameterPanel getParameterPanel() + { + return parameterPanel; + } + + public String getName() + { + return m_Name; + } + + public StringBuffer getMessageText() + { + return m_messageText; + } + + public void setMessageText(StringBuffer messageText) + { + this.m_messageText = messageText; + } + + public String getShowHelp() + { + return m_ShowHelp; + } + + public String getInitialMessage() + { + return initialMessage; + } + + public boolean isBackgroundJob() + { + return runAsJobField != null && runAsJobField.isChecked(); + } + + public String getNotificationType() + { + return (String) notificationTypeField.getValue(); + } + + public List getDownloadFiles() + { + return downloadFiles; + } + + private class ProcessDialogRunnable extends ContextRunnable + { + private Trx m_trx; + + private ProcessDialogRunnable(Trx trx) + { + super(); + m_trx = trx; + } + + protected void doRun() + { + ProcessInfo m_pi = getProcessInfo(); + try { + if (log.isLoggable(Level.INFO)) + log.log(Level.INFO, "Process Info=" + m_pi + " AD_Client_ID="+ Env.getAD_Client_ID(Env.getCtx())); + WProcessCtl.process(AbstractProcessDialog.this, getWindowNo(), getParameterPanel(), m_pi, m_trx); + } catch (Exception ex) { + m_pi.setError(true); + m_pi.setSummary(ex.getLocalizedMessage()); + log.log(Level.SEVERE, ex.getLocalizedMessage(), ex); + } finally { + Executions.schedule(getDesktop(), AbstractProcessDialog.this, new Event(ON_COMPLETE, AbstractProcessDialog.this, null)); + } + } + } + + private class BackgroundJobRunnable implements Runnable + { + private Properties m_ctx; + + private BackgroundJobRunnable(Properties ctx) + { + super(); + + m_ctx = new Properties(); + Env.setContext(m_ctx, "#AD_Client_ID", ctx.getProperty("#AD_Client_ID")); + Env.setContext(m_ctx, "#AD_Org_ID", ctx.getProperty("#AD_Org_ID")); + Env.setContext(m_ctx, "#AD_Role_ID", ctx.getProperty("#AD_Role_ID")); + Env.setContext(m_ctx, "#M_Warehouse_ID", ctx.getProperty("#M_Warehouse_ID")); + Env.setContext(m_ctx, "#AD_Language", ctx.getProperty("#AD_Language")); + Env.setContext(m_ctx, "#AD_User_ID", ctx.getProperty("#AD_User_ID")); + Env.setContext(m_ctx, "#Date", ctx.getProperty("#Date")); + } + + @Override + public void run() { + try { + ServerContext.setCurrentInstance(m_ctx); + doRun(); + } finally { + ServerContext.dispose(); + } + } + + private void doRun() + { + ProcessInfo m_pi = getProcessInfo(); + m_pi.setIsBatch(true); + + MPInstance instance = new MPInstance(m_ctx, m_pi.getAD_PInstance_ID(), null); + String notificationType = instance.getNotificationType(); + boolean sendEmail = notificationType.equals(MPInstance.NOTIFICATIONTYPE_EMail) || notificationType.equals(MPInstance.NOTIFICATIONTYPE_EMailPlusNotice); + boolean createNotice = notificationType.equals(MPInstance.NOTIFICATIONTYPE_Notice) || notificationType.equals(MPInstance.NOTIFICATIONTYPE_EMailPlusNotice); + + int AD_Client_ID = Env.getAD_Client_ID(m_ctx); + int AD_User_ID = Env.getAD_User_ID(m_ctx); + + try { + m_pi.setSummary(""); // reset summary + + MProcess process = new MProcess(m_ctx, m_pi.getAD_Process_ID(), null); + ServerProcessCtl.process(m_pi, null); + ProcessInfoUtil.setLogFromDB(m_pi); + if (!m_pi.isError()) + { + boolean isReport = (process.isReport() || process.getAD_ReportView_ID() > 0 || process.getJasperReport() != null || process.getAD_PrintFormat_ID() > 0); + if (isReport) + { + ReportEngine re = ReportEngine.get(m_ctx, m_pi); + if(re != null && re.getPrintFormat().getJasperProcess_ID() > 0) + { + ProcessInfo jasperpi = new ProcessInfo ("", re.getPrintFormat().getJasperProcess_ID()); + jasperpi.setIsBatch(true); + ServerProcessCtl.process(jasperpi, null); + File report = jasperpi.getPDFReport(); + if (report != null) + download(report); + } + else if (process.getJasperReport() != null) + { + download(m_pi.getPDFReport()); + } + else + { + if (re == null) + log.log(Level.SEVERE, "Cannot create Report AD_Process_ID=" + process.getAD_Process_ID() + " - " + process.getName()); + else + { + File report = re.getPDF(); + if (report != null) + download(report); + } + } + } + + File generatedFile = m_pi.isExport() ? m_pi.getExportFile() : m_pi.getPDFReport(); + if (generatedFile != null) + download(generatedFile); + } + + if (sendEmail) + { + MClient client = MClient.get(m_ctx, AD_Client_ID); + client.sendEMailAttachments(AD_User_ID, process.getName(), m_pi.getSummary() + " " + m_pi.getLogInfo(), getDownloadFiles()); + } + + if (createNotice) + { + MNote note = new MNote(m_ctx, "BackgroundJob", AD_User_ID, null); + note.setTextMsg(process.getName() + "\n" + m_pi.getSummary()); + note.setRecord(MPInstance.Table_ID, m_pi.getAD_PInstance_ID()); + note.saveEx(); + + MAttachment attachment = null; + if (getDownloadFiles().size() > 0) + { + attachment = note.createAttachment(); + for (File downloadFile : getDownloadFiles()) + attachment.addEntry(downloadFile); + } + String log = m_pi.getLogInfo(true); + if (log != null && log.trim().length() > 0) { + if (attachment == null) + attachment = note.createAttachment(); + attachment.addEntry("ProcessLog.html", log.getBytes("UTF-8")); + } + if (attachment != null) + attachment.saveEx(); + } + } catch (Exception e) { + log.log(Level.SEVERE, e.getLocalizedMessage()); + } finally { + instance.setIsProcessing(false); + instance.saveEx(); + + MPInstance.publishChangedEvent(AD_User_ID); + } + } + } +} \ No newline at end of file diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/ProcessDialog.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/ProcessDialog.java index 33a7b4fb16..3f25b8b06a 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/ProcessDialog.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/ProcessDialog.java @@ -1,91 +1,3 @@ -package org.adempiere.webui.apps; - -import static org.compiere.model.SystemIDs.PROCESS_C_INVOICE_GENERATE; -import static org.compiere.model.SystemIDs.PROCESS_M_INOUT_GENERATE; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; -import java.util.concurrent.Future; -import java.util.logging.Level; - -import org.adempiere.util.Callback; -import org.adempiere.util.ContextRunnable; -import org.adempiere.util.IProcessUI; -import org.adempiere.webui.LayoutUtils; -import org.adempiere.webui.component.Button; -import org.adempiere.webui.component.Combobox; -import org.adempiere.webui.component.ConfirmPanel; -import org.adempiere.webui.component.Grid; -import org.adempiere.webui.component.GridFactory; -import org.adempiere.webui.component.Label; -import org.adempiere.webui.component.Mask; -import org.adempiere.webui.component.Panel; -import org.adempiere.webui.component.Rows; -import org.adempiere.webui.component.Window; -import org.adempiere.webui.desktop.IDesktop; -import org.adempiere.webui.factory.ButtonFactory; -import org.adempiere.webui.panel.IHelpContext; -import org.adempiere.webui.part.WindowContainer; -import org.adempiere.webui.process.WProcessInfo; -import org.adempiere.webui.session.SessionManager; -import org.adempiere.webui.theme.ThemeManager; -import org.adempiere.webui.window.FDialog; -import org.adempiere.webui.window.MultiFileDownloadDialog; -import org.adempiere.webui.window.SimplePDFViewer; -import org.compiere.Adempiere; -import org.compiere.model.MPInstance; -import org.compiere.model.MPInstancePara; -import org.compiere.model.MProcess; -import org.compiere.model.X_AD_CtxHelp; -import org.compiere.print.ReportEngine; -import org.compiere.process.ProcessInfo; -import org.compiere.process.ProcessInfoLog; -import org.compiere.process.ProcessInfoUtil; -import org.compiere.util.AdempiereSystemError; -import org.compiere.util.CLogger; -import org.compiere.util.DB; -import org.compiere.util.DisplayType; -import org.compiere.util.Env; -import org.compiere.util.Msg; -import org.compiere.util.Util; -import org.zkoss.zhtml.Table; -import org.zkoss.zhtml.Td; -import org.zkoss.zhtml.Text; -import org.zkoss.zhtml.Tr; -import org.zkoss.zk.au.out.AuEcho; -import org.zkoss.zk.au.out.AuScript; -import org.zkoss.zk.ui.Component; -import org.zkoss.zk.ui.Desktop; -import org.zkoss.zk.ui.Executions; -import org.zkoss.zk.ui.event.Event; -import org.zkoss.zk.ui.event.EventListener; -import org.zkoss.zk.ui.event.Events; -import org.zkoss.zk.ui.util.Clients; -import org.zkoss.zul.A; -import org.zkoss.zul.Borderlayout; -import org.zkoss.zul.Center; -import org.zkoss.zul.Comboitem; -import org.zkoss.zul.Div; -import org.zkoss.zul.Hbox; -import org.zkoss.zul.Html; -import org.zkoss.zul.North; -import org.zkoss.zul.Row; -import org.zkoss.zul.South; - -import com.lowagie.text.Document; -import com.lowagie.text.pdf.PdfContentByte; -import com.lowagie.text.pdf.PdfImportedPage; -import com.lowagie.text.pdf.PdfReader; -import com.lowagie.text.pdf.PdfWriter; - /****************************************************************************** * Product: Adempiere ERP & CRM Smart Business Solution * * Copyright (C) 2007 Low Heng Sin * @@ -100,8 +12,80 @@ import com.lowagie.text.pdf.PdfWriter; * with this program; if not, write to the Free Software Foundation, Inc., * * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * *****************************************************************************/ +package org.adempiere.webui.apps; +import static org.compiere.model.SystemIDs.PROCESS_C_INVOICE_GENERATE; +import static org.compiere.model.SystemIDs.PROCESS_M_INOUT_GENERATE; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; + +import org.adempiere.util.Callback; +import org.adempiere.webui.LayoutUtils; +import org.adempiere.webui.component.Button; +import org.adempiere.webui.component.Combobox; +import org.adempiere.webui.component.ConfirmPanel; +import org.adempiere.webui.component.Grid; +import org.adempiere.webui.component.GridFactory; +import org.adempiere.webui.component.Mask; +import org.adempiere.webui.component.Panel; +import org.adempiere.webui.component.Row; +import org.adempiere.webui.component.Rows; +import org.adempiere.webui.component.Window; +import org.adempiere.webui.desktop.IDesktop; +import org.adempiere.webui.factory.ButtonFactory; +import org.adempiere.webui.panel.IHelpContext; +import org.adempiere.webui.part.WindowContainer; +import org.adempiere.webui.process.WProcessInfo; +import org.adempiere.webui.session.SessionManager; +import org.adempiere.webui.theme.ThemeManager; +import org.adempiere.webui.window.FDialog; +import org.adempiere.webui.window.SimplePDFViewer; +import org.compiere.model.MPInstance; +import org.compiere.model.MPInstancePara; +import org.compiere.model.MProcess; +import org.compiere.model.X_AD_CtxHelp; +import org.compiere.print.ReportEngine; +import org.compiere.process.ProcessInfo; +import org.compiere.process.ProcessInfoLog; +import org.compiere.process.ProcessInfoUtil; +import org.compiere.util.AdempiereSystemError; +import org.compiere.util.CLogger; +import org.compiere.util.DisplayType; +import org.compiere.util.Env; +import org.compiere.util.Msg; +import org.compiere.util.Util; +import org.zkoss.zhtml.Table; +import org.zkoss.zhtml.Td; +import org.zkoss.zhtml.Text; +import org.zkoss.zhtml.Tr; +import org.zkoss.zk.au.out.AuEcho; +import org.zkoss.zk.au.out.AuScript; +import org.zkoss.zk.ui.Component; +import org.zkoss.zk.ui.event.Event; +import org.zkoss.zk.ui.event.EventListener; +import org.zkoss.zk.ui.event.Events; +import org.zkoss.zk.ui.util.Clients; +import org.zkoss.zul.A; +import org.zkoss.zul.Borderlayout; +import org.zkoss.zul.Center; +import org.zkoss.zul.Comboitem; +import org.zkoss.zul.Div; +import org.zkoss.zul.Hbox; +import org.zkoss.zul.Label; +import org.zkoss.zul.North; +import org.zkoss.zul.South; + +import com.lowagie.text.Document; +import com.lowagie.text.pdf.PdfContentByte; +import com.lowagie.text.pdf.PdfImportedPage; +import com.lowagie.text.pdf.PdfReader; +import com.lowagie.text.pdf.PdfWriter; /** * Dialog to Start process or report. @@ -113,21 +97,30 @@ import com.lowagie.text.pdf.PdfWriter; * @author arboleda - globalqss * - Implement ShowHelp option on processes and reports */ -public class ProcessDialog extends Window implements EventListener, IProcessUI, IHelpContext +public class ProcessDialog extends AbstractProcessDialog implements EventListener, IHelpContext { /** - * + * generate serial version ID */ - private static final long serialVersionUID = -899849696748614034L; - + private static final long serialVersionUID = 3329046204196602797L; + private static final String MESSAGE_DIV_STYLE = "max-height: 150pt; overflow: auto; margin: 10px;"; + + /** Logger */ + private static CLogger log = CLogger.getCLogger(ProcessDialog.class); + // + private Div messageDiv; private Center center; private Table logMessageTable; private North north; - - private List downloadFiles; + private int[] m_ids = null; + private Button bOK = null; + + private boolean isParameterPage = true; + private Mask mask; + private boolean showLastRun = false; private Grid southRowPanel = GridFactory.newGridLayout(); @@ -147,20 +140,19 @@ public class ProcessDialog extends Window implements EventListener, IProc public ProcessDialog (int AD_Process_ID, boolean isSOTrx) { log.info("Process=" + AD_Process_ID ); - m_ctx = Env.getCtx(); - m_WindowNo = SessionManager.getAppDesktop().registerWindow(this); - this.setAttribute(IDesktop.WINDOWNO_ATTRIBUTE, m_WindowNo); - m_AD_Process_ID = AD_Process_ID; - Env.setContext(Env.getCtx(), m_WindowNo, "IsSOTrx", isSOTrx ? "Y" : "N"); + int WindowNo = SessionManager.getAppDesktop().registerWindow(this); + this.setAttribute(IDesktop.WINDOWNO_ATTRIBUTE, WindowNo); + Env.setContext(Env.getCtx(), WindowNo, "IsSOTrx", isSOTrx ? "Y" : "N"); try { - MProcess process = new MProcess(m_ctx, m_AD_Process_ID, null); + MProcess process = MProcess.get(Env.getCtx(), AD_Process_ID); int count = process.getParameters().length; if (count > 0) showLastRun = true; initComponents(); - init(); + init(Env.getCtx(), WindowNo, AD_Process_ID, null, "70%", false, false); + querySaved(); addEventListener(WindowContainer.ON_WINDOW_CONTAINER_SELECTION_CHANGED_EVENT, this); } catch(Exception ex) @@ -169,13 +161,26 @@ public class ProcessDialog extends Window implements EventListener, IProc } } // ProcessDialog + private void querySaved() + { + //user query + savedParams = MPInstance.get(Env.getCtx(), getAD_Process_ID(), Env.getContextAsInt(Env.getCtx(), "#AD_User_ID")); + fSavedName.removeAllItems(); + for (MPInstance instance : savedParams) + { + String queries = instance.get_ValueAsString("Name"); + fSavedName.appendItem(queries); + } + + fSavedName.setValue(""); + } + private void initComponents() { this.setStyle("position: absolute; width: 100%; height: 100%"); Borderlayout layout = new Borderlayout(); layout.setStyle("position: absolute; width: 100%; height: 100%; border: none;"); messageDiv = new Div(); - message = new Html(); - messageDiv.appendChild(message); + messageDiv.appendChild(getMessage()); messageDiv.setStyle(MESSAGE_DIV_STYLE); messageDiv.setId("message"); @@ -185,12 +190,11 @@ public class ProcessDialog extends Window implements EventListener, IProc north.setAutoscroll(true); north.setStyle("border: none;"); - centerPanel = new Panel(); center = new Center(); layout.appendChild(center); - center.appendChild(centerPanel); - centerPanel.setHflex("1"); - centerPanel.setVflex("1"); + center.appendChild(getCenterPanel()); + getCenterPanel().setHflex("1"); + getCenterPanel().setVflex("1"); center.setAutoscroll(true); center.setStyle("border: none"); @@ -199,6 +203,7 @@ public class ProcessDialog extends Window implements EventListener, IProc Hbox hBox = new Hbox(); + lSaved = new Label(Msg.getMsg(Env.getCtx(), "SavedParameter")); hBox.appendChild(lSaved); fSavedName.addEventListener(Events.ON_CHANGE, this); hBox.appendChild(fSavedName); @@ -218,8 +223,6 @@ public class ProcessDialog extends Window implements EventListener, IProc Panel confParaPanel =new Panel(); confParaPanel.setAlign("right"); - @SuppressWarnings("unused") - String label = Msg.getMsg(Env.getCtx(), "Start"); // Invert - Unify OK/Cancel IDEMPIERE-77 bOK = ButtonFactory.createNamedButton(ConfirmPanel.A_OK, true, true); bOK.setId("Ok"); @@ -239,45 +242,14 @@ public class ProcessDialog extends Window implements EventListener, IProc this.appendChild(layout); } - private int m_WindowNo; - private Properties m_ctx; - private int m_AD_Process_ID; - private String m_Name = null; - - private int[] m_ids = null; - private StringBuffer m_messageText = new StringBuffer(); - private String m_ShowHelp = null; // Determine if a Help Process Window is shown - - private Panel centerPanel = null; - private Html message = null; - private Button bOK = null; private Button bCancel = null; - - private boolean valid = true; - - /** Logger */ - private static CLogger log = CLogger.getCLogger(ProcessDialog.class); - // - private ProcessParameterPanel parameterPanel = null; - - private ProcessInfo m_pi = null; - private boolean m_isLocked = false; - private boolean isParameterPage = true; - private String initialMessage; - private BusyDialog progressWindow; - private Future future; - private ProcessDialogRunnable processDialogRunnable; - private Mask mask; - private static final String ON_STATUS_UPDATE = "onStatusUpdate"; - private static final String ON_COMPLETE = "onComplete"; - //saved parameters private Combobox fSavedName=new Combobox(); private Button bSave=ButtonFactory.createNamedButton("Save"); private Button bDelete=ButtonFactory.createNamedButton("Delete"); private List savedParams; - private Label lSaved=new Label(Msg.getMsg(Env.getCtx(), "SavedParameter")); + private Label lSaved; /** * Set Visible @@ -294,153 +266,9 @@ public class ProcessDialog extends Window implements EventListener, IProc */ public void dispose() { - SessionManager.getAppDesktop().closeWindow(m_WindowNo); - valid = false; + super.dispose(); + SessionManager.getAppDesktop().closeWindow(getWindowNo()); }// dispose - - /** - * Dynamic Init - * @return true, if there is something to process (start from menu) - */ - public boolean init() - { - log.config(""); - // - boolean trl = !Env.isBaseLanguage(m_ctx, "AD_Process"); - String sql = "SELECT Name, Description, Help, IsReport, ShowHelp " - + "FROM AD_Process " - + "WHERE AD_Process_ID=?"; - if (trl) - sql = "SELECT t.Name, t.Description, t.Help, p.IsReport, p.ShowHelp " - + "FROM AD_Process p, AD_Process_Trl t " - + "WHERE p.AD_Process_ID=t.AD_Process_ID" - + " AND p.AD_Process_ID=? AND t.AD_Language=?"; - - PreparedStatement pstmt = null; - ResultSet rs = null; - try - { - pstmt = DB.prepareStatement(sql, null); - pstmt.setInt(1, m_AD_Process_ID); - if (trl) - pstmt.setString(2, Env.getAD_Language(m_ctx)); - rs = pstmt.executeQuery(); - if (rs.next()) - { - m_Name = rs.getString(1); - m_ShowHelp = rs.getString(5); - // - m_messageText.append(""); - String s = rs.getString(2); // Description - if (rs.wasNull()) - m_messageText.append(Msg.getMsg(m_ctx, "StartProcess?")); - else - m_messageText.append(s); - m_messageText.append(""); - - s = rs.getString(3); // Help - if (!rs.wasNull()) - m_messageText.append("

").append(s).append("

"); - } - } - catch (SQLException e) - { - log.log(Level.SEVERE, sql, e); - return false; - } - finally - { - DB.close(rs, pstmt); - } - - if (m_Name == null) - return false; - // - this.setTitle(m_Name); - initialMessage = m_messageText.toString(); - message.setContent(initialMessage); - bOK.setLabel(Msg.getMsg(Env.getCtx(), "Start")); - - // Move from APanel.actionButton - m_pi = new WProcessInfo(m_Name, m_AD_Process_ID); - m_pi.setAD_User_ID (Env.getAD_User_ID(Env.getCtx())); - m_pi.setAD_Client_ID(Env.getAD_Client_ID(Env.getCtx())); - parameterPanel = new ProcessParameterPanel(m_WindowNo, m_pi, "70%"); - centerPanel.getChildren().clear(); - if ( parameterPanel.init() ) { - centerPanel.appendChild(parameterPanel); - } else { - if (m_ShowHelp != null && m_ShowHelp.equals("N")) { - startProcess(); - } - } - - // Check if the process is a silent one - if(m_ShowHelp != null && m_ShowHelp.equals("S")) - { - startProcess(); - } - querySaved(); - return true; - } // init - - private void querySaved() - { - //user query - savedParams = MPInstance.get(Env.getCtx(), m_AD_Process_ID, Env.getContextAsInt(Env.getCtx(), "#AD_User_ID")); - fSavedName.removeAllItems(); - for (MPInstance instance : savedParams) - { - String queries = instance.get_ValueAsString("Name"); - fSavedName.appendItem(queries); - } - - fSavedName.setValue(""); - } - - public void startProcess() - { - m_pi.setPrintPreview(true); - - this.lockUI(m_pi); - - downloadFiles = new ArrayList(); - - Clients.response(new AuEcho(this, "runProcess", null)); - } - - public void runProcess() { - processDialogRunnable = new ProcessDialogRunnable(); - future = Adempiere.getThreadPoolExecutor().submit(new DesktopRunnable(processDialogRunnable, getDesktop())); - } - - private void onComplete() { - if (future != null) { - try { - future.get(); - } catch (Exception e) { - log.log(Level.SEVERE, e.getLocalizedMessage(), e); - if (!m_pi.isError()) { - m_pi.setSummary(e.getLocalizedMessage(), true); - } - } - } - future = null; - processDialogRunnable = null; - unlockUI(m_pi); - if (downloadFiles.size() > 0) { - MultiFileDownloadDialog downloadDialog = new MultiFileDownloadDialog(downloadFiles.toArray(new File[0])); - downloadDialog.setPage(this.getPage()); - downloadDialog.setTitle(m_pi.getTitle()); - Events.postEvent(downloadDialog, new Event(MultiFileDownloadDialog.ON_SHOW)); - } - } - - private void onStatusUpdate(Event event) { - String message = (String) event.getData(); - if (progressWindow != null) - progressWindow.statusUpdate(message); - } public void onEvent(Event event) { Component component = event.getTarget(); @@ -457,15 +285,13 @@ public class ProcessDialog extends Window implements EventListener, IProc } else if (component instanceof Button) { Button element = (Button)component; if ("Ok".equalsIgnoreCase(element.getId())) { - if (isParameterPage) { - if (!parameterPanel.validateParameters()) - return; - this.startProcess(); - } + if (isParameterPage) + startProcess(); else restart(); } else if ("Cancel".equalsIgnoreCase(element.getId())) { - this.dispose(); + cancelProcess(); + } else if (event.getTarget().equals(bSave) && fSavedName != null && !lastRun) { @@ -473,13 +299,13 @@ public class ProcessDialog extends Window implements EventListener, IProc if (fSavedName.getSelectedIndex() > -1 && savedParams != null) { for (int i = 0; i < savedParams.size(); i++) { if (savedParams.get(i).getName().equals(saveName)) { - m_pi.setAD_PInstance_ID(savedParams.get(i) + getProcessInfo().setAD_PInstance_ID(savedParams.get(i) .getAD_PInstance_ID()); for (MPInstancePara para : savedParams.get(i) .getParameters()) { para.deleteEx(true); } - parameterPanel.saveParameters(); + getParameterPanel().saveParameters(); } } } @@ -488,13 +314,13 @@ public class ProcessDialog extends Window implements EventListener, IProc MPInstance instance = null; try { instance = new MPInstance(Env.getCtx(), - m_pi.getAD_Process_ID(), m_pi.getRecord_ID()); + getProcessInfo().getAD_Process_ID(), getProcessInfo().getRecord_ID()); instance.setName(saveName); instance.saveEx(); - m_pi.setAD_PInstance_ID(instance.getAD_PInstance_ID()); + getProcessInfo().setAD_PInstance_ID(instance.getAD_PInstance_ID()); // Get Parameters - if (parameterPanel != null) { - if (!parameterPanel.saveParameters()) { + if (getParameterPanel() != null) { + if (!getParameterPanel().saveParameters()) { throw new AdempiereSystemError(Msg.getMsg( Env.getCtx(), "SaveParameterError")); } @@ -520,12 +346,8 @@ public class ProcessDialog extends Window implements EventListener, IProc } querySaved(); } - } else if (event.getName().equals(ON_STATUS_UPDATE)) { - onStatusUpdate(event); - } else if (event.getName().equals(ON_COMPLETE)) { - onComplete(); } else if (event.getName().equals(WindowContainer.ON_WINDOW_CONTAINER_SELECTION_CHANGED_EVENT)) { - SessionManager.getAppDesktop().updateHelpContext(X_AD_CtxHelp.CTXTYPE_Process, m_AD_Process_ID); + SessionManager.getAppDesktop().updateHelpContext(X_AD_CtxHelp.CTXTYPE_Process, getAD_Process_ID()); } else if (event.getTarget().equals(fSavedName)) { if (savedParams != null && saveName != null) { for (int i = 0; i < savedParams.size(); i++) { @@ -538,6 +360,8 @@ public class ProcessDialog extends Window implements EventListener, IProc bSave.setEnabled(enabled && !lastRun); bDelete.setEnabled(enabled && fSavedName.getSelectedIndex() > -1 && !lastRun); + } else { + super.onEvent(event); } } @@ -555,7 +379,7 @@ public class ProcessDialog extends Window implements EventListener, IProc } private void loadSavedParams(MPInstance instance) { - parameterPanel.loadParameters(instance); + getParameterPanel().loadParameters(instance); } private void doOnClick(A btn) { @@ -575,19 +399,10 @@ public class ProcessDialog extends Window implements EventListener, IProc } } - - public void lockUI(ProcessInfo pi) { - if (m_isLocked || Executions.getCurrent() == null) return; - - m_isLocked = true; - - showBusyDialog(); - } - - private void showBusyDialog() { - progressWindow = new BusyDialog(); + @Override + public void showBusyDialog() { + BusyDialog progressWindow = createBusyDialog(); progressWindow.setStyle("position: absolute;"); - this.appendChild(progressWindow); showBusyMask(progressWindow); LayoutUtils.openOverlappedWindow(this, progressWindow, "middle_center"); } @@ -599,7 +414,7 @@ public class ProcessDialog extends Window implements EventListener, IProc return mask; } - public void showBusyMask(Window window) { + private void showBusyMask(Window window) { getParent().appendChild(getMask()); StringBuilder script = new StringBuilder("var w=zk.Widget.$('#"); script.append(getParent().getUuid()).append("');"); @@ -610,16 +425,9 @@ public class ProcessDialog extends Window implements EventListener, IProc } Clients.response(new AuScript(script.toString())); } - - public void unlockUI(ProcessInfo pi) { - if (!m_isLocked || Executions.getCurrent() == null) return; - m_isLocked = false; - hideBusyDialog(); - updateUI(pi); - } - - public void hideBusyMask() { + private void hideBusyMask() + { if (mask != null && mask.getParent() != null) { mask.detach(); StringBuilder script = new StringBuilder("var w=zk.Widget.$('#"); @@ -628,20 +436,21 @@ public class ProcessDialog extends Window implements EventListener, IProc } } - private void hideBusyDialog() { + @Override + public void hideBusyDialog() + { hideBusyMask(); - if (progressWindow != null) { - progressWindow.dispose(); - progressWindow = null; - } + closeBusyDialog(); } - private void updateUI(ProcessInfo pi) { + @Override + public void updateUI() { + ProcessInfo pi = getProcessInfo(); ProcessInfoUtil.setLogFromDB(pi); - m_messageText.append("

** ") + getMessageText().append("

** ") .append(pi.getSummary()) .append("

"); - message.setContent(m_messageText.toString()); + getMessage().setContent(getMessageText().toString()); // Add Log info with zoom on record id appendRecordLogInfo(pi.getLogs()); @@ -652,7 +461,7 @@ public class ProcessDialog extends Window implements EventListener, IProc m_ids = pi.getIDs(); //move message div to center to give more space to display potentially very long log info - centerPanel.detach(); + getCenterPanel().detach(); messageDiv.detach(); messageDiv.setStyle(""); north.setVisible(false); @@ -747,8 +556,8 @@ public class ProcessDialog extends Window implements EventListener, IProc } private void restart() { - m_messageText = new StringBuffer(initialMessage); - message.setContent(initialMessage); + setMessageText(new StringBuffer(getInitialMessage())); + getMessage().setContent(getInitialMessage()); north.setVisible(true); messageDiv.detach(); @@ -758,7 +567,7 @@ public class ProcessDialog extends Window implements EventListener, IProc messageDiv.setStyle(MESSAGE_DIV_STYLE); north.appendChild(messageDiv); - center.appendChild(centerPanel); + center.appendChild(getCenterPanel()); isParameterPage = true; @@ -766,10 +575,11 @@ public class ProcessDialog extends Window implements EventListener, IProc bOK.setImage(ThemeManager.getThemeResource("images/Ok16.png")); //recreate process info - m_pi = new WProcessInfo(m_Name, m_AD_Process_ID); + ProcessInfo m_pi = new WProcessInfo(getName(), getAD_Process_ID()); m_pi.setAD_User_ID (Env.getAD_User_ID(Env.getCtx())); m_pi.setAD_Client_ID(Env.getAD_Client_ID(Env.getCtx())); - parameterPanel.setProcessInfo(m_pi); + setProcessInfo(m_pi); + getParameterPanel().setProcessInfo(m_pi); m_ids = null; @@ -781,7 +591,7 @@ public class ProcessDialog extends Window implements EventListener, IProc // if (!afterProcessTask()) { // If the process is a silent one and no errors occured, close the dialog - if(m_ShowHelp != null && m_ShowHelp.equals("S")) + if(getShowHelp() != null && getShowHelp().equals("S")) this.dispose(); } } @@ -796,12 +606,12 @@ public class ProcessDialog extends Window implements EventListener, IProc { log.config(""); // Print invoices - if (m_AD_Process_ID == PROCESS_C_INVOICE_GENERATE) + if (getAD_Process_ID() == PROCESS_C_INVOICE_GENERATE) { printInvoices(); return true; } - else if (m_AD_Process_ID == PROCESS_M_INOUT_GENERATE) + else if (getAD_Process_ID() == PROCESS_M_INOUT_GENERATE) { printShipments(); return true; @@ -821,12 +631,12 @@ public class ProcessDialog extends Window implements EventListener, IProc { if (m_ids == null) return; - FDialog.ask(m_WindowNo, this, "PrintShipments", new Callback() { + FDialog.ask(getWindowNo(), this, "PrintShipments", new Callback() { @Override public void onCallback(Boolean result) { if (result) { - m_messageText.append("

").append(Msg.getMsg(Env.getCtx(), "PrintShipments")).append("

"); - message.setContent(m_messageText.toString()); + getMessageText().append("

").append(Msg.getMsg(Env.getCtx(), "PrintShipments")).append("

"); + getMessage().setContent(getMessageText().toString()); showBusyDialog(); Clients.response(new AuEcho(ProcessDialog.this, "onPrintShipments", null)); } @@ -872,7 +682,7 @@ public class ProcessDialog extends Window implements EventListener, IProc document.close(); hideBusyDialog(); - Window win = new SimplePDFViewer(m_pi.getTitle(), new FileInputStream(outFile)); + Window win = new SimplePDFViewer(getProcessInfo().getTitle(), new FileInputStream(outFile)); SessionManager.getAppDesktop().showWindow(win, "center"); } catch (Exception e) { log.log(Level.SEVERE, e.getLocalizedMessage(), e); @@ -883,7 +693,7 @@ public class ProcessDialog extends Window implements EventListener, IProc } else if (pdfList.size() > 0) { hideBusyDialog(); try { - Window win = new SimplePDFViewer(m_pi.getTitle(), new FileInputStream(pdfList.get(0))); + Window win = new SimplePDFViewer(getProcessInfo().getTitle(), new FileInputStream(pdfList.get(0))); SessionManager.getAppDesktop().showWindow(win, "center"); } catch (Exception e) { @@ -892,7 +702,7 @@ public class ProcessDialog extends Window implements EventListener, IProc } // If the process is a silent one and no errors occured, close the dialog - if(m_ShowHelp != null && m_ShowHelp.equals("S")) + if(getShowHelp() != null && getShowHelp().equals("S")) this.dispose(); } @@ -903,14 +713,14 @@ public class ProcessDialog extends Window implements EventListener, IProc { if (m_ids == null) return; - FDialog.ask(m_WindowNo, this, "PrintInvoices", new Callback() { + FDialog.ask(getWindowNo(), this, "PrintInvoices", new Callback() { @Override public void onCallback(Boolean result) { if (result) { - m_messageText.append("

").append(Msg.getMsg(Env.getCtx(), "PrintInvoices")).append("

"); - message.setContent(m_messageText.toString()); + getMessageText().append("

").append(Msg.getMsg(Env.getCtx(), "PrintInvoices")).append("

"); + getMessage().setContent(getMessageText().toString()); showBusyDialog(); Clients.response(new AuEcho(ProcessDialog.this, "onPrintInvoices", null)); } @@ -954,7 +764,7 @@ public class ProcessDialog extends Window implements EventListener, IProc document.close(); hideBusyDialog(); - Window win = new SimplePDFViewer(m_pi.getTitle(), new FileInputStream(outFile)); + Window win = new SimplePDFViewer(getProcessInfo().getTitle(), new FileInputStream(outFile)); SessionManager.getAppDesktop().showWindow(win, "center"); } catch (Exception e) { log.log(Level.SEVERE, e.getLocalizedMessage(), e); @@ -965,7 +775,7 @@ public class ProcessDialog extends Window implements EventListener, IProc } else if (pdfList.size() > 0) { hideBusyDialog(); try { - Window win = new SimplePDFViewer(m_pi.getTitle(), new FileInputStream(pdfList.get(0))); + Window win = new SimplePDFViewer(getProcessInfo().getTitle(), new FileInputStream(pdfList.get(0))); SessionManager.getAppDesktop().showWindow(win, "center"); } catch (Exception e) { @@ -974,52 +784,8 @@ public class ProcessDialog extends Window implements EventListener, IProc } // If the process is a silent one and no errors occured, close the dialog - if(m_ShowHelp != null && m_ShowHelp.equals("S")) + if(getShowHelp() != null && getShowHelp().equals("S")) this.dispose(); } - - public boolean isValid() { - return valid; - } - - public boolean isUILocked() { - return m_isLocked; - } - class ProcessDialogRunnable extends ContextRunnable { - ProcessDialogRunnable() { - super(); - } - - protected void doRun() { - try { - if (log.isLoggable(Level.INFO))log.log(Level.INFO, "Process Info="+m_pi+" AD_Client_ID="+Env.getAD_Client_ID(Env.getCtx())); - WProcessCtl.process(ProcessDialog.this, m_WindowNo, parameterPanel, m_pi, null); - } finally { - Executions.schedule(getDesktop(), ProcessDialog.this, new Event(ON_COMPLETE, ProcessDialog.this, null)); - } - } - } - - @Override - public void statusUpdate(String message) { - Desktop desktop = getDesktop(); - if (desktop != null && desktop.isAlive()) - Executions.schedule(desktop, this, new Event(ON_STATUS_UPDATE, this, message)); - } - - @Override - public void ask(final String message, final Callback callback) { - Executions.schedule(getDesktop(), new EventListener() { - @Override - public void onEvent(Event event) throws Exception { - FDialog.ask(m_WindowNo, null, message, callback); - } - }, new Event("onAsk")); - } - - @Override - public void download(File file) { - downloadFiles.add(file); - } } // ProcessDialog diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/ProcessModalDialog.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/ProcessModalDialog.java index d6fb4c02af..d2f3a7b0bc 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/ProcessModalDialog.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/ProcessModalDialog.java @@ -16,45 +16,24 @@ *****************************************************************************/ package org.adempiere.webui.apps; -import java.io.File; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; -import java.util.concurrent.Future; import java.util.logging.Level; -import org.adempiere.util.Callback; -import org.adempiere.util.ContextRunnable; -import org.adempiere.util.IProcessUI; import org.adempiere.webui.LayoutUtils; import org.adempiere.webui.component.Button; import org.adempiere.webui.component.ConfirmPanel; -import org.adempiere.webui.component.Panel; import org.adempiere.webui.component.VerticalBox; import org.adempiere.webui.component.Window; import org.adempiere.webui.event.DialogEvents; import org.adempiere.webui.factory.ButtonFactory; -import org.adempiere.webui.window.FDialog; -import org.adempiere.webui.window.MultiFileDownloadDialog; -import org.compiere.Adempiere; import org.compiere.process.ProcessInfo; import org.compiere.util.CLogger; -import org.compiere.util.DB; import org.compiere.util.Env; -import org.compiere.util.Msg; -import org.zkoss.zk.au.out.AuEcho; import org.zkoss.zk.ui.Component; -import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.Events; -import org.zkoss.zk.ui.util.Clients; import org.zkoss.zul.Div; import org.zkoss.zul.Hbox; -import org.zkoss.zul.Html; import org.zkoss.zul.Vlayout; /** @@ -68,20 +47,18 @@ import org.zkoss.zul.Vlayout; * @author arboleda - globalqss * - Implement ShowHelp option on processes and reports */ -public class ProcessModalDialog extends Window implements EventListener, IProcessUI, DialogEvents +public class ProcessModalDialog extends AbstractProcessDialog implements EventListener, DialogEvents { /** * */ - private static final long serialVersionUID = -3708004619583382450L; + private static final long serialVersionUID = -3260639688339379279L; - private static final String ON_STATUS_UPDATE = "onStatusUpdate"; - private static final String ON_COMPLETE = "onComplete"; - - private boolean m_autoStart; private VerticalBox dialogBody; - - private List downloadFiles; + + /** Logger */ + private static CLogger log = CLogger.getCLogger(ProcessModalDialog.class); + // /** * @param aProcess @@ -102,10 +79,7 @@ public class ProcessModalDialog extends Window implements EventListener, */ public ProcessModalDialog(EventListener listener, int WindowNo, ProcessInfo pi, boolean autoStart) { - m_ctx = Env.getCtx(); - m_WindowNo = WindowNo; - m_pi = pi; - m_autoStart = autoStart; + super(); if (listener != null) { @@ -116,7 +90,7 @@ public class ProcessModalDialog extends Window implements EventListener, try { initComponents(); - init(); + init(Env.getCtx(), WindowNo, pi.getAD_Process_ID(), pi, "100%", autoStart, true); } catch(Exception ex) { @@ -172,12 +146,10 @@ public class ProcessModalDialog extends Window implements EventListener, dialogBody.appendChild(dialogContent); Div div = new Div(); div.setId("message"); - message = new Html(); - div.appendChild(message); + div.appendChild(getMessage()); div.setStyle("max-height: 150pt; overflow: auto;"); dialogContent.appendChild(div); - centerPanel = new Panel(); - dialogContent.appendChild(centerPanel); + dialogContent.appendChild(getCenterPanel()); Hbox hbox = new Hbox(); hbox.setWidth("100%"); hbox.setSclass("dialog-footer"); @@ -198,28 +170,6 @@ public class ProcessModalDialog extends Window implements EventListener, } - private int m_WindowNo; - private Properties m_ctx; - private String m_Name = null; - private StringBuffer m_messageText = new StringBuffer(); - private String m_ShowHelp = null; // Determine if a Help Process Window is shown - private boolean m_valid = true; - private boolean m_cancel = false; - - private Panel centerPanel = null; - private Html message = null; - - /** Logger */ - private static CLogger log = CLogger.getCLogger(ProcessModalDialog.class); - // - private ProcessParameterPanel parameterPanel = null; - - private ProcessInfo m_pi = null; - private BusyDialog progressWindow; - private boolean isLocked = false; - private org.adempiere.webui.apps.ProcessModalDialog.ProcessDialogRunnable processDialogRunnable; - private Future future; - /** * Set Visible * (set focus to OK if visible) @@ -235,158 +185,39 @@ public class ProcessModalDialog extends Window implements EventListener, */ public void dispose() { - parameterPanel.restoreContext(); - m_valid = false; + super.dispose(); + getParameterPanel().restoreContext(); this.detach(); } // dispose - /** - * is dialog still valid - * @return boolean - */ - public boolean isValid() + @Override + public void autoStart() { - return m_valid; + this.getFirstChild().setVisible(false); + super.autoStart(); } - /** - * @return true if user have press the cancel button to close the dialog - */ - public boolean isCancel() - { - return m_cancel; - } - - /** - * Dynamic Init - * @return true, if there is something to process (start from menu) - */ - public boolean init() - { - log.config(""); - // - boolean trl = !Env.isBaseLanguage(m_ctx, "AD_Process"); - String sql = "SELECT Name, Description, Help, IsReport, ShowHelp " - + "FROM AD_Process " - + "WHERE AD_Process_ID=?"; - if (trl) - sql = "SELECT t.Name, t.Description, t.Help, p.IsReport, p.ShowHelp " - + "FROM AD_Process p, AD_Process_Trl t " - + "WHERE p.AD_Process_ID=t.AD_Process_ID" - + " AND p.AD_Process_ID=? AND t.AD_Language=?"; - - PreparedStatement pstmt = null; - ResultSet rs = null; - try - { - pstmt = DB.prepareStatement(sql, null); - pstmt.setInt(1, m_pi.getAD_Process_ID()); - if (trl) - pstmt.setString(2, Env.getAD_Language(m_ctx)); - rs = pstmt.executeQuery(); - if (rs.next()) - { - m_Name = rs.getString(1); - m_ShowHelp = rs.getString(5); - // - m_messageText.append(""); - String s = rs.getString(2); // Description - if (rs.wasNull()) - m_messageText.append(Msg.getMsg(m_ctx, "StartProcess?")); - else - m_messageText.append(s); - m_messageText.append(""); - - s = rs.getString(3); // Help - if (!rs.wasNull()) - m_messageText.append("

").append(s).append("

"); - } - } - catch (SQLException e) - { - log.log(Level.SEVERE, sql, e); - return false; - } - finally - { - DB.close(rs, pstmt); - } - - if (m_Name == null) - return false; - // - this.setTitle(m_Name); - message.setContent(m_messageText.toString()); - - // Move from APanel.actionButton - m_pi.setAD_User_ID (Env.getAD_User_ID(Env.getCtx())); - m_pi.setAD_Client_ID(Env.getAD_Client_ID(Env.getCtx())); - m_pi.setTitle(m_Name); - parameterPanel = new ProcessParameterPanel(m_WindowNo, m_pi); - centerPanel.getChildren().clear(); - if ( parameterPanel.init() ) { - centerPanel.appendChild(parameterPanel); - } else { - if (m_ShowHelp != null && m_ShowHelp.equals("N")) { - m_autoStart = true; - } - if (m_autoStart) { - this.getFirstChild().setVisible(false); - startProcess(); - return true; - } - } - - // Check if the process is a silent one - if(isValid() && m_ShowHelp != null && m_ShowHelp.equals("S")) - { - this.getFirstChild().setVisible(false); - startProcess(); - } - return true; - } // init - - /** - * launch process - */ - private void startProcess() - { - m_pi.setPrintPreview(true); - - lockUI(m_pi); - - downloadFiles = new ArrayList(); - - //use echo, otherwise lock ui wouldn't work - Clients.response(new AuEcho(this, "runProcess", null)); - } - - private void showBusyDialog() { + @Override + public void showBusyDialog() { this.setBorder("none"); this.setTitle(null); dialogBody.setVisible(false); - progressWindow = new BusyDialog(); - this.appendChild(progressWindow); + BusyDialog progressWindow = createBusyDialog(); if (this.getParent() != null) LayoutUtils.openOverlappedWindow(this.getParent(), progressWindow, "middle_center"); } - - /** - * internal use, don't call this directly - */ - public void runProcess() { - processDialogRunnable = new ProcessDialogRunnable(); - future = Adempiere.getThreadPoolExecutor().submit(new DesktopRunnable(processDialogRunnable, getDesktop())); + + @Override + public void updateUI() { + } - private void hideBusyDialog() { - if (progressWindow != null) { - progressWindow.dispose(); - progressWindow = null; - } + @Override + public void hideBusyDialog() { + closeBusyDialog(); } - + /** * handle events */ @@ -394,138 +225,12 @@ public class ProcessModalDialog extends Window implements EventListener, Component component = event.getTarget(); if (component instanceof Button) { Button element = (Button)component; - if ("Ok".equalsIgnoreCase(element.getId())) { - onOK(); - } else if ("Cancel".equalsIgnoreCase(element.getId())) { - onCancel(); - } - } else if (event.getName().equals(ON_STATUS_UPDATE)) { - onStatusUpdate(event); - } else if (event.getName().equals(ON_COMPLETE)) { - onComplete(); + if ("Ok".equalsIgnoreCase(element.getId())) + startProcess(); + else if ("Cancel".equalsIgnoreCase(element.getId())) + cancelProcess(); + } else { + super.onEvent(event); } - } - - private void onOK() { - if (!parameterPanel.validateParameters()) - return; - this.startProcess(); - } - - private void onCancel() { - m_cancel = true; - this.dispose(); - } - - private void onStatusUpdate(Event event) { - String message = (String) event.getData(); - if (progressWindow != null) - progressWindow.statusUpdate(message); - } - - private void onComplete() { - if (future != null) { - try { - future.get(); - } catch (Exception e) { - log.log(Level.SEVERE, e.getLocalizedMessage(), e); - if (!m_pi.isError()) { - m_pi.setSummary(e.getLocalizedMessage(), true); - } - } - } - future = null; - processDialogRunnable = null; - unlockUI(m_pi); - if (downloadFiles.size() > 0) { - MultiFileDownloadDialog downloadDialog = new MultiFileDownloadDialog(downloadFiles.toArray(new File[0])); - downloadDialog.setPage(this.getPage()); - downloadDialog.setTitle(m_pi.getTitle()); - Events.postEvent(downloadDialog, new Event(MultiFileDownloadDialog.ON_SHOW)); - } - dispose(); - } - - @Override - public void lockUI(ProcessInfo pi) { - if (isLocked || Executions.getCurrent() == null) - return; - - showBusyDialog(); - isLocked = true; - } - - @Override - public void unlockUI(ProcessInfo pi) { - if (!isLocked) - return; - - if (Executions.getCurrent() == null) { - Executions.schedule(getDesktop(), new EventListener() { - @Override - public void onEvent(Event event) throws Exception { - doUnlockUI(); - } - }, new Event("onUnLockUI")); - } else { - doUnlockUI(); - } - } - - private void doUnlockUI() { - hideBusyDialog(); - isLocked = false; - } - - @Override - public boolean isUILocked() { - return isLocked; - } - - @Override - public void statusUpdate(String message) { - Executions.schedule(getDesktop(), this, new Event(ON_STATUS_UPDATE, this, message)); - } - - /** - * - * @return ProcessInfo - */ - public ProcessInfo getProcessInfo() { - return m_pi; - } - - class ProcessDialogRunnable extends ContextRunnable{ - ProcessDialogRunnable() { - super(); - } - - protected void doRun() { - try { - if (log.isLoggable(Level.INFO))log.log(Level.INFO, "Process Info="+m_pi+" AD_Client_ID="+Env.getAD_Client_ID(Env.getCtx())); - WProcessCtl.process(ProcessModalDialog.this, m_WindowNo, parameterPanel, m_pi, null); - } catch (Exception ex) { - m_pi.setError(true); - m_pi.setSummary(ex.getLocalizedMessage()); - log.log(Level.SEVERE, ex.getLocalizedMessage(), ex); - } finally { - Executions.schedule(getDesktop(), ProcessModalDialog.this, new Event(ON_COMPLETE, ProcessModalDialog.this, null)); - } - } - } - - @Override - public void ask(final String message, final Callback callback) { - Executions.schedule(getDesktop(), new EventListener() { - @Override - public void onEvent(Event event) throws Exception { - FDialog.ask(m_WindowNo, null, message, callback); - } - }, new Event("onAsk")); - } - - @Override - public void download(File file) { - downloadFiles.add(file); - } + } } // ProcessDialog diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/dashboard/DPRunningJobs.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/dashboard/DPRunningJobs.java new file mode 100644 index 0000000000..83e220b5e7 --- /dev/null +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/dashboard/DPRunningJobs.java @@ -0,0 +1,282 @@ +/****************************************************************************** + * Copyright (C) 2014 Elaine Tan * + * Copyright (C) 2014 Trek Global + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ + +package org.adempiere.webui.dashboard; + +import java.lang.ref.WeakReference; +import java.util.List; +import java.util.Properties; + +import org.adempiere.base.Service; +import org.adempiere.base.event.EventManager; +import org.adempiere.webui.apps.AEnv; +import org.adempiere.webui.theme.ThemeManager; +import org.adempiere.webui.util.ServerPushTemplate; +import org.compiere.model.MPInstance; +import org.compiere.model.MProcess; +import org.compiere.model.Query; +import org.compiere.util.Env; +import org.compiere.util.Msg; +import org.compiere.util.Util; +import org.idempiere.distributed.IMessageService; +import org.idempiere.distributed.ITopic; +import org.idempiere.distributed.ITopicSubscriber; +import org.osgi.service.event.EventHandler; +import org.zkoss.zk.ui.Component; +import org.zkoss.zk.ui.Desktop; +import org.zkoss.zk.ui.Page; +import org.zkoss.zk.ui.event.Event; +import org.zkoss.zk.ui.event.EventListener; +import org.zkoss.zk.ui.event.Events; +import org.zkoss.zk.ui.util.DesktopCleanup; +import org.zkoss.zul.A; +import org.zkoss.zul.Box; +import org.zkoss.zul.Image; +import org.zkoss.zul.Panel; +import org.zkoss.zul.Panelchildren; +import org.zkoss.zul.Toolbar; +import org.zkoss.zul.Vbox; + +public class DPRunningJobs extends DashboardPanel implements EventListener, EventHandler { + + /** + * + */ + private static final long serialVersionUID = 1946438226234068194L; + + private static final String AD_PINSTANCE_ID_ATTR = "AD_PInstance_ID"; + + private static TopicSubscriber topicSubscriber; + + private Box bxJobs; + + private int AD_User_ID; + + private Properties ctx; + + private WeakReference desktop; + + private DesktopCleanup listener; + + public DPRunningJobs() + { + super(); + + ctx = new Properties(); + ctx.putAll(Env.getCtx()); + AD_User_ID = Env.getAD_User_ID(ctx); + + Panel panel = new Panel(); + this.appendChild(panel); + + Panelchildren jobsContent = new Panelchildren(); + panel.appendChild(jobsContent); + bxJobs = new Vbox(); + bxJobs.setHflex("1"); + this.setSclass("recentitems-box"); + jobsContent.appendChild(bxJobs); + createJobsPanel(); + + Toolbar jobsToolbar = new Toolbar(); + this.appendChild(jobsToolbar); + + Image imgr = new Image(ThemeManager.getThemeResource("images/Refresh24.png")); + jobsToolbar.appendChild(imgr); + imgr.setStyle("text-align: right; cursor: pointer; width:24px; height:24px;"); + imgr.setTooltiptext(Util.cleanAmp(Msg.getMsg(ctx, "Refresh"))); + imgr.addEventListener(Events.ON_CLICK, this); + + createTopicSubscriber(); + + listener = new DesktopCleanup() { + @Override + public void cleanup(Desktop desktop) throws Exception { + DPRunningJobs.this.cleanup(); + } + }; + } + + protected void cleanup() + { + EventManager.getInstance().unregister(this); + desktop = null; + } + + private static synchronized void createTopicSubscriber() + { + if (topicSubscriber == null) { + topicSubscriber = new TopicSubscriber(); + IMessageService service = Service.locator().locate(IMessageService.class).getService(); + if (service != null) { + ITopic topic = service.getTopic(MPInstance.ON_RUNNING_JOB_CHANGED_TOPIC); + topic.subscribe(topicSubscriber); + } + } + } + + private void createJobsPanel() + { + refresh(); + } + + @Override + public void onEvent(Event event) throws Exception + { + Component comp = event.getTarget(); + String eventName = event.getName(); + + if (eventName.equals(Events.ON_CLICK)) + doOnClick(comp); + } + + private void doOnClick(Component comp) + { + if (comp instanceof A) + { + A btn = (A) comp; + + int AD_PInstance_ID = 0; + try + { + AD_PInstance_ID = Integer.valueOf((String)btn.getAttribute(AD_PINSTANCE_ID_ATTR)); + } + catch (Exception e) { + } + + if (AD_PInstance_ID > 0) + AEnv.zoom(MPInstance.Table_ID, AD_PInstance_ID); + } + + if (comp instanceof Image) // Refresh button + { + refresh(); + } + } + + private synchronized void refresh() + { + // Please review here - is throwing NPE in some cases when user push repeatedly the refresh button + List childs = bxJobs.getChildren(); + int childCount = childs.size(); + for (int c = childCount - 1; c >=0; c--) { + Component comp = (Component) childs.get(c); + if (comp instanceof A) { + comp.removeEventListener(Events.ON_CLICK, this); + } + bxJobs.removeChild(comp); + } + + List pis = getRunningJobForUser(ctx, AD_User_ID); + for (MPInstance pi : pis) { + MProcess process = new MProcess(pi.getCtx(), pi.getAD_Process_ID(), pi.get_TrxName()); + String label = process.getName() + " [" + Msg.getElement(pi.getCtx(), "Created") + " = " + pi.getCreated() + "]"; + A btnJob = new A(); + btnJob.setAttribute(AD_PINSTANCE_ID_ATTR, String.valueOf(pi.getAD_PInstance_ID())); + bxJobs.appendChild(btnJob); + btnJob.setLabel(label); + btnJob.setImage(ThemeManager.getThemeResource(getIconFile())); + btnJob.addEventListener(Events.ON_CLICK, this); + btnJob.setSclass("menu-href"); + btnJob.setHflex("1"); + } + } + + public static List getRunningJobForUser(Properties ctx, int AD_User_ID) + { + List pis = new Query(ctx, MPInstance.Table_Name, "Coalesce(AD_User_ID,0)=? AND IsProcessing='Y' AND IsRunAsJob='Y'", null) + .setOnlyActiveRecords(true) + .setClient_ID() + .setParameters(AD_User_ID) + .setOrderBy("Updated DESC") + .list(); + return pis; + } + + private String getIconFile() + { + return "images/mWindow.png"; + } + + @Override + public void refresh(ServerPushTemplate template) + { + template.executeAsync(this); + } + + @Override + public void updateUI() + { + refresh(); + bxJobs.invalidate(); + updateDesktopReference(); + } + + /** + * + */ + protected void updateDesktopReference() + { + if ((desktop == null || desktop.get() == null) || (desktop.get() != null && desktop.get() != getDesktop())) { + if (desktop != null && desktop.get() != null) + desktop.get().removeListener(listener); + + desktop = new WeakReference(getDesktop()); + desktop.get().addListener(listener); + } + } + + @Override + public void handleEvent(org.osgi.service.event.Event event) + { + if (event.getTopic().equals(MPInstance.ON_RUNNING_JOB_CHANGED_TOPIC) && event.getProperty("AD_User_ID") != null) { + Object property = event.getProperty("AD_User_ID"); + if (property instanceof Number) { + int id = ((Number)property).intValue(); + if (id == AD_User_ID) { + try { + if (desktop != null && desktop.get() != null && desktop.get().isAlive()) { + ServerPushTemplate template = new ServerPushTemplate(desktop.get()); + refresh(template); + } + } catch (Exception e) { + EventManager.getInstance().unregister(this); + } + } + } + } + } + + @Override + public void onPageAttached(Page newpage, Page oldpage) + { + super.onPageAttached(newpage, oldpage); + if (newpage != null) { + EventManager.getInstance().register(MPInstance.ON_RUNNING_JOB_CHANGED_TOPIC, this); + updateDesktopReference(); + } + } + + @Override + public void onPageDetached(Page page) { + super.onPageDetached(page); + cleanup(); + } + + static class TopicSubscriber implements ITopicSubscriber { + @Override + public void onMessage(Integer message) { + MPInstance.postOnChangedEvent(message); + } + } +} \ No newline at end of file diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/WAttachment.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/WAttachment.java index 6f41ab7d51..f6136ff8f8 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/WAttachment.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/WAttachment.java @@ -122,6 +122,7 @@ public class WAttachment extends Window implements EventListener autoPreviewList.add("image/gif"); autoPreviewList.add("text/plain"); autoPreviewList.add("application/pdf"); + autoPreviewList.add("text/html"); } /** diff --git a/org.adempiere.ui.zk/theme/default/zul/dashboard/runningJobs.zul b/org.adempiere.ui.zk/theme/default/zul/dashboard/runningJobs.zul new file mode 100644 index 0000000000..981e9fee23 --- /dev/null +++ b/org.adempiere.ui.zk/theme/default/zul/dashboard/runningJobs.zul @@ -0,0 +1,2 @@ + + diff --git a/org.adempiere.ui.zk/zul/runningJobs.zul b/org.adempiere.ui.zk/zul/runningJobs.zul new file mode 100644 index 0000000000..27906a7b1e --- /dev/null +++ b/org.adempiere.ui.zk/zul/runningJobs.zul @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file