From 9f71eeadbc611ad230b9337fc93415a1453c7b9f Mon Sep 17 00:00:00 2001 From: matheus-marcelinux Date: Wed, 1 Feb 2023 00:43:06 -0300 Subject: [PATCH] IDEMPIERE-5458 - Timezone defined by Organization (#1568) * # IDEMPIERE-5458 - Timezone defined by Organization * # IDEMPIERE-5468 - improved unit test * # IDEMPIERE-5458 - removing user/password from scriptg * IDEMPIERE-5458 - fix migration script * IDEMPIERE-5458 - adding field in org info tab --- .../oracle/202211011331_IDEMPIERE-5458.sql | 13 +++++ .../oracle/202212221947_IDEMPIERE-5458.sql | 38 +++++++++++++ .../202211011331_IDEMPIERE-5458.sql | 10 ++++ .../202212221947_IDEMPIERE-5458.sql | 35 ++++++++++++ .../src/org/compiere/model/I_AD_OrgInfo.java | 13 +++++ .../org/compiere/model/MAcctProcessor.java | 21 +++++-- .../org/compiere/model/MAlertProcessor.java | 13 ++++- .../org/compiere/model/MRequestProcessor.java | 18 ++++-- .../src/org/compiere/model/MScheduler.java | 17 +++++- .../src/org/compiere/model/X_AD_OrgInfo.java | 18 +++++- .../org/compiere/wf/MWorkflowProcessor.java | 16 +++++- .../org/compiere/server/AdempiereServer.java | 18 +++++- .../webui/editor/WDatetimeEditor.java | 13 +++-- .../idempiere/test/model/MSchedulerTest.java | 56 ++++++++++++++++++- 14 files changed, 277 insertions(+), 22 deletions(-) create mode 100644 migration/iD11/oracle/202211011331_IDEMPIERE-5458.sql create mode 100644 migration/iD11/oracle/202212221947_IDEMPIERE-5458.sql create mode 100644 migration/iD11/postgresql/202211011331_IDEMPIERE-5458.sql create mode 100644 migration/iD11/postgresql/202212221947_IDEMPIERE-5458.sql diff --git a/migration/iD11/oracle/202211011331_IDEMPIERE-5458.sql b/migration/iD11/oracle/202211011331_IDEMPIERE-5458.sql new file mode 100644 index 0000000000..c06ee7e308 --- /dev/null +++ b/migration/iD11/oracle/202211011331_IDEMPIERE-5458.sql @@ -0,0 +1,13 @@ +-- IDEMPIERE-5458 +SELECT register_migration_script('202211011331_IDEMPIERE-5458.sql') FROM dual; + +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- Nov 1, 2022, 1:31:23 PM BRT +INSERT INTO AD_Column (AD_Column_ID,Version,Name,Description,AD_Table_ID,ColumnName,FieldLength,IsKey,IsParent,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsEncrypted,AD_Reference_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Element_ID,IsUpdateable,IsSelectionColumn,EntityType,IsSyncDatabase,IsAlwaysUpdateable,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsAllowCopy,SeqNoSelection,IsToolbarButton,IsSecure,FKConstraintType,IsHtml) VALUES (215633,0,'Time Zone','Time zone name',228,'TimeZone',60,'N','N','N','N','N',0,'N',200135,0,0,'Y',TO_TIMESTAMP('2022-11-01 13:31:22','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-11-01 13:31:22','YYYY-MM-DD HH24:MI:SS'),100,203049,'Y','N','D','N','N','N','Y','cee6683d-23df-4918-be6f-afa14608e010','Y',0,'N','N','N','N') +; + +-- Nov 1, 2022, 1:31:26 PM BRT +ALTER TABLE AD_OrgInfo ADD TimeZone VARCHAR2(60 CHAR) DEFAULT NULL +; \ No newline at end of file diff --git a/migration/iD11/oracle/202212221947_IDEMPIERE-5458.sql b/migration/iD11/oracle/202212221947_IDEMPIERE-5458.sql new file mode 100644 index 0000000000..551d54d670 --- /dev/null +++ b/migration/iD11/oracle/202212221947_IDEMPIERE-5458.sql @@ -0,0 +1,38 @@ +-- IDEMPIERE-5458 +SELECT register_migration_script('202212221947_IDEMPIERE-5458.sql') FROM dual; + +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- Dec 22, 2022, 7:47:23 PM BRT +INSERT INTO AD_Field (AD_Field_ID,Name,Description,AD_Tab_ID,AD_Column_ID,IsDisplayed,DisplayLength,SeqNo,IsSameLine,IsHeading,IsFieldOnly,IsEncrypted,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsReadOnly,IsCentrallyMaintained,EntityType,AD_Field_UU,IsDisplayedGrid,SeqNoGrid,ColumnSpan) VALUES (207517,'Time Zone','Time zone name',170,215633,'Y',60,180,'N','N','N','N',0,0,'Y',TO_TIMESTAMP('2022-12-22 19:47:22','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-12-22 19:47:22','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','91adaa04-3962-4dfb-8357-958d325a063b','Y',180,5) +; + +-- Dec 22, 2022, 7:47:39 PM BRT +UPDATE AD_Field SET IsDisplayed='Y', SeqNo=130, XPosition=4, ColumnSpan=2,Updated=TO_TIMESTAMP('2022-12-22 19:47:39','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=207517 +; + +-- Dec 22, 2022, 7:47:39 PM BRT +UPDATE AD_Field SET SeqNo=140,Updated=TO_TIMESTAMP('2022-12-22 19:47:39','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=58855 +; + +-- Dec 22, 2022, 7:47:39 PM BRT +UPDATE AD_Field SET SeqNo=150,Updated=TO_TIMESTAMP('2022-12-22 19:47:39','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=58852 +; + +-- Dec 22, 2022, 7:47:39 PM BRT +UPDATE AD_Field SET SeqNo=160,Updated=TO_TIMESTAMP('2022-12-22 19:47:39','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=58854 +; + +-- Dec 22, 2022, 7:47:39 PM BRT +UPDATE AD_Field SET SeqNo=170,Updated=TO_TIMESTAMP('2022-12-22 19:47:39','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=58853 +; + +-- Dec 22, 2022, 7:47:39 PM BRT +UPDATE AD_Field SET SeqNo=180,Updated=TO_TIMESTAMP('2022-12-22 19:47:39','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=57532 +; + +-- Dec 22, 2022, 7:47:39 PM BRT +UPDATE AD_Field SET SeqNo=0,Updated=TO_TIMESTAMP('2022-12-22 19:47:39','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=204544 +; + diff --git a/migration/iD11/postgresql/202211011331_IDEMPIERE-5458.sql b/migration/iD11/postgresql/202211011331_IDEMPIERE-5458.sql new file mode 100644 index 0000000000..40904ce6fd --- /dev/null +++ b/migration/iD11/postgresql/202211011331_IDEMPIERE-5458.sql @@ -0,0 +1,10 @@ +-- IDEMPIERE-5458 +SELECT register_migration_script('202211011331_IDEMPIERE-5458.sql') FROM dual; + +-- Nov 1, 2022, 1:31:23 PM BRT +INSERT INTO AD_Column (AD_Column_ID,Version,Name,Description,AD_Table_ID,ColumnName,FieldLength,IsKey,IsParent,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsEncrypted,AD_Reference_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Element_ID,IsUpdateable,IsSelectionColumn,EntityType,IsSyncDatabase,IsAlwaysUpdateable,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsAllowCopy,SeqNoSelection,IsToolbarButton,IsSecure,FKConstraintType,IsHtml) VALUES (215633,0,'Time Zone','Time zone name',228,'TimeZone',60,'N','N','N','N','N',0,'N',200135,0,0,'Y',TO_TIMESTAMP('2022-11-01 13:31:22','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-11-01 13:31:22','YYYY-MM-DD HH24:MI:SS'),100,203049,'Y','N','D','N','N','N','Y','cee6683d-23df-4918-be6f-afa14608e010','Y',0,'N','N','N','N') +; + +-- Nov 1, 2022, 1:31:26 PM BRT +ALTER TABLE AD_OrgInfo ADD COLUMN TimeZone VARCHAR(60) DEFAULT NULL +; \ No newline at end of file diff --git a/migration/iD11/postgresql/202212221947_IDEMPIERE-5458.sql b/migration/iD11/postgresql/202212221947_IDEMPIERE-5458.sql new file mode 100644 index 0000000000..d4da43c699 --- /dev/null +++ b/migration/iD11/postgresql/202212221947_IDEMPIERE-5458.sql @@ -0,0 +1,35 @@ +-- IDEMPIERE-5458 +SELECT register_migration_script('202212221947_IDEMPIERE-5458.sql') FROM dual; + +-- Dec 22, 2022, 7:47:23 PM BRT +INSERT INTO AD_Field (AD_Field_ID,Name,Description,AD_Tab_ID,AD_Column_ID,IsDisplayed,DisplayLength,SeqNo,IsSameLine,IsHeading,IsFieldOnly,IsEncrypted,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsReadOnly,IsCentrallyMaintained,EntityType,AD_Field_UU,IsDisplayedGrid,SeqNoGrid,ColumnSpan) VALUES (207517,'Time Zone','Time zone name',170,215633,'Y',60,180,'N','N','N','N',0,0,'Y',TO_TIMESTAMP('2022-12-22 19:47:22','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-12-22 19:47:22','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','91adaa04-3962-4dfb-8357-958d325a063b','Y',180,5) +; + +-- Dec 22, 2022, 7:47:39 PM BRT +UPDATE AD_Field SET IsDisplayed='Y', SeqNo=130, XPosition=4, ColumnSpan=2,Updated=TO_TIMESTAMP('2022-12-22 19:47:39','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=207517 +; + +-- Dec 22, 2022, 7:47:39 PM BRT +UPDATE AD_Field SET SeqNo=140,Updated=TO_TIMESTAMP('2022-12-22 19:47:39','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=58855 +; + +-- Dec 22, 2022, 7:47:39 PM BRT +UPDATE AD_Field SET SeqNo=150,Updated=TO_TIMESTAMP('2022-12-22 19:47:39','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=58852 +; + +-- Dec 22, 2022, 7:47:39 PM BRT +UPDATE AD_Field SET SeqNo=160,Updated=TO_TIMESTAMP('2022-12-22 19:47:39','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=58854 +; + +-- Dec 22, 2022, 7:47:39 PM BRT +UPDATE AD_Field SET SeqNo=170,Updated=TO_TIMESTAMP('2022-12-22 19:47:39','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=58853 +; + +-- Dec 22, 2022, 7:47:39 PM BRT +UPDATE AD_Field SET SeqNo=180,Updated=TO_TIMESTAMP('2022-12-22 19:47:39','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=57532 +; + +-- Dec 22, 2022, 7:47:39 PM BRT +UPDATE AD_Field SET SeqNo=0,Updated=TO_TIMESTAMP('2022-12-22 19:47:39','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=204544 +; + diff --git a/org.adempiere.base/src/org/compiere/model/I_AD_OrgInfo.java b/org.adempiere.base/src/org/compiere/model/I_AD_OrgInfo.java index 1cfba6fcba..daef603727 100644 --- a/org.adempiere.base/src/org/compiere/model/I_AD_OrgInfo.java +++ b/org.adempiere.base/src/org/compiere/model/I_AD_OrgInfo.java @@ -305,6 +305,19 @@ public interface I_AD_OrgInfo */ public String getTaxID(); + /** Column name TimeZone */ + public static final String COLUMNNAME_TimeZone = "TimeZone"; + + /** Set Time Zone. + * Time zone name + */ + public void setTimeZone (String TimeZone); + + /** Get Time Zone. + * Time zone name + */ + public String getTimeZone(); + /** Column name TransferBank_ID */ public static final String COLUMNNAME_TransferBank_ID = "TransferBank_ID"; diff --git a/org.adempiere.base/src/org/compiere/model/MAcctProcessor.java b/org.adempiere.base/src/org/compiere/model/MAcctProcessor.java index ad22956b13..f2d1223c82 100644 --- a/org.adempiere.base/src/org/compiere/model/MAcctProcessor.java +++ b/org.adempiere.base/src/org/compiere/model/MAcctProcessor.java @@ -24,6 +24,7 @@ import java.util.Properties; import org.compiere.util.DB; import org.compiere.util.Msg; +import org.compiere.util.Util; /** @@ -105,11 +106,21 @@ public class MAcctProcessor extends X_C_AcctProcessor protected boolean beforeSave(boolean newRecord) { if (newRecord || is_ValueChanged("AD_Schedule_ID")) { - MClientInfo clientInfo = MClientInfo.get(getCtx(), getAD_Client_ID()); - if (clientInfo == null) - clientInfo = MClientInfo.get(getCtx(), getAD_Client_ID(), get_TrxName()); - long nextWork = MSchedule.getNextRunMS(System.currentTimeMillis(), getScheduleType(), getFrequencyType(), getFrequency(), getCronPattern(), - clientInfo.getTimeZone()); + String timeZoneId = null; + if((getAD_Client_ID() == 0 && getAD_Org_ID() == 0) || getAD_Org_ID() > 0) { + MOrgInfo orgInfo = MOrgInfo.get(getAD_Org_ID()); + timeZoneId = orgInfo.getTimeZone(); + } + + if(Util.isEmpty(timeZoneId, true)) { + MClientInfo clientInfo = MClientInfo.get(getCtx(), getAD_Client_ID()); + if (clientInfo == null) + clientInfo = MClientInfo.get(getCtx(), getAD_Client_ID(), get_TrxName()); + timeZoneId = clientInfo.getTimeZone(); + } + + long nextWork = MSchedule.getNextRunMS(System.currentTimeMillis(), getScheduleType(), getFrequencyType(), + getFrequency(), getCronPattern(), timeZoneId); if (nextWork > 0) setDateNextRun(new Timestamp(nextWork)); } diff --git a/org.adempiere.base/src/org/compiere/model/MAlertProcessor.java b/org.adempiere.base/src/org/compiere/model/MAlertProcessor.java index d399577782..8650669226 100644 --- a/org.adempiere.base/src/org/compiere/model/MAlertProcessor.java +++ b/org.adempiere.base/src/org/compiere/model/MAlertProcessor.java @@ -23,6 +23,7 @@ import java.util.Properties; import org.compiere.util.CLogger; import org.compiere.util.DB; +import org.compiere.util.Util; /** @@ -168,8 +169,18 @@ public class MAlertProcessor extends X_AD_AlertProcessor protected boolean beforeSave(boolean newRecord) { if (newRecord || is_ValueChanged("AD_Schedule_ID")) { + String timeZoneId = null; + if((getAD_Client_ID() == 0 && getAD_Org_ID() == 0) || getAD_Org_ID() > 0) { + MOrgInfo orgInfo = MOrgInfo.get(getAD_Org_ID()); + timeZoneId = orgInfo.getTimeZone(); + } + + if(Util.isEmpty(timeZoneId, true)) { + MClientInfo clientInfo = MClientInfo.get(getCtx(), getAD_Client_ID()); + timeZoneId = clientInfo.getTimeZone(); + } long nextWork = MSchedule.getNextRunMS(System.currentTimeMillis(), getScheduleType(), getFrequencyType(), getFrequency(), getCronPattern(), - MClientInfo.get(getCtx(), getAD_Client_ID()).getTimeZone()); + timeZoneId); if (nextWork > 0) setDateNextRun(new Timestamp(nextWork)); } diff --git a/org.adempiere.base/src/org/compiere/model/MRequestProcessor.java b/org.adempiere.base/src/org/compiere/model/MRequestProcessor.java index 496993664b..e341cecde3 100644 --- a/org.adempiere.base/src/org/compiere/model/MRequestProcessor.java +++ b/org.adempiere.base/src/org/compiere/model/MRequestProcessor.java @@ -26,6 +26,7 @@ import java.util.logging.Level; import org.compiere.util.CLogger; import org.compiere.util.DB; import org.compiere.util.Msg; +import org.compiere.util.Util; /** * Request Processor Model @@ -242,11 +243,20 @@ public class MRequestProcessor extends X_R_RequestProcessor protected boolean beforeSave(boolean newRecord) { if (newRecord || is_ValueChanged("AD_Schedule_ID")) { - MClientInfo clientInfo = MClientInfo.get(getCtx(), getAD_Client_ID()); - if (clientInfo == null) - clientInfo = MClientInfo.get(getCtx(), getAD_Client_ID(), get_TrxName()); + String timeZoneId = null; + if((getAD_Client_ID() == 0 && getAD_Org_ID() == 0) || getAD_Org_ID() > 0) { + MOrgInfo orgInfo = MOrgInfo.get(getAD_Org_ID()); + timeZoneId = orgInfo.getTimeZone(); + } + + if(Util.isEmpty(timeZoneId, true)) { + MClientInfo clientInfo = MClientInfo.get(getCtx(), getAD_Client_ID()); + if (clientInfo == null) + clientInfo = MClientInfo.get(getCtx(), getAD_Client_ID(), get_TrxName()); + timeZoneId = clientInfo.getTimeZone(); + } long nextWork = MSchedule.getNextRunMS(System.currentTimeMillis(), getScheduleType(), getFrequencyType(), getFrequency(), getCronPattern(), - clientInfo.getTimeZone()); + timeZoneId); if (nextWork > 0) setDateNextRun(new Timestamp(nextWork)); } diff --git a/org.adempiere.base/src/org/compiere/model/MScheduler.java b/org.adempiere.base/src/org/compiere/model/MScheduler.java index 9a09645b8a..8b80688d62 100644 --- a/org.adempiere.base/src/org/compiere/model/MScheduler.java +++ b/org.adempiere.base/src/org/compiere/model/MScheduler.java @@ -28,6 +28,7 @@ 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.idempiere.cache.ImmutablePOSupport; @@ -325,9 +326,21 @@ public class MScheduler extends X_AD_Scheduler } if (newRecord || is_ValueChanged("AD_Schedule_ID")) { - MClientInfo clientInfo = MClientInfo.get(getCtx(), getAD_Client_ID()); + String timeZoneId = null; + if((getAD_Client_ID() == 0 && getAD_Org_ID() == 0) || getAD_Org_ID() > 0) { + MOrgInfo orgInfo = MOrgInfo.get(getAD_Org_ID()); + timeZoneId = orgInfo.getTimeZone(); + } + + if(Util.isEmpty(timeZoneId, true)) { + MClientInfo clientInfo = MClientInfo.get(getCtx(), getAD_Client_ID()); + if (clientInfo == null) + clientInfo = MClientInfo.get(getCtx(), getAD_Client_ID(), get_TrxName()); + timeZoneId = clientInfo.getTimeZone(); + } + long nextWork = MSchedule.getNextRunMS(System.currentTimeMillis(), getScheduleType(), getFrequencyType(), getFrequency(), getCronPattern(), - clientInfo.getTimeZone()); + timeZoneId); if (nextWork > 0) setDateNextRun(new Timestamp(nextWork)); } diff --git a/org.adempiere.base/src/org/compiere/model/X_AD_OrgInfo.java b/org.adempiere.base/src/org/compiere/model/X_AD_OrgInfo.java index 4068e10df9..63839a3b26 100644 --- a/org.adempiere.base/src/org/compiere/model/X_AD_OrgInfo.java +++ b/org.adempiere.base/src/org/compiere/model/X_AD_OrgInfo.java @@ -424,6 +424,22 @@ public class X_AD_OrgInfo extends PO implements I_AD_OrgInfo, I_Persistent return (String)get_Value(COLUMNNAME_TaxID); } + /** Set Time Zone. + @param TimeZone Time zone name + */ + public void setTimeZone (String TimeZone) + { + set_Value (COLUMNNAME_TimeZone, TimeZone); + } + + /** Get Time Zone. + @return Time zone name + */ + public String getTimeZone() + { + return (String)get_Value(COLUMNNAME_TimeZone); + } + public org.compiere.model.I_C_Bank getTransferBank() throws RuntimeException { return (org.compiere.model.I_C_Bank)MTable.get(getCtx(), org.compiere.model.I_C_Bank.Table_ID) @@ -478,4 +494,4 @@ public class X_AD_OrgInfo extends PO implements I_AD_OrgInfo, I_Persistent return 0; return ii.intValue(); } -} \ No newline at end of file +} diff --git a/org.adempiere.base/src/org/compiere/wf/MWorkflowProcessor.java b/org.adempiere.base/src/org/compiere/wf/MWorkflowProcessor.java index 6934bf588c..5bfea31fae 100644 --- a/org.adempiere.base/src/org/compiere/wf/MWorkflowProcessor.java +++ b/org.adempiere.base/src/org/compiere/wf/MWorkflowProcessor.java @@ -25,10 +25,12 @@ import org.compiere.model.AdempiereProcessor; import org.compiere.model.AdempiereProcessor2; import org.compiere.model.AdempiereProcessorLog; import org.compiere.model.MClientInfo; +import org.compiere.model.MOrgInfo; import org.compiere.model.MSchedule; import org.compiere.model.Query; import org.compiere.model.X_AD_WorkflowProcessor; import org.compiere.util.DB; +import org.compiere.util.Util; /** @@ -143,8 +145,20 @@ public class MWorkflowProcessor extends X_AD_WorkflowProcessor protected boolean beforeSave(boolean newRecord) { if (newRecord || is_ValueChanged("AD_Schedule_ID")) { + String timeZoneId = null; + if((getAD_Client_ID() == 0 && getAD_Org_ID() == 0) || getAD_Org_ID() > 0) { + MOrgInfo orgInfo = MOrgInfo.get(getAD_Org_ID()); + timeZoneId = orgInfo.getTimeZone(); + } + + if(Util.isEmpty(timeZoneId, true)) { + MClientInfo clientInfo = MClientInfo.get(getCtx(), getAD_Client_ID()); + if (clientInfo == null) + clientInfo = MClientInfo.get(getCtx(), getAD_Client_ID(), get_TrxName()); + timeZoneId = clientInfo.getTimeZone(); + } long nextWork = MSchedule.getNextRunMS(System.currentTimeMillis(), getScheduleType(), getFrequencyType(), getFrequency(), getCronPattern(), - MClientInfo.get(getCtx(), getAD_Client_ID()).getTimeZone()); + timeZoneId); if (nextWork > 0) setDateNextRun(new Timestamp(nextWork)); } diff --git a/org.adempiere.server/src/main/server/org/compiere/server/AdempiereServer.java b/org.adempiere.server/src/main/server/org/compiere/server/AdempiereServer.java index 327829fa19..665b98f470 100644 --- a/org.adempiere.server/src/main/server/org/compiere/server/AdempiereServer.java +++ b/org.adempiere.server/src/main/server/org/compiere/server/AdempiereServer.java @@ -38,6 +38,7 @@ import org.compiere.model.SystemIDs; import org.compiere.util.CLogger; import org.compiere.util.Env; import org.compiere.util.TimeUtil; +import org.compiere.util.Util; /** * Adempiere Server Base @@ -112,10 +113,12 @@ public abstract class AdempiereServer implements Runnable public void recalculateSleepMS() { + int adOrgId = 0; if (p_model instanceof PO) { PO po = (PO) p_model; po.load(null); + adOrgId = po.getAD_Org_ID(); } m_sleepMS = 0; m_nextWork = 0; @@ -126,10 +129,21 @@ public abstract class AdempiereServer implements Runnable m_nextWork = dateNextRun.getTime(); } else - { + { + String timeZoneId = null; + if((p_model.getAD_Client_ID() == 0 && adOrgId == 0) || adOrgId > 0) { + MOrgInfo orgInfo = MOrgInfo.get(adOrgId); + timeZoneId = orgInfo.getTimeZone(); + } + + if(Util.isEmpty(timeZoneId, true)) { + MClientInfo clientInfo = MClientInfo.get(getCtx(), p_model.getAD_Client_ID()); + timeZoneId = clientInfo.getTimeZone(); + } + m_nextWork = MSchedule.getNextRunMS(now.getTime(), p_model.getScheduleType(), p_model.getFrequencyType(), - p_model.getFrequency(), p_model.getCronPattern(), MClientInfo.get(getCtx(), p_model.getAD_Client_ID()).getTimeZone()); + p_model.getFrequency(), p_model.getCronPattern(), timeZoneId); } if (m_nextWork > now.getTime()) diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WDatetimeEditor.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WDatetimeEditor.java index d3b72aadcd..d0cb6eca38 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WDatetimeEditor.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WDatetimeEditor.java @@ -27,6 +27,7 @@ import org.adempiere.webui.event.ValueChangeEvent; import org.adempiere.webui.window.WFieldRecordInfo; import org.compiere.model.GridField; import org.compiere.model.MClientInfo; +import org.compiere.model.MOrgInfo; import org.compiere.util.CLogger; import org.compiere.util.DisplayType; import org.compiere.util.Env; @@ -123,10 +124,14 @@ public class WDatetimeEditor extends WEditor implements ContextMenuListener if (isTimestampWithTimeZone()) { - MClientInfo clientInfo = MClientInfo.get(); - String timezoneId = clientInfo.getTimeZone(); - if (Util.isEmpty(timezoneId, true)) - timezoneId = Env.getContext(Env.getCtx(), Env.CLIENT_INFO_TIME_ZONE); + MOrgInfo orgInfo = MOrgInfo.get(Env.getAD_Org_ID(Env.getCtx())); + String timezoneId = orgInfo.getTimeZone(); + if (Util.isEmpty(timezoneId, true)) { + MClientInfo clientInfo = MClientInfo.get(); + timezoneId = clientInfo.getTimeZone(); + if (Util.isEmpty(timezoneId, true)) + timezoneId = Env.getContext(Env.getCtx(), Env.CLIENT_INFO_TIME_ZONE); + } if (!Util.isEmpty(timezoneId, true)) { diff --git a/org.idempiere.test/src/org/idempiere/test/model/MSchedulerTest.java b/org.idempiere.test/src/org/idempiere/test/model/MSchedulerTest.java index 09f45a9d64..bb2df8c5e8 100644 --- a/org.idempiere.test/src/org/idempiere/test/model/MSchedulerTest.java +++ b/org.idempiere.test/src/org/idempiere/test/model/MSchedulerTest.java @@ -33,6 +33,7 @@ import java.util.Calendar; import java.util.TimeZone; import org.compiere.model.MClientInfo; +import org.compiere.model.MOrgInfo; import org.compiere.model.MSchedule; import org.compiere.model.MScheduler; import org.compiere.model.PO; @@ -59,6 +60,9 @@ public class MSchedulerTest extends AbstractTestCase { MSchedule schedule = null; MClientInfo clientInfo = MClientInfo.getCopy(Env.getCtx(), getAD_Client_ID(), null); String currentTimeZone = clientInfo.getTimeZone(); + MOrgInfo orgInfo = MOrgInfo.getCopy(Env.getCtx(), getAD_Org_ID(), null); + String currentTimeZoneOrg = orgInfo.getTimeZone(); + try { schedule = new MSchedule(Env.getCtx(), 0, null); schedule.setName("Every Day at 5 pm Test"); @@ -102,18 +106,43 @@ public class MSchedulerTest extends AbstractTestCase { cal2.set(Calendar.SECOND, 0); cal2.set(Calendar.MILLISECOND, 0); + //get timezone with +3 hour offset + ids = TimeZone.getAvailableIDs(tz1.getRawOffset()+(3*60*60*1000)); + TimeZone tz3 = TimeZone.getTimeZone(ids[0]); + Calendar cal3 = Calendar.getInstance(); + cal3.setTimeZone(tz3); + cal3.setTimeInMillis(System.currentTimeMillis()); + hour = cal3.get(Calendar.HOUR_OF_DAY); + if (hour >= 17) { + cal3.add(Calendar.DAY_OF_MONTH, 1); + } + cal3.set(Calendar.HOUR_OF_DAY, 17); + cal3.set(Calendar.MINUTE, 0); + cal3.set(Calendar.SECOND, 0); + cal3.set(Calendar.MILLISECOND, 0); + //formatter for comparison DateTimeFormatter formatter1 = DateTimeFormatter.ISO_ZONED_DATE_TIME; formatter1 = formatter1.withZone(tz1.toZoneId()); DateTimeFormatter formatter2 = DateTimeFormatter.ISO_ZONED_DATE_TIME; formatter2 = formatter2.withZone(tz2.toZoneId()); + DateTimeFormatter formatter3 = DateTimeFormatter.ISO_ZONED_DATE_TIME; + formatter3 = formatter3.withZone(tz3.toZoneId()); //test with default time zone if (!Util.isEmpty(currentTimeZone, true)) { clientInfo.setTimeZone(null); clientInfo.saveEx(); CacheMgt.get().reset(); - } + } + + //test with default time zone + if (!Util.isEmpty(currentTimeZoneOrg, true)) { + orgInfo.setTimeZone(null); + orgInfo.saveEx(); + CacheMgt.get().reset(); + } + MScheduler scheduler1 = new MScheduler(Env.getCtx(), 0, getTrxName()); scheduler1.setAD_Process_ID(121); //Open Orders Process Id scheduler1.setAD_Schedule_ID(schedule.get_ID()); @@ -125,7 +154,7 @@ public class MSchedulerTest extends AbstractTestCase { assertEquals(formatter1.format(cal1.getTime().toInstant()), formatter1.format(ts1.toInstant()), "Un-expected date next run"); assertFalse(cal2.getTimeInMillis() == ts1.getTime(), "Un-expected date next run"); - //test with default + 2hour time zone + //test with default + 2hour time zone (defined in tenant) clientInfo.setTimeZone(tz2.toZoneId().getId()); clientInfo.saveEx(); CacheMgt.get().reset(); @@ -140,6 +169,23 @@ public class MSchedulerTest extends AbstractTestCase { Timestamp ts2 = scheduler2.getDateNextRun(); assertEquals(formatter2.format(cal2.getTime().toInstant()), formatter2.format(ts2.toInstant()), "Un-expected date next run"); assertFalse(cal1.getTimeInMillis() == ts2.getTime(), "Un-expected date next run"); + + //test with default + 3hour time zone (defined in org) + orgInfo.setTimeZone(tz3.toZoneId().getId()); + orgInfo.saveEx(); + CacheMgt.get().reset(); + + MScheduler scheduler3 = new MScheduler(Env.getCtx(), 0, getTrxName()); + scheduler3.setAD_Process_ID(121); + scheduler3.setAD_Schedule_ID(schedule.get_ID()); + scheduler3.setName("Cron Scheduler Test 3"); + scheduler3.setSupervisor_ID(100); + scheduler3.saveEx(); + + Timestamp ts3 = scheduler3.getDateNextRun(); + assertEquals(formatter3.format(cal3.getTime().toInstant()), formatter3.format(ts3.toInstant()), "Un-expected date next run"); + assertFalse(cal1.getTimeInMillis() == ts3.getTime(), "Un-expected date next run"); + } finally { rollback(); if (schedule != null && schedule.get_ID() > 0) @@ -149,6 +195,12 @@ public class MSchedulerTest extends AbstractTestCase { clientInfo.saveEx(); CacheMgt.get().reset(); } + + orgInfo.setTimeZone(currentTimeZoneOrg); + if (orgInfo.is_Changed()) { + orgInfo.saveEx(); + CacheMgt.get().reset(); + } } } }