/////////////////////////////////////////////////////////// // Global.cs // Implementation of Class Global // CSLA type: Editable Root // Created on: 07-Jun-2004 8:41:25 AM // Object design: Joyce // Coded: John 30-July-2004 /////////////////////////////////////////////////////////// using System; using System.Data; using CSLA.Data; using GZTW.Data; using CSLA; using System.Threading; using CSLA.Security; using System.ComponentModel; using System.Text; namespace GZTW.AyaNova.BLL { /// /// Global settings - stores AyaNova wide defaults and preferences /// API users: use the property to ensure you are working with the most current GlobalSettings rather than retrieving this object directly. /// [Serializable] public class Global : BusinessBase { #region Attributes private bool bReadOnly; //private Guid mID; private SmartDate mCreated; private SmartDate mModified; private Guid mCreator; private Guid mModifier; private Address mGoToAddress; private Address mMailToAddress; private Guid mTaxPartPurchaseID; private Guid mTaxPartSaleID; private Guid mTaxRateSaleID; private Guid mDefaultServiceTemplateID; private bool mAllowScheduleConflicts; private string mDefaultLanguage=""; //private bool mUseRegions; private Guid mWorkorderClosedStatus; // O.Global private string mWorkorderSummaryTemplate; private bool mUseInventory; private UnitNameDisplayFormats mDefaultUnitNameDisplayFormat=UnitNameDisplayFormats.SerialOnly; private ScheduleableUserNameDisplayFormats mDefaultScheduleableUserNameDisplayFormat=ScheduleableUserNameDisplayFormats.FirstLast; private PartDisplayFormats mDefaultPartDisplayFormat=PartDisplayFormats.NumberName; private bool mCJKIndex; //start seed update flags private bool mUpdateWorkorderServiceStartSeed=false; private bool mUpdateQuoteNumberStartSeed=false; private bool mUpdatePurchaseOrderStartSeed=false; private bool mUpdateInventoryAdjustmentStartSeed=false; //private bool mUpdateRentalStartSeed=false; //start seed current values private int mWorkorderServiceStartSeed=1; private int mQuoteNumberStartSeed=1; private int mPurchaseOrderStartSeed=1; private int mInventoryAdjustmentStartSeed=1; private int mWorkorderCloseByAge=0; private bool mUseNotification; private string mNotifySMTPHost=""; private string mNotifySMTPEncryptionMethod = "";//case 1136 private string mNotifySMTPAccount=""; private string mNotifySMTPPassword=""; private string mNotifySMTPFrom=""; private CoordinateTypes mCoordinateStyle=CoordinateTypes.DegreesDecimalMinutes; private LatitudeHemisphere mDefaultLatitude=LatitudeHemisphere.North; private LongitudeHemisphere mDefaultLongitude=LongitudeHemisphere.West; private int mMaxFileSizeMB = 50; //case 816 private int mLaborSchedUserDfltTimeSpan = 60; private int mTravelDfltTimeSpan = 60; private bool mSMTPRetry; //case 1194 private System.Collections.Generic.List mHiddenControls = null; //case 1346 private string mSignatureHeader = ""; private string mSignatureFooter = ""; private string mSignatureTitle = ""; //case 1392 private SmartDate mSchedUserNonTodayStartTime; //case 1487 private bool mMainGridAutoRefresh; #endregion #region Constructor /// /// Private constructor to prevent direct instantiation /// private Global() { //Set to read / write initially so that properties //can be set bReadOnly=false; // mGoToAddress=Address.NewItem(); // mGoToAddress.RootObjectID=Guid.Empty; // mGoToAddress.RootObjectType=RootObjectTypes.Global; // mGoToAddress.AddressType=AddressTypes.Physical; // // mMailToAddress=Address.NewItem(); // mMailToAddress.RootObjectID=Guid.Empty; // mMailToAddress.RootObjectType=RootObjectTypes.Global; // mMailToAddress.AddressType=AddressTypes.Postal; //Set record history to defaults mCreated = new SmartDate(DBUtil.CurrentWorkingDateTime); mModified=new SmartDate(); mCreator=Guid.Empty; mModifier=Guid.Empty; mUseInventory=false; mUseNotification=false; } #endregion #region Business properties // /// // /// Get internal id number Read only property because it's set internally, not // /// externally // /// // public Guid ID // { // get // { // return mID; // } // } /// /// Get created date /// /// /// [Browsable(false)] public string Created { get { return mCreated.ToString(); } } /// /// Get modified date /// /// /// [Browsable(false)] public string Modified { get { return mModified.ToString(); } } /// /// Get user record ID of person who created this record /// /// /// [Browsable(false)] public Guid Creator { get { return mCreator; } } /// /// Get user ID of person who modified this record /// /// /// [Browsable(false)] public Guid Modifier { get { return mModifier; } } /// /// Get service address for this client /// public Address GoToAddress { get { return mGoToAddress; } } /// /// Get mailing address object for this client /// Returns GoToAddress object if MailToAddress is empty /// public Address MailToAddress { get { return mMailToAddress; } } /// /// Default is true (allow) /// False means if schedule coflicts occurs, it gives a pop up message indicating /// so that you need to change it. /// True means it gives a popup letting you know, but lets you go ahead with /// schedule. /// We do not have an option to turn off popup as should purchase enough licenses /// to cover all users. /// [DefaultValue(true)] public bool AllowScheduleConflicts { get { return mAllowScheduleConflicts; } set { if(bReadOnly) ThrowSetError(); else { if(mAllowScheduleConflicts!=value) { mAllowScheduleConflicts = value; MarkDirty(); } } } } ///// ///// Default is false ///// If true, displays region settings and fields ///// If false, still uses a default region behind the scenes so "ready" to go to use ///// regions ///// //[DefaultValue(false)] //public bool UseRegions //{ // get // { // return mUseRegions; // } // set // { // if(bReadOnly) // ThrowSetError(); // else // { // if(mUseRegions!=value) // { // mUseRegions = value; // MarkDirty(); // } // } // } //} /// /// Default locale to use /// [DefaultValue("English")] [System.ComponentModel.TypeConverter(typeof(LocaleConverter))] public string DefaultLanguage { get { return mDefaultLanguage; } set { if(bReadOnly) ThrowSetError(); else { if(mDefaultLanguage!=value) { mDefaultLanguage = value; MarkDirty(); } } } } //[Browsable(false)] //public Guid DefaultPurchaseOrderTemplate //{ // get // { // return mDefaultPurchaseOrderTemplate; // } // set // { // if(bReadOnly) // ThrowSetError(); // else // { // if(mDefaultPurchaseOrderTemplate!=value) // { // mDefaultPurchaseOrderTemplate = value; // MarkDirty(); // } // } // } //} //[Browsable(false)] //public Guid DefaultQuoteTemplate //{ // get // { // return mDefaultQuoteTemplate; // } // set // { // if(bReadOnly) // ThrowSetError(); // else // { // if(mDefaultQuoteTemplate!=value) // { // mDefaultQuoteTemplate = value; // MarkDirty(); // } // } // } //} /// /// Default tax for selling parts /// [System.ComponentModel.TypeConverter(typeof(TaxCodeIDConverter))] public Guid TaxPartSaleID { get { return mTaxPartSaleID; } set { if(bReadOnly) ThrowSetError(); else { if(mTaxPartSaleID!=value) { mTaxPartSaleID = value; MarkDirty(); } } } } /// /// Default purchase tax code for parts /// [System.ComponentModel.TypeConverter(typeof(TaxCodeIDConverter))] public Guid TaxPartPurchaseID { get { return mTaxPartPurchaseID; } set { if(bReadOnly) ThrowSetError(); else { if(mTaxPartPurchaseID!=value) { mTaxPartPurchaseID = value; MarkDirty(); } } } } /// /// Default tax for selling services / rates /// [System.ComponentModel.TypeConverter(typeof(TaxCodeIDConverter))] public Guid TaxRateSaleID { get { return mTaxRateSaleID; } set { if(bReadOnly) ThrowSetError(); else { if(mTaxRateSaleID!=value) { mTaxRateSaleID = value; MarkDirty(); } } } } /// /// Default global service template ID to use when no other more specific template applies /// [Browsable(false)] public Guid DefaultServiceTemplateID { get { return mDefaultServiceTemplateID; } set { if(bReadOnly) ThrowSetError(); else { if (mDefaultServiceTemplateID != value) { mDefaultServiceTemplateID = value; MarkDirty(); } } } } // /// // /// Default is false // /// If true, checks spelling against internal dictionary (do we have a program to // /// do this?) following rules set by bool // /// NOTE: ignores words with numbers in it // /// // [DefaultValue(false)] // public bool SpellCheck // { // get // { // return mSpellCheck; // } // set // { // if(bReadOnly) // ThrowSetError(); // else // { // if(mSpellCheck!=value) // { // mSpellCheck = value; // MarkDirty(); // // } // } // } // } /// /// Status that identifies when a workorder is completed /// Used internally by the program for some functions. /// [Browsable(false)] public Guid WorkorderClosedStatus { get { return mWorkorderClosedStatus; } set { if(bReadOnly) ThrowSetError(); else { if(mWorkorderClosedStatus!=value) { mWorkorderClosedStatus = value; MarkDirty(); } } } } #region seed identity start values /// /// /// Reset starting number for auto incrementing workorder number /// Can only be set higher than current seed value /// public int WorkorderNumberStartSeed { get { return mWorkorderServiceStartSeed; } set { if(bReadOnly) ThrowSetError(); else { if(mWorkorderServiceStartSeed!=value) { mWorkorderServiceStartSeed = value; MarkDirty(); this.mUpdateWorkorderServiceStartSeed=true; } } } } /// /// Reset starting number for auto incrementing quote number /// Can only be set higher than current seed value /// public int QuoteNumberStartSeed { get { return mQuoteNumberStartSeed; } set { if(bReadOnly) ThrowSetError(); else { if(mQuoteNumberStartSeed!=value) { mQuoteNumberStartSeed = value; MarkDirty(); this.mUpdateQuoteNumberStartSeed=true; } } } } /// /// write only /// Reset starting number for auto incrementing Purchase Order number /// Can only be set higher than current seed value /// public int PurchaseOrderStartSeed { get { return mPurchaseOrderStartSeed; } set { if(bReadOnly) ThrowSetError(); else { if(mPurchaseOrderStartSeed!=value) { mPurchaseOrderStartSeed = value; MarkDirty(); this.mUpdatePurchaseOrderStartSeed=true; } } } } /// /// write only /// Reset starting number for auto incrementing InventoryAdjustment number /// Can only be set higher than current seed value /// public int InventoryAdjustmentStartSeed { get { return mInventoryAdjustmentStartSeed; } set { if(bReadOnly) ThrowSetError(); else { if(mInventoryAdjustmentStartSeed!=value) { mInventoryAdjustmentStartSeed = value; MarkDirty(); this.mUpdateInventoryAdjustmentStartSeed=true; } } } } #endregion /// /// Template for displaying information about a workorder /// compactly in summary form on calendars and in lists /// and reports /// (Maximum 500 characters) /// public string WorkorderSummaryTemplate { get { return mWorkorderSummaryTemplate; } set { if(bReadOnly) ThrowSetError(); else { if(mWorkorderSummaryTemplate!=value) {//TODO: if this is empty will it cause a bomb in the schedule screen? //should it default to something if it's set to empty, i.e. just the wo number or...? mWorkorderSummaryTemplate = value; BrokenRules.Assert("WorkorderSummaryTemplateLength", "Error.Object.FieldLengthExceeded,Global.Label.WorkorderSummaryTemplate,500", "WorkorderSummaryTemplate",value.Length>500); MarkDirty(); } } } } /// /// Default is false /// If true, activates AyaNova inventory tracking and features /// [DefaultValue(false)] public bool UseInventory { get { if (AyaBizUtils.Lite) return false;//case 1172 return mUseInventory; } set { if(bReadOnly) ThrowSetError(); else { if(mUseInventory!=value) { mUseInventory = value; MarkDirty(); } } } } /// /// Default /// [System.ComponentModel.TypeConverter(typeof(EnumDescConverter))] [DefaultValue(UnitNameDisplayFormats.SerialOnly)] public UnitNameDisplayFormats DefaultUnitNameDisplayFormat { get { return mDefaultUnitNameDisplayFormat; } set { if(bReadOnly) ThrowSetError(); else { if(mDefaultUnitNameDisplayFormat!=value) { mDefaultUnitNameDisplayFormat = value; MarkDirty(); } } } } /// /// Global default /// [System.ComponentModel.TypeConverter(typeof(EnumDescConverter))] [DefaultValue(ScheduleableUserNameDisplayFormats.FirstLast)] public ScheduleableUserNameDisplayFormats DefaultScheduleableUserNameDisplayFormat { get { return mDefaultScheduleableUserNameDisplayFormat; } set { if(bReadOnly) ThrowSetError(); else { if(mDefaultScheduleableUserNameDisplayFormat!=value) { mDefaultScheduleableUserNameDisplayFormat = value; MarkDirty(); } } } } /// /// Global default /// [System.ComponentModel.TypeConverter(typeof(EnumDescConverter))] [DefaultValue(PartDisplayFormats.NumberName)] public PartDisplayFormats DefaultPartDisplayFormat { get { return mDefaultPartDisplayFormat; } set { if(bReadOnly) ThrowSetError(); else { if(mDefaultPartDisplayFormat!=value) { mDefaultPartDisplayFormat = value; MarkDirty(); } } } } /// /// Indexing style to use for AyaNova internal search engine /// Default is false. /// /// If data entry is primarily in a language with no spacing or punctuation to /// identify the boundaries between words (Chinese, Japanese, Korean, Thai etc) then /// setting this value to true will use a 2 character segmentation system /// /// In all other languages with spacing and/or punctuation this value should be false to ensure most accurate word indexing /// /// [DefaultValue(false)] public bool CJKIndex { get { return this.mCJKIndex; } set { if(bReadOnly) ThrowSetError(); else { if(mCJKIndex!=value) { mCJKIndex = value; MarkDirty(); } } } } /// /// Default for how old in minutes a workorder has to be and not be closed before /// it's considered "stale" (for purposes of notification and display in some lists) /// /// This is used to catch forgotten workorders. /// This value is used to set the default CloseByDate by date/time in a service workorder. /// [DefaultValue(0)] public int WorkorderCloseByAge { get { return this.mWorkorderCloseByAge; } set { if(bReadOnly) ThrowSetError(); else { if(mWorkorderCloseByAge!=value) { mWorkorderCloseByAge = value; MarkDirty(); } } } } /// /// Default is false /// If true, activates AyaNova notification feature /// and causes biz objects to check for notification events /// and Process them as part of their normal updating routines /// [DefaultValue(false)] public bool UseNotification { get { return this.mUseNotification; } set { if(bReadOnly) ThrowSetError(); else { if(mUseNotification!=value) { mUseNotification = value; MarkDirty(); } } } } /// /// SMTP server to use for outgoing AyaNova generated email /// [DefaultValue("mail.yourserver.com")] public string NotifySMTPHost { get { return mNotifySMTPHost; } set { if(bReadOnly) ThrowSetError(); else { if(mNotifySMTPHost!=value) { mNotifySMTPHost = value; MarkDirty(); } } } } //Case 515 /// /// Extracts the port number if present from the end of the /// NotifySMTPHost property /// e.g. /// mail.yourhost.com:587 returns 587 /// mail.yourhost.com returns 25 /// public int NotifySMTPPort { get { if (string.IsNullOrEmpty(mNotifySMTPHost)) return 25; if (!mNotifySMTPHost.Contains(":")) return 25; string [] s=mNotifySMTPHost.Split(':'); if (s.GetLength(0) < 2) return 25; int nPort = 0; if (!System.Int32.TryParse(s[1], out nPort)) return 25; if (nPort == 0) return 25; return nPort; } } //Case 515 /// /// Extracts only host name portion of smtp host that might contain a port number /// on it's end /// public string NotifySMTPHostPortionOnly { get { if (!mNotifySMTPHost.Contains(":")) return mNotifySMTPHost; string s=mNotifySMTPHost.Substring(0, mNotifySMTPHost.IndexOf(":")); return s; } } //case 1136 /// /// Encryption protocol to use /// if value is SSL then ssl encryption is used /// if TLS then tls encryption used /// Any other value or no value means no encryption is used /// [DefaultValue("")] public string NotifySMTPEncryptionMethod { get { return mNotifySMTPEncryptionMethod; } set { if (bReadOnly) ThrowSetError(); else { if (mNotifySMTPEncryptionMethod != value) { mNotifySMTPEncryptionMethod = value; MarkDirty(); } } } } /// /// Read only flag used internally /// internal bool NotifySMTPUseSSL {//case 1136 get { if (mNotifySMTPEncryptionMethod.Equals("SSL", StringComparison.CurrentCultureIgnoreCase)) return true; return false; } } /// /// Read only flag used internally /// internal bool NotifySMTPUseTLS {//case 1136 get { if (mNotifySMTPEncryptionMethod.Equals("TLS", StringComparison.CurrentCultureIgnoreCase)) return true; return false; } } /// /// Email account AyaNova should use for sending email /// [DefaultValue("senderaccount@yourserver.com")] public string NotifySMTPAccount { get { return mNotifySMTPAccount; } set { if(bReadOnly) ThrowSetError(); else { if(mNotifySMTPAccount!=value) { mNotifySMTPAccount = value; MarkDirty(); } } } } /// /// SMTP Server password for NotifySMTPAccount /// [DefaultValue("senderaccountpassword")] public string NotifySMTPPassword { get { return mNotifySMTPPassword; } set { if(bReadOnly) ThrowSetError(); else { if(mNotifySMTPPassword!=value) { mNotifySMTPPassword = value; MarkDirty(); } } } } /// /// Outgoing email messages sent by AyaNova will have the From address set to this value /// [DefaultValue("fromaddress@yourserver.com")] public string NotifySMTPFrom { get { return mNotifySMTPFrom; } set { if(bReadOnly) ThrowSetError(); else { if(mNotifySMTPFrom!=value) { mNotifySMTPFrom = value; MarkDirty(); } } } } /// /// Global default /// [System.ComponentModel.TypeConverter(typeof(EnumDescConverter))] [DefaultValue(CoordinateTypes.DegreesDecimalMinutes)] public CoordinateTypes CoordinateStyle { get { return mCoordinateStyle; } set { if(bReadOnly) ThrowSetError(); else { if(mCoordinateStyle!=value) { mCoordinateStyle = value; MarkDirty(); } } } } /// /// Default hemisphere for interpreting co-ordinates /// See /// [System.ComponentModel.TypeConverter(typeof(EnumDescConverter))] [DefaultValue(LatitudeHemisphere.North)] public LatitudeHemisphere DefaultLatitude { get { return mDefaultLatitude; } set { if(bReadOnly) ThrowSetError(); else { if(mDefaultLatitude!=value) { mDefaultLatitude = value; MarkDirty(); } } } } /// /// Default prime meridian offset for interpreting co-ordinates /// See /// [System.ComponentModel.TypeConverter(typeof(EnumDescConverter))] [DefaultValue(LongitudeHemisphere.West)] public LongitudeHemisphere DefaultLongitude { get { return mDefaultLongitude; } set { if(bReadOnly) ThrowSetError(); else { if(mDefaultLongitude!=value) { mDefaultLongitude = value; MarkDirty(); } } } } /// /// Returns true if passed in tax code ID /// is used as the default anywhere in global settings /// /// /// public bool TaxCodeIsADefault(Guid TaxCodeID) { if(this.mTaxPartPurchaseID==TaxCodeID) return true; if(this.mTaxPartSaleID==TaxCodeID) return true; if(this.mTaxRateSaleID==TaxCodeID) return true; return false; } /// /// Maximum file size that users can store in the database /// [DefaultValue(50)] public int MaxFileSizeMB//case 73 { get { return this.mMaxFileSizeMB; } set { if (bReadOnly) ThrowSetError(); else { if (value > 50) value = 50; if (mMaxFileSizeMB != value) { mMaxFileSizeMB = value; MarkDirty(); } } } } /// /// Flag - indicates if current user can open the wiki page for this object /// Note that in this case there is a special right "Object.GlobalWikiPage" that is checked instead /// of the normal process of checking the companion object's rights because many users may want /// to allow all users to edit the global wiki but not allow them to edit the global object itself /// /// /// This is NOT cached for the lifetime of this object /// since it could be hanging around between sessions /// public bool CanWiki//case 73 { get { return WikiPage.ShowWikiLink(RootObjectTypes.Global, Address.GlobalAddressID); } } /// /// Default auto complete minutes for new labor or sched user records /// when start date / time is first entered /// [DefaultValue(60)] public int LaborSchedUserDfltTimeSpan//case 816 { get { return this.mLaborSchedUserDfltTimeSpan; } set { if (bReadOnly) ThrowSetError(); else { if (mLaborSchedUserDfltTimeSpan != value) { mLaborSchedUserDfltTimeSpan = value; MarkDirty(); } } } } /// /// Default auto complete minutes for new workorderitemtravel records /// when start date / time is first entered /// [DefaultValue(60)] public int TravelDfltTimeSpan//case 816 { get { return this.mTravelDfltTimeSpan; } set { if (bReadOnly) ThrowSetError(); else { if (mTravelDfltTimeSpan != value) { mTravelDfltTimeSpan = value; MarkDirty(); } } } } //case 1382 /// /// Default is false /// If true, notification deliveries via SMTP (SMTP/SMS) that fail /// because Generator can not contact and log into the SMTP server will be /// kept and retried at next generator process. /// /// Note this only applies to failure to connect to the smtp server, notifications that have other /// reasons for not being delivered (i.e. bad email address etc) will still be removed after failed delivery. /// /// If this is false then any failure to deliver a notification via SMTP will result in that notification being /// removed permanently. This is the original behaviour. /// [DefaultValue(false)] public bool SMTPRetry { get { return this.mSMTPRetry; } set { if (bReadOnly) ThrowSetError(); else { if (mSMTPRetry != value) { mSMTPRetry = value; MarkDirty(); } } } } /// /// Form controls to hide as set by administrator /// public System.Collections.Generic.List HiddenControls { get { if (mHiddenControls == null) { mHiddenControls = new System.Collections.Generic.List(); } return mHiddenControls; } } /// /// Add a control to the hidden controls collection /// /// [Browsable(false)] public void AddHiddenControl(string sControl) { if (!HiddenControls.Contains(sControl)) { HiddenControls.Add(sControl); MarkDirty(); } } /// /// Remove a control from the hidden controls collection /// /// [Browsable(false)] public void RemoveHiddenControl(string sControl) { if (HiddenControls.Contains(sControl)) { HiddenControls.Remove(sControl); MarkDirty(); } } //case 1346 /// /// Title above signature pad /// [DefaultValue("Please sign below")] public string SignatureTitle { get { return mSignatureTitle; } set { if (bReadOnly) ThrowSetError(); else { if (mSignatureTitle != value) { mSignatureTitle = value; MarkDirty(); } } } } /// /// Text above signature area below title /// /// [DefaultValue("By signing below you agree to terms for service provided")] public string SignatureHeader { get { return mSignatureHeader; } set { if (bReadOnly) ThrowSetError(); else { if (mSignatureHeader != value) { mSignatureHeader = value; MarkDirty(); } } } } /// /// Text below signature area /// /// [DefaultValue("")] public string SignatureFooter { get { return mSignatureFooter; } set { if (bReadOnly) ThrowSetError(); else { if (mSignatureFooter != value) { mSignatureFooter = value; MarkDirty(); } } } } //case 1392 /// /// Scheduled user default time for new records when choosing start date other than today /// public string SchedUserNonTodayStartTime { get { mSchedUserNonTodayStartTime.FormatString="t"; return mSchedUserNonTodayStartTime.Text; } set { if (bReadOnly) ThrowSetError(); else { SmartDate sd = new SmartDate(); sd.Text = value; if (!AyaBizUtils.SmartDateEquals(mSchedUserNonTodayStartTime, sd)) { if (!sd.IsEmpty) { sd.Date = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, sd.Date.Hour, sd.Date.Minute, sd.Date.Second); } mSchedUserNonTodayStartTime = sd; MarkDirty(); } } } } //case 1487 /// /// Default is true /// Turns on or off automatic refresh of main grids in AyaNova for windows /// [DefaultValue(true)] public bool MainGridAutoRefresh { get { return this.mMainGridAutoRefresh; } set { if (bReadOnly) ThrowSetError(); else { if (mMainGridAutoRefresh != value) { mMainGridAutoRefresh = value; MarkDirty(); } } } } /// /// Throw an error when a read only user /// tries to set a property /// (this should normally never be called unless someone is using the developer api since the UI /// should prevent it from happening initially) /// private void ThrowSetError() { throw new System.Security.SecurityException ( string.Format ( LocalizedTextTable.GetLocalizedTextDirect("Error.Security.NotAuthorizedToChange"), LocalizedTextTable.GetLocalizedTextDirect("O.Global") ) ); } #endregion #region System.Object overrides /// /// /// /// public override string ToString() { return "Global" ; } /// /// /// /// /// public override bool Equals(Object obj) { return true; } /// /// /// /// public override int GetHashCode() { return ("Global" ).GetHashCode(); } #endregion #region Static methods /// /// Fetch the one and only Global item /// /// public static Global GetItem() { if(!AyaBizUtils.Lite && !User.IsAdmin && ScheduleableUserCountFetcher.GetItem()>AyaBizUtils.GlobalX.ScheduleableUsers )//case 1172 { throw new System.Security.SecurityException( "\r\nLICENSE VIOLATION\r\n\r\n" + "AyaNova has detected an attempt to circumvent AyaNova licensing.\r\n\r\n" + "This database is licensed for " + AyaBizUtils.GlobalX.ScheduleableUsers.ToString() + " scheduleable users\r\n" + "Currently there are " + ScheduleableUserCountFetcher.GetItem().ToString() + " scheduleable users active.\r\n\r\n" + "All AyaNova accounts other than Manager have been suspended until\r\n" + "the extra scheduleable users that are not licensed are\r\n" + "set inactive, removed or changed to non-scheduleable users\r\n"+ "to bring this database back into license compliance.\r\n\r\n"+ "Directly editing the AyaNova database can lead to lost or damaged data\r\n"+ "Please ensure no one tampers with the AyaNova database in future.\r\n\r\n" + "** License violations are logged for the protection of the licensee and licensor **"); } //if(AyaBizUtils.Right("Object.Global")>(int)SecurityLevelTypes.NoAccess || AyaBizUtils.IsGenerator ) return (Global)DataPortal.Fetch(new Criteria()); // else // throw new System.Security.SecurityException( // string.Format( // LocalizedTextTable.GetLocalizedTextDirect("Error.Security.NotAuthorizedToRetrieve"), // LocalizedTextTable.GetLocalizedTextDirect("O.Global"))); } [Browsable(false)] internal static Global GetItemInternally() { //Internal version used by util class to verify license etc //no security check because this will be fetched //before a user has logged in. //however it cannot be called from outside this assembly so it's not a risk return (Global)DataPortal.Fetch(new Criteria()); } #endregion #region DAL DATA ACCESS #region Custom concurrency check private static void CheckSafeToUpdate(System.DateTime LastUpdated) { DBCommandWrapper dbCommandWrapper = DBUtil.DB.GetSqlStringCommandWrapper( "SELECT aModified, aModifier FROM aGlobal;" ); SafeDataReader r = new SafeDataReader(DBUtil.DB.ExecuteReader(dbCommandWrapper)); if(r.Read()) { if(!DBUtil.DatesAreEqualish(DBUtil.ToUTC(LastUpdated),r.GetSmartDate("aModified").Date)) { Guid gModifier=r.GetGuid("aModifier"); r.Close(); dbCommandWrapper.Command.Parameters.Clear(); dbCommandWrapper.AddInParameter("@ID",DbType.Guid,gModifier); dbCommandWrapper.Command.CommandText="SELECT aFirstName, aLastName FROM aUser WHERE aID = @ID"; r=new SafeDataReader(DBUtil.DB.ExecuteReader(dbCommandWrapper)); if(r.Read()) { string sUser=r.GetString("aFirstName") + " " + r.GetString("aLastName"); r.Close(); throw new System.Exception(string.Format(LocalizedTextTable.GetLocalizedTextDirect("Error.DB.RecordModifiedExternally"),"Global",sUser)); } } else { //de nada r.Close(); return; } } //Added: 20-June-2006 r.Close(); } #endregion #region Fetch /// /// protected override void DataPortal_Fetch(object Criteria) { //set to false to load items initially bReadOnly=false; Criteria crit = (Criteria)Criteria; SafeDataReader dr = null; try { dr=DBUtil.GetReaderFromSQLString("SELECT * FROM aGlobal;"); if(!dr.Read()) DBUtil.ThrowFetchError("Global"); //Standard fields //mID=dr.GetGuid("aID"); mCreated=DBUtil.ToLocal(dr.GetSmartDate("aCreated")); mModified=DBUtil.ToLocal(dr.GetSmartDate("aModified")); mCreator=dr.GetGuid("aCreator"); mModifier=dr.GetGuid("aModifier"); //Global fields mTaxPartSaleID=dr.GetGuid("aTaxPartSaleID"); //case 1858 if(AyaBizUtils.Lite) mTaxPartPurchaseID = Guid.Empty; else mTaxPartPurchaseID=dr.GetGuid("aTaxPartPurchaseID"); mTaxRateSaleID=dr.GetGuid("aTaxRateSaleID"); //case 2104 added in schema 46 if (AyaBizUtils.GlobalX.DBSchemaVersion > 45) { mDefaultServiceTemplateID = dr.GetGuid("ADEFAULTSERVICETEMPLATEID"); } mAllowScheduleConflicts=dr.GetBoolean("AALLOWSCHEDULECONFLICTS");//AALLOWSCHEDULECONFLICTS mDefaultLanguage=dr.GetString("aLanguage"); //mUseRegions=dr.GetBoolean("aUseRegions"); mWorkorderClosedStatus=dr.GetGuid("aWorkorderClosedStatus"); mWorkorderSummaryTemplate=dr.GetString("aWorkorderSummaryTemplate"); mUseInventory=dr.GetBoolean("aUseInventory"); mDefaultUnitNameDisplayFormat=(UnitNameDisplayFormats)dr.GetInt16("aUnitNameFormat"); mDefaultScheduleableUserNameDisplayFormat=(ScheduleableUserNameDisplayFormats)dr.GetInt16("aScheduleableUserNameFormat"); mCJKIndex=dr.GetBoolean("aCJKIndex"); mDefaultPartDisplayFormat=(PartDisplayFormats)dr.GetInt16("aPartFormat"); mWorkorderCloseByAge=dr.GetInt32("aWorkorderCloseByAge"); //case 2102 added in schema 64 if (AyaBizUtils.GlobalX.DBSchemaVersion > 63) { //case 73 mMaxFileSizeMB = dr.GetInt32("aMaxFileSizeMB"); } //case 2102 added in schema 78 if (AyaBizUtils.GlobalX.DBSchemaVersion > 77) { //case 816 mLaborSchedUserDfltTimeSpan = dr.GetInt32("aLaborSchedUserDfltTimeSpan"); mTravelDfltTimeSpan = dr.GetInt32("aTravelDfltTimeSpan"); } //Notification fields mUseNotification=dr.GetBoolean("aUseNotification"); mNotifySMTPHost=dr.GetString("aNotifySMTPHost"); mNotifySMTPAccount=dr.GetString("aNotifySMTPAccount"); mNotifySMTPPassword=dr.GetString("aNotifySMTPPassword"); mNotifySMTPFrom=dr.GetString("aNotifySMTPFrom"); //case 2100 added in schema 99 if (AyaBizUtils.GlobalX.DBSchemaVersion > 98) { //case 1382 mSMTPRetry = dr.GetBoolean("ASMTPRETRY"); } //case 2100 added in schema 89 if (AyaBizUtils.GlobalX.DBSchemaVersion > 88) { //case 1136 mNotifySMTPEncryptionMethod = dr.GetString("aNotifyEncryption"); } mCoordinateStyle=(CoordinateTypes)dr.GetInt16("aCoordinateStyle"); mDefaultLatitude=(LatitudeHemisphere)dr.GetInt16("aDefaultLatitude"); mDefaultLongitude=(LongitudeHemisphere)dr.GetInt16("aDefaultLongitude"); //case 1194 mHiddenControls = new System.Collections.Generic.List(); //case 2099 update to 7.4 throws exception on aformcustom not a column string s = string.Empty; if (AyaBizUtils.GlobalX.DBSchemaVersion > 99) { s = dr.GetString("AFORMCUSTOM"); } if (!string.IsNullOrWhiteSpace(s)) { mHiddenControls.AddRange(s.Split(',')); } //case 2099 sigs added in schema 104 if (AyaBizUtils.GlobalX.DBSchemaVersion > 103) { //case 1346 mSignatureTitle = dr.GetString("ASIGNATURETITLE"); mSignatureHeader = dr.GetString("ASIGNATUREHEADER"); mSignatureFooter = dr.GetString("ASIGNATUREFOOTER"); } //case 2099 added in schema 108 if (AyaBizUtils.GlobalX.DBSchemaVersion > 108) { //case 1392 mSchedUserNonTodayStartTime = DBUtil.ToLocal(dr.GetSmartDate("ASCHEDUSERNONTODAYSTARTTIME")); } //case 2099 added in schema 110 if (AyaBizUtils.GlobalX.DBSchemaVersion > 109) { //case 1487 mMainGridAutoRefresh = dr.GetBoolean("AMAINGRIDAUTOREFRESH"); } if(dr!=null) dr.Close(); /* Load child collection objects */ //GoToAddress dr=DBUtil.GetReaderFromSQLString("SELECT * " + "FROM AADDRESS WHERE aRootObjectID=@ID AND " + "aRootObjectType=1 AND AADDRESSTYPE=2",Address.GlobalAddressID); if(!dr.Read()) { mGoToAddress=Address.NewItem(); mGoToAddress.RootObjectID=Address.GlobalAddressID; mGoToAddress.RootObjectType=RootObjectTypes.Global; mGoToAddress.AddressType=AddressTypes.Physical; } else { mGoToAddress=Address.GetItem(dr); } if(dr!=null) dr.Close(); //MailToAddress dr=DBUtil.GetReaderFromSQLString("SELECT * " + "FROM AADDRESS WHERE aRootObjectID=@ID AND " + "aRootObjectType=1 AND AADDRESSTYPE=1",Address.GlobalAddressID); if(!dr.Read()) { mMailToAddress=Address.NewItem(); mMailToAddress.RootObjectID=Address.GlobalAddressID; mMailToAddress.RootObjectType=RootObjectTypes.Global; mMailToAddress.AddressType=AddressTypes.Postal; } else { mMailToAddress=Address.GetItem(dr); } //Load start seed values Object o=DBUtil.GetScalarFromSQLString( "SELECT MAX(aServiceNumber) FROM aWorkorderService" ); if(o==null || o==System.DBNull.Value) o=0; mWorkorderServiceStartSeed=(int)o; o=DBUtil.GetScalarFromSQLString( "SELECT MAX(aQuoteNumber) FROM aWorkorderQuote" ); if(o==null || o==System.DBNull.Value) o=0; mQuoteNumberStartSeed=(int)o; o=DBUtil.GetScalarFromSQLString( "SELECT MAX(aPONumber) FROM aPurchaseOrder" ); if(o==null || o==System.DBNull.Value) o=0; mPurchaseOrderStartSeed=(int)o; o=DBUtil.GetScalarFromSQLString( "SELECT MAX(AADJUSTMENTNUMBER) FROM aPartInventoryAdjustment" ); if(o==null || o==System.DBNull.Value) o=0; mInventoryAdjustmentStartSeed=(int)o; } finally { if(dr!=null) dr.Close(); } MarkOld(); //special code to update the identity with selected values //so that a remote dataportal has access to the values for the biz objects //BUGBUG BusinessPrincipal p = ((BusinessPrincipal)Thread.CurrentPrincipal); p.CJKIndex=mCJKIndex; p.UseNotification=this.mUseNotification; //Get access rights level bReadOnly=AyaBizUtils.Right("Object.Global")<(int)SecurityLevelTypes.ReadWrite; } #endregion #region Update /// /// Called by DataPortal to delete/add/update data into the database /// protected override void DataPortal_Update() { // If not a new record, check if record was modified //by another user since original retrieval: if(!IsNew) CheckSafeToUpdate(this.mModified.Date); #region Delete if(IsDeleted) { throw new System.ApplicationException ( string.Format ( LocalizedTextTable.GetLocalizedTextDirect("Error.Object.NotDeleteable"), LocalizedTextTable.GetLocalizedTextDirect("O.Global") ) ); } #endregion #region Add / Update //get modification time temporarily, if update succeeds then //set to this time System.DateTime dtModified = DBUtil.CurrentWorkingDateTime; DBCommandWrapper cm = null; //UPDATE IS THE ONLY VALID OPERATION FOR THE GLOBAL OBJECT cm=DBUtil.GetCommandFromSQL( "UPDATE aGlobal SET aTaxPartSaleID=@TaxPartSaleID, " + "aTaxRateSaleID=@TaxRateSaleID,aTaxPartPurchaseID=@TaxPartPurchaseID, " + "ADEFAULTSERVICETEMPLATEID=@ADEFAULTSERVICETEMPLATEID, " + //"aQuoteTemplate=@DefaultQuoteTemplate, " + //"aPurchaseOrderTemplate=@DefaultPurchaseOrderTemplate, " + /*"aSpellCheck=@SpellCheck, " +*/ "aMaxFileSizeMB=@MaxFileSizeMB, " +//case 73 "aLaborSchedUserDfltTimeSpan=@LaborSchedUserDfltTimeSpan, aTravelDfltTimeSpan=@TravelDfltTimeSpan, " + //case 816 "AALLOWSCHEDULECONFLICTS=@AllowScheduleConflicts, " + "aLanguage=@DefaultLanguage, " + "aWorkorderClosedStatus=@WorkorderClosedStatus, " + "aWorkorderSummaryTemplate=@WorkorderSummaryTemplate, " + "aModifier=@CurrentUserID, aUseInventory=@UseInventory, " + "aUnitNameFormat=@DefaultUnitNameDisplayFormat, " + "aScheduleableUserNameFormat=@DefaultScheduleableUserNameDisplayFormat, " + "aWorkorderCloseByAge=@WorkorderCloseByAge,aUseNotification=@UseNotification, " + "aNotifySMTPHost=@NotifySMTPHost, aNotifySMTPAccount=@NotifySMTPAccount, " + "aNotifySMTPPassword=@NotifySMTPPassword,aNotifySMTPFrom=@NotifySMTPFrom, " + "aNotifyEncryption=@NOTIFYENCRYPTION, ASMTPRETRY=@SMTPRETRY, AFORMCUSTOM=@FORMCUSTOM, " +//case 1194 "aCJKIndex=@CJKIndex,aPartFormat=@PartFormat,aCoordinateStyle=@CoordinateStyle, " + "ASIGNATURETITLE=@SIGNATURETITLE, ASIGNATUREHEADER=@SIGNATUREHEADER, ASIGNATUREFOOTER=@SIGNATUREFOOTER, " + // CASE 1346 "ASCHEDUSERNONTODAYSTARTTIME=@SCHEDUSERNONTODAYSTARTTIME, AMAINGRIDAUTOREFRESH=@MAINGRIDAUTOREFRESH, " + // case 1392 //case 1487 "aDefaultLatitude=@DefaultLatitude, aDefaultLongitude=@DefaultLongitude, aModified=@Modified;" ); //Standard fields cm.AddInParameter("@CurrentUserID",DbType.Guid, CurrentUserID); cm.AddInParameter("@Modified",DbType.DateTime, DBUtil.ToUTC(dtModified)); //Global fields cm.AddInParameter("@TaxPartSaleID", DbType.Guid, mTaxPartSaleID); //case 1858 if(AyaBizUtils.Lite) mTaxPartPurchaseID = Guid.Empty; cm.AddInParameter("@TaxPartPurchaseID", DbType.Guid, mTaxPartPurchaseID); cm.AddInParameter("@TaxRateSaleID", DbType.Guid, mTaxRateSaleID); cm.AddInParameter("@ADEFAULTSERVICETEMPLATEID", DbType.Guid, mDefaultServiceTemplateID); //cm.AddInParameter("@DefaultQuoteTemplate", DbType.Guid, mDefaultQuoteTemplate); //cm.AddInParameter("@DefaultPurchaseOrderTemplate", DbType.Guid, mDefaultPurchaseOrderTemplate); //cm.AddInParameter("@SpellCheck", DbType.Boolean, mSpellCheck); cm.AddInParameter("@AllowScheduleConflicts", DbType.Boolean, mAllowScheduleConflicts); cm.AddInParameter("@DefaultLanguage", DbType.String, mDefaultLanguage); //cm.AddInParameter("@UseRegions", DbType.Boolean, mUseRegions); cm.AddInParameter("@WorkorderClosedStatus", DbType.Guid, mWorkorderClosedStatus); cm.AddInParameter("@WorkorderSummaryTemplate", DbType.String, mWorkorderSummaryTemplate); cm.AddInParameter("@UseInventory", DbType.Boolean, mUseInventory); cm.AddInParameter("@DefaultUnitNameDisplayFormat", DbType.Int16, (int)mDefaultUnitNameDisplayFormat); cm.AddInParameter("@DefaultScheduleableUserNameDisplayFormat", DbType.Int16, (int)mDefaultScheduleableUserNameDisplayFormat); cm.AddInParameter("@CJKIndex", DbType.Boolean, mCJKIndex); cm.AddInParameter("@PartFormat", DbType.Int16, (int)mDefaultPartDisplayFormat); cm.AddInParameter("@WorkorderCloseByAge", DbType.Int32, mWorkorderCloseByAge); cm.AddInParameter("@UseNotification", DbType.Boolean, mUseNotification); cm.AddInParameter("@NotifySMTPHost", DbType.String, mNotifySMTPHost); cm.AddInParameter("@NotifySMTPAccount", DbType.String, mNotifySMTPAccount); cm.AddInParameter("@NotifySMTPPassword", DbType.String, mNotifySMTPPassword); cm.AddInParameter("@NotifySMTPFrom", DbType.String, mNotifySMTPFrom); //case 1136 cm.AddInParameter("@NOTIFYENCRYPTION", DbType.String, mNotifySMTPEncryptionMethod); //case 1382 cm.AddInParameter("@SMTPRETRY", DbType.Boolean, mSMTPRetry); //case 1194 //Load generic list back into string for saving System.Text.StringBuilder sbFormCustom = new StringBuilder(); foreach (string s in mHiddenControls) { sbFormCustom.Append(s); sbFormCustom.Append(","); } if (sbFormCustom.Length > 0) sbFormCustom.Length = sbFormCustom.Length - 1; cm.AddInParameter("@FORMCUSTOM", DbType.String, sbFormCustom.ToString()); cm.AddInParameter("@CoordinateStyle",DbType.Int16,(int)mCoordinateStyle); cm.AddInParameter("@DefaultLatitude",DbType.Int16,(int)mDefaultLatitude); cm.AddInParameter("@DefaultLongitude",DbType.Int16,(int)mDefaultLongitude); cm.AddInParameter("@MaxFileSizeMB", DbType.Int32, mMaxFileSizeMB);//case 73 cm.AddInParameter("@LaborSchedUserDfltTimeSpan", DbType.Int32, mLaborSchedUserDfltTimeSpan);//case 816 cm.AddInParameter("@TravelDfltTimeSpan", DbType.Int32, mTravelDfltTimeSpan);//case 816 //case 1346 cm.AddInParameter("@SIGNATURETITLE", DbType.String, mSignatureTitle); cm.AddInParameter("@SIGNATUREHEADER", DbType.String, mSignatureHeader); cm.AddInParameter("@SIGNATUREFOOTER", DbType.String, mSignatureFooter); //case 1392 cm.AddInParameter("@SCHEDUSERNONTODAYSTARTTIME", DbType.DateTime, DBUtil.ToUTC(mSchedUserNonTodayStartTime).DBValue); //case 1487 cm.AddInParameter("@MAINGRIDAUTOREFRESH", DbType.Boolean, mMainGridAutoRefresh); using (IDbConnection connection = DBUtil.DB.GetConnection()) { connection.Open(); IDbTransaction transaction = connection.BeginTransaction(); try { //Update child objects //GoToAddress mGoToAddress.Update(RootObjectTypes.Global,Address.GlobalAddressID,AddressTypes.Physical,transaction); //MailToAddress mMailToAddress.Update(RootObjectTypes.Global,Address.GlobalAddressID,AddressTypes.Postal,transaction); DBUtil.DB.ExecuteNonQuery(cm, transaction); MarkOld();//db is now synched with object // Commit the transaction transaction.Commit(); } catch { // Rollback transaction transaction.Rollback(); throw; } finally { connection.Close(); } //Successful update so //change modification time to match this.mModified.Date=dtModified; //special code to update the identity with the global settings values //so that a remote dataportal has access to these value for the biz objects BusinessPrincipal p = ((BusinessPrincipal)Thread.CurrentPrincipal); p.CJKIndex=mCJKIndex; p.UseNotification=this.mUseNotification; } //Set new seed values if required if(this.mUpdateWorkorderServiceStartSeed) { WorkorderService.SetVisibleIDNumber(this.mWorkorderServiceStartSeed); } if(this.mUpdateQuoteNumberStartSeed) { WorkorderQuote.SetVisibleIDNumber(this.mQuoteNumberStartSeed); } if(this.mUpdatePurchaseOrderStartSeed) { PurchaseOrder.SetVisibleIDNumber(this.mPurchaseOrderStartSeed); } if(this.mUpdateInventoryAdjustmentStartSeed) { PartInventoryAdjustment.SetVisibleIDNumber(this.mInventoryAdjustmentStartSeed); } #endregion //case 1035 //this is to trigger a reset of the cached global settings object in the dataportal //this ensures when global is saved that the changes are reflected when running via dataportal DBManager.ResetCacheInDataPortal.Reset(); } #endregion #endregion #region Override IsValid / IsDirty etc etc /// /// /// [Browsable(false)] public override bool IsValid { get { return base.IsValid && mGoToAddress.IsValid && mMailToAddress.IsValid; } } /// /// /// [Browsable(false)] public override bool IsDirty { get { return base.IsDirty || mGoToAddress.IsDirty || mMailToAddress.IsDirty; } } #endregion #region criteria /// /// Criteria for identifying existing object /// [Serializable] private class Criteria { //public Guid ID; public Criteria() { } } #endregion }//end Global }//end namespace GZTW.AyaNova.BLL