/////////////////////////////////////////////////////////// // WorkorderItemTravel.cs // Implementation of Class WorkorderItemTravel // CSLA type: Editable Child // Created on: 07-Jun-2004 8:41:51 AM // Object design: Joyce // Coded: John 26-July-2004 /////////////////////////////////////////////////////////// using System; using System.Data; using CSLA.Data; using GZTW.Data; using CSLA; using System.Threading; using CSLA.Security; namespace GZTW.AyaNova.BLL { /// /// Travel object for object's collection /// [Serializable] public class WorkorderItemTravel : BusinessBase { #region Attributes private bool bReadOnly; private Guid mID; private SmartDate mCreated; private SmartDate mModified; private Guid mCreator; private Guid mModifier; private string mNotes=""; private Guid mWorkorderItemID; private Guid mUserID; private SmartDate mTravelStartDate; private SmartDate mTravelStopDate; private Guid mTravelRateID; private string mTravelDetails=""; private decimal mTravelRateQuantity; private decimal mNoChargeQuantity; //------------------------- private decimal mDistance; private Guid mTaxRateSaleID; private Guid mServiceBankID; #endregion #region Constructor /// /// Private constructor to prevent direct instantiation /// private WorkorderItemTravel() { //Set to read / write initially so that properties //can be set bReadOnly=false; //Child object MarkAsChild(); //New ID mID = Guid.NewGuid(); mTravelStartDate= new SmartDate(); mTravelStopDate=new SmartDate(); //Set record history to defaults mCreated = new SmartDate(DBUtil.CurrentWorkingDateTime); mModified=new SmartDate(); mCreator=Guid.Empty; mModifier=Guid.Empty; mServiceBankID=Guid.Empty; mTaxRateSaleID=AyaBizUtils.GlobalSettings.TaxRateSaleID; } #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 /// /// /// public string Created { get { return mCreated.ToString(); } } /// /// Get modified date /// /// /// public string Modified { get { return mModified.ToString(); } } /// /// Get user record ID of person who created this record /// /// /// public Guid Creator { get { return mCreator; } } /// /// Get user ID of person who modified this record /// /// /// public Guid Modifier { get { return mModifier; } } //case 2006 /// /// DEPRECATED: API USERS - DO NOT USE THIS FIELD. /// IT HAS NEVER BEEN EXPOSED IN THE USER INTERFACE /// AND MAY BE DROPPED ENTIRELY IN A FUTURE RELEASE /// public string Notes { get { return mNotes; } set { if(bReadOnly) ThrowSetError(); else { if(mNotes!=value) { mNotes = value; MarkDirty(); } } } } /// /// ID /// public Guid UserID { get { return mUserID; } set { if(bReadOnly) ThrowSetError(); else { if(mUserID!=value) { mUserID = value; MarkDirty(); } } } } /// /// Quantity of travel /// public decimal TravelRateQuantity { get { return mTravelRateQuantity; } set { if(bReadOnly) ThrowSetError(); else { if(mTravelRateQuantity!=value) { mTravelRateQuantity = value; MarkDirty(); } } } } /// /// Quantity of travel provided at no charge /// /// public decimal NoChargeQuantity { get { return mNoChargeQuantity; } set { if(bReadOnly) ThrowSetError(); else { if(mNoChargeQuantity!=value) { mNoChargeQuantity = value; MarkDirty(); } } } } /// /// Travel start date and time /// public object TravelStartDate { get { return mTravelStartDate.DBValue; } set { if(bReadOnly) ThrowSetError(); else { if (!AyaBizUtils.SmartDateEquals(mTravelStartDate, value)) //Case 298 { mTravelStartDate.DBValue = value; //Added: 4-Nov- 2006 autocomplete time if (!mTravelStartDate.IsEmpty && mTravelStopDate.IsEmpty && (AyaBizUtils.GlobalSettings.TravelDfltTimeSpan != 0)) mTravelStopDate.Date = mTravelStartDate.Date.AddMinutes(AyaBizUtils.GlobalSettings.TravelDfltTimeSpan);//case 816 MarkDirty(); } } } } /// /// Travel stop date and time /// public object TravelStopDate { get { return mTravelStopDate.DBValue; } set { if(bReadOnly) ThrowSetError(); else { if (!AyaBizUtils.SmartDateEquals(mTravelStopDate, value)) //Case 298 { mTravelStopDate.DBValue = value; //Added: 4-Nov- 2006 autocomplete time if (!mTravelStopDate.IsEmpty && mTravelStartDate.IsEmpty && (AyaBizUtils.GlobalSettings.TravelDfltTimeSpan != 0)) mTravelStartDate.Date = mTravelStopDate.Date.AddMinutes(-AyaBizUtils.GlobalSettings.TravelDfltTimeSpan);//case 816 MarkDirty(); } } } } #region PM accessible start / stop dates internal DateTime dtTravelStartDate { get { return mTravelStartDate.Date; } set { if(mTravelStartDate.Date!=value) { mTravelStartDate.Date = value; MarkDirty(); } } } internal DateTime dtTravelStopDate { get { return mTravelStopDate.Date; } set { if(mTravelStopDate.Date!=value) { mTravelStopDate.Date = value; MarkDirty(); } } } #endregion /// /// used for travel charges /// public Guid TravelRateID { get { return mTravelRateID; } set { if(bReadOnly) ThrowSetError(); else { if(mTravelRateID!=value) { mTravelRateID = value; MarkDirty(); } } } } /// /// Up to 255 characters of notes on travel charges /// public string TravelDetails { get { return mTravelDetails; } set { if(bReadOnly) ThrowSetError(); else { if(mTravelDetails!=value) { mTravelDetails = value; //case 2006 added this rule BrokenRules.Assert("TravelDetailsLength", "Error.Object.FieldLengthExceeded255,WorkorderItemTravel.Label.TravelDetails", "TravelDetails", value.Length > 255); MarkDirty(); } } } } /// /// Guid ID of parent object /// public Guid WorkorderItemID { get { return mWorkorderItemID; } // set // { // if(bReadOnly) // ThrowSetError(); // else // { // if(mWorkorderItemID!=value) // { // mWorkorderItemID = value; // MarkDirty(); // // } // } // } } /// /// Sales for travel /// public Guid TaxRateSaleID { get { return mTaxRateSaleID; } set { if(bReadOnly) ThrowSetError(); else { if(mTaxRateSaleID!=value) { mTaxRateSaleID = value; MarkDirty(); } } } } /// /// Called by parent collection object /// when called in turn by workorder object that is read only due to /// security or closed or service completed /// /// Either true or the rights allowed for the current user public void SetReadOnly(bool RO) { bReadOnly=RO; } /// /// Distance travelled /// public decimal Distance { get { return mDistance; } set { if(bReadOnly) ThrowSetError(); else { if(mDistance!=value) { mDistance = value; MarkDirty(); } } } } /// /// Applies this travel entry to service bank /// and sets ServiceBankID /// /// Populate TypeAndID object /// Rate currency per unit for banked currency calcs /// Descriptive text to enter in service bank /// (255 char - the localized text length of O.WorkorderItemTravel which is inserted automatically before description) public void ApplyToServiceBank(TypeAndID tid, decimal TravelRate, string Description) { if (mServiceBankID != Guid.Empty) throw new System.ApplicationException (LocalizedTextTable.GetLocalizedTextDirect("WorkorderItemLabor.Label.UI.ReBankWarning")); ServiceBank s = ServiceBank.NewItem(); s.AppliesToRootObjectID = tid.ID; s.AppliesToRootObjectType = tid.RootObjectType; s.Currency = -(TravelRate * this.mTravelRateQuantity); s.Incidents = -1; s.Hours = -(this.mTravelRateQuantity); s.Description = LocalizedTextTable.GetLocalizedTextDirect("O.WorkorderItemTravel") + " (" + Description + ")"; s.EffectiveDate = this.mTravelStopDate.DBValue; s.SourceRootObjectID = this.ID; s.SourceRootObjectType = RootObjectTypes.WorkorderItemTravel; s.Save(); mServiceBankID = s.ID; MarkDirty(); } /// /// UI convenience property (read only) /// public bool IsBanked { get { return mServiceBankID != Guid.Empty; } } //case 1975 /// /// Determines automaticaly the most correct service rate and /// the most correct object's bank to apply this /// travel entry to and does so. /// /// NOTE: silently returns regardless if banking was done or /// if nothing to bank or no bankable object is found or there is already a service bank ID set /// (there is no exception thrown in these logical non-bankable conditions) /// /// Callers who need to confirm can check ServiceBankID after this method call which /// will be set if bank entry was made otherwise it will remain Guid.Empty /// /// Parent workorder (required for autodiscovery of bank and rate) public void ApplyToServiceBankAuto(Workorder w) { TypeAndID bankableObject = w.BankableResolved(mWorkorderItemID); if (bankableObject == null || bankableObject.RootObjectType == RootObjectTypes.Nothing) return; if (mTravelRateID == Guid.Empty) return; if (mTravelRateQuantity == 0) return; if (mServiceBankID != Guid.Empty) return; RatePickList.RatePickListInfo theRate = RatePickList.GetListOfOneSpecificRate(mTravelRateID)[0]; decimal dCharge = theRate.Charge; //case 1190 //Check if already banked Guid gPriorBank = ServiceBankCheckAlreadyBanked.GetBankID(mID, RootObjectTypes.WorkorderItemTravel); if (gPriorBank != Guid.Empty) { //case 1189 flag the labor record ApplyServiceBankID(gPriorBank); } else ApplyToServiceBank(bankableObject, dCharge, LocalizedTextTable.GetLocalizedTextDirect("O.Workorder") + " " + w.WorkorderService.ServiceNumber.ToString()); } //case 1189 /// /// Used to resolve an issue that can arise when a user applys to service bank but then doesn't save workorder /// Won't actually bank because it's already banked but will tag this record with the correct /// service bank ID from the prior banking /// /// ID is retrieve by using the methods in ServiceBankCheckAlreadyBanked class /// /// public void ApplyServiceBankID(Guid serviceBankID) { if (mServiceBankID != serviceBankID) { mServiceBankID = serviceBankID; MarkDirty(); } } /// /// ID of record created from this travel record /// Is set when apply service bank is called /// public Guid ServiceBankID { get { return mServiceBankID; } } /// /// 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.WorkorderItemTravel") ) ); } #endregion #region System.object overrides /// /// /// /// public override string ToString() { return "WorkorderItemTravel" + mID.ToString(); } /// /// /// /// /// public override bool Equals(Object obj) { if ( obj == null || GetType ( ) != obj.GetType ( ) ) return false; WorkorderItemTravel c=(WorkorderItemTravel)obj; return mID==c.mID; } /// /// /// /// public override int GetHashCode() { return ("WorkorderItemTravel"+mID).GetHashCode(); } #endregion #region Searching /// /// Returns a search result object based on search terms /// for the ID specified /// /// /// /// public static SearchResult GetSearchResult(Guid ID, string[]searchTerms) { //case 1387 if (Workorder.RightsToWorkorder(WorkorderIDFetcher.GetWorkorderByRelative(RootObjectTypes.WorkorderItemTravel, ID)) < SecurityLevelTypes.ReadOnly) return new SearchResult(); SearchResult sr=new SearchResult(); System.Text.StringBuilder sb = new System.Text.StringBuilder(); SafeDataReader dr = null; try { //Case 88 removed //"SELECT aID, aCreator, aModifier, aCreated, aModified, aNotes, " + //" aTravelDetails FROM aWorkorderItemTravel WHERE " + //"(aID = @ID)" dr=DBUtil.GetReaderFromSQLString( "SELECT AWORKORDERITEMTRAVEL.aID, AWORKORDERITEMTRAVEL.aCreator, " + " AWORKORDERITEMTRAVEL.aModifier, AWORKORDERITEMTRAVEL.aCreated, " + " AWORKORDERITEMTRAVEL.aModified, AWORKORDERITEMTRAVEL.aNotes, AWORKORDERITEMTRAVEL.aTravelDetails, " + "AWORKORDERSERVICE.ASERVICENUMBER, " + " AWORKORDERQUOTE.AQUOTENUMBER, AWORKORDERPREVENTIVEMAINTENANCE.APREVENTIVEMAINTENANCENUMBER, " + " ACLIENT.ANAME AS ACLIENTNAME, aClient.aRegionID AS ACLIENTREGION, AWORKORDER.aWorkorderType " + "FROM AWORKORDERITEMTRAVEL INNER JOIN AWORKORDERITEM " + "ON AWORKORDERITEMTRAVEL.AWORKORDERITEMID = AWORKORDERITEM.AID " + "LEFT OUTER " + "JOIN AWORKORDER ON AWORKORDERITEM.AWORKORDERID = " + "AWORKORDER.AID LEFT OUTER JOIN ACLIENT ON AWORKORDER.ACLIENTID " + "= ACLIENT.AID LEFT OUTER JOIN AWORKORDERPREVENTIVEMAINTENANCE " + "ON AWORKORDER.AID = " + "AWORKORDERPREVENTIVEMAINTENANCE.AWORKORDERID LEFT OUTER JOIN " + "AWORKORDERQUOTE ON AWORKORDER.AID = AWORKORDERQUOTE.AWORKORDERID " + "LEFT OUTER JOIN AWORKORDERSERVICE " + "ON AWORKORDER.AID = AWORKORDERSERVICE.AWORKORDERID " + "WHERE (AWORKORDERITEMTRAVEL.aID = @ID)" ,ID); if(!dr.Read()) return new SearchResult();//DBUtil.ThrowFetchError("SearchResult for WorkorderItemTravelID: " + ID.ToString()); if (!AyaBizUtils.InYourRegion(dr.GetGuid("ACLIENTREGION"))) return new SearchResult();//case 58 //Case 88 parse out workorder type and prepare description field accordingly WorkorderTypes workorderType = (WorkorderTypes)dr.GetInt16("aWorkorderType"); switch (workorderType) { case WorkorderTypes.Service: sr.Description = LocalizedTextTable.GetLocalizedTextDirect("O.WorkorderService") + " " + dr.GetInt32("aServiceNumber").ToString() + " " + dr.GetString("ACLIENTNAME"); break; case WorkorderTypes.Quote: sr.Description = LocalizedTextTable.GetLocalizedTextDirect("O.WorkorderQuote") + " " + dr.GetInt32("AQUOTENUMBER").ToString() + " " + dr.GetString("ACLIENTNAME"); break; case WorkorderTypes.PreventiveMaintenance: sr.Description = LocalizedTextTable.GetLocalizedTextDirect("O.WorkorderPreventiveMaintenance") + " " + dr.GetInt32("APREVENTIVEMAINTENANCENUMBER").ToString() + " " + dr.GetString("ACLIENTNAME"); break; } //sr.Description=""; sb.Append(dr.GetString("aTravelDetails")); sb.Append(" "); sb.Append(dr.GetString("aNotes")); sr.Created=DBUtil.ToLocal(dr.GetSmartDate("aCreated")); sr.Modified=DBUtil.ToLocal(dr.GetSmartDate("aModified")); sr.Creator=dr.GetGuid("aCreator"); sr.Modifier=dr.GetGuid("aModifier"); } finally { if(dr!=null) dr.Close(); } //Formulate results ExtractAndRank er = new ExtractAndRank(); er.Process(sb.ToString().Trim(),searchTerms); sr.Extract=er.Extract; sr.Rank=er.Ranking; sr.AncestorRootObjectID=ID; sr.AncestorRootObjectType=RootObjectTypes.WorkorderItemTravel; return sr; } #endregion #region Static methods /// /// New item /// /// /// internal static WorkorderItemTravel NewItem(WorkorderItem obj) { //case 1387 if (AyaBizUtils.IsGenerator || ((obj.mHeaderRights > SecurityLevelTypes.ReadOnly) && (AyaBizUtils.Right("Object.WorkorderItemTravel") > (int)SecurityLevelTypes.ReadOnly))) { WorkorderItemTravel child = new WorkorderItemTravel(); child.mWorkorderItemID=obj.ID; return child; } else throw new System.Security.SecurityException( string.Format( LocalizedTextTable.GetLocalizedTextDirect("Error.Security.NotAuthorizedToCreate"), LocalizedTextTable.GetLocalizedTextDirect("O.WorkorderItemTravel"))); } /// /// Get Item /// /// /// /// internal static WorkorderItemTravel GetItem(SafeDataReader dr, WorkorderItem obj) { //case 1387 if ((obj.mHeaderRights > SecurityLevelTypes.NoAccess) && (AyaBizUtils.Right("Object.WorkorderItemTravel") > (int)SecurityLevelTypes.NoAccess)) { WorkorderItemTravel child = new WorkorderItemTravel(); child.Fetch(dr); return child; } else throw new System.Security.SecurityException( string.Format( LocalizedTextTable.GetLocalizedTextDirect("Error.Security.NotAuthorizedToRetrieve"), LocalizedTextTable.GetLocalizedTextDirect("O.WorkorderItemTravel"))); } #endregion #region DAL DATA ACCESS #region Fetch /// /// /// /// protected void Fetch(SafeDataReader dr) { //Standard fields mCreated=DBUtil.ToLocal(dr.GetSmartDate("aCreated")); mModified=DBUtil.ToLocal(dr.GetSmartDate("aModified")); mCreator=dr.GetGuid("aCreator"); mModifier=dr.GetGuid("aModifier"); mID=dr.GetGuid("aID"); //WorkorderItemTravel fields mNotes=dr.GetString("aNotes"); mNoChargeQuantity=dr.GetDecimal("aNoChargeQuantity"); mTravelDetails=dr.GetString("aTravelDetails"); mTravelRateID=dr.GetGuid("aTravelRateID"); mTravelRateQuantity=dr.GetDecimal("aTravelRateQuantity"); mTravelStartDate=DBUtil.ToLocal(dr.GetSmartDate("aTravelStartDate")); mTravelStopDate=DBUtil.ToLocal(dr.GetSmartDate("aTravelStopDate")); mUserID=dr.GetGuid("aUserID"); mWorkorderItemID=dr.GetGuid("aWorkorderItemID"); mDistance=dr.GetDecimal("aDistance"); mTaxRateSaleID=dr.GetGuid("aTaxRateSaleID"); mServiceBankID = dr.GetGuid("aServiceBankID"); //Get access rights level bReadOnly=AyaBizUtils.Right("Object.WorkorderItemTravel")<(int)SecurityLevelTypes.ReadWrite; MarkOld(); } #endregion fetch #region Add / Update /// /// Update child /// /// /// internal void Update(WorkorderItem obj,IDbTransaction tr) { //No need to update if there is nothing changed if(!this.IsDirty) return; // If not a new record, check if record was modified //by another user since original retrieval: if(!IsNew) DBUtil.CheckSafeToUpdateInsideTransaction(this.mModified.Date, this.mID, "aWorkorderItemTravel", tr);//case 1960 #region Delete if(IsDeleted) { if(!IsNew) { //Make a reversing entry in the service bank if (this.mServiceBankID != Guid.Empty) ServiceBank.ReverseItem(mServiceBankID, tr); DBCommandWrapper cmDelete = DBUtil.GetCommandFromSQL("DELETE FROM aWorkorderItemTravel WHERE aID=@ID;"); cmDelete.AddInParameter("@ID",DbType.Guid,this.mID); DBUtil.DB.ExecuteNonQuery(cmDelete, tr); DBUtil.RemoveKeywords(tr,RootObjectTypes.WorkorderItemTravel,this.mID); } MarkNew(); return; } #endregion #region Add / Update //get modification time temporarily, if update succeeds then //set to this time System.DateTime dtModified = DBUtil.CurrentWorkingDateTime; DBCommandWrapper cm = null; if(IsNew)//Add or update? cm=DBUtil.GetCommandFromSQL( "INSERT INTO aWorkorderItemTravel (aWorkorderItemID, " + "aID, aNotes, aUserID, aTravelStartDate, aTravelStopDate, " + "aTravelRateID, aTravelDetails, aTravelRateQuantity, " + "aNoChargeQuantity, aDistance, aServiceBankID, aTaxRateSaleID, aCreated,aModified,aCreator, " + "aModifier) VALUES (@WorkorderItemID,@ID,@Notes,@UserID, " + "@TravelStartDate,@TravelStopDate, @TravelRateID, " + "@TravelDetails,@TravelRateQuantity,@NoChargeQuantity, " + "@Distance,@ServiceBankID,@TaxRateSaleID,@Created,@Modified,@CurrentUserID,@CurrentUserID)" ); else cm=DBUtil.GetCommandFromSQL( "UPDATE aWorkorderItemTravel SET aWorkorderItemID=@WorkorderItemID, " + "aID=@ID, aNotes=@Notes, aUserID=@UserID, " + "aTravelStartDate=@TravelStartDate, aTravelStopDate=@TravelStopDate, " + "aTravelRateID=@TravelRateID, " + "aTravelDetails=@TravelDetails, aTravelRateQuantity=@TravelRateQuantity, " + "aNoChargeQuantity=@NoChargeQuantity, " + "aDistance=@Distance,aServiceBankID=@ServiceBankID, aTaxRateSaleID=@TaxRateSaleID, aModifier=@CurrentUserID, " + "aModified=@Modified WHERE aID=@ID" ); //WorkorderItemTravel specific cm.AddInParameter("@ID",DbType.Guid,mID); cm.AddInParameter("@WorkorderItemID",DbType.Guid,mWorkorderItemID); cm.AddLargeStringInParameter("@Notes", mNotes); cm.AddInParameter("@NoChargeQuantity",DbType.Decimal,mNoChargeQuantity); cm.AddInParameter("@TravelDetails",DbType.String,mTravelDetails); cm.AddInParameter("@TravelRateID",DbType.Guid,mTravelRateID); cm.AddInParameter("@TravelRateQuantity",DbType.Decimal,mTravelRateQuantity); cm.AddInParameter("@TravelStartDate",DbType.DateTime,DBUtil.ToUTC(mTravelStartDate).DBValue); cm.AddInParameter("@TravelStopDate",DbType.DateTime,DBUtil.ToUTC(mTravelStopDate).DBValue); cm.AddInParameter("@UserID",DbType.Guid,mUserID); cm.AddInParameter("@Distance",DbType.Decimal,mDistance); cm.AddInParameter("@ServiceBankID", DbType.Guid, mServiceBankID); cm.AddInParameter("@TaxRateSaleID",DbType.Guid,mTaxRateSaleID); //standard parameters cm.AddInParameter("@CurrentUserID",DbType.Guid, CurrentUserID); cm.AddInParameter("@Created",DbType.DateTime, DBUtil.ToUTC(mCreated.Date)); cm.AddInParameter("@Modified",DbType.DateTime, DBUtil.ToUTC(dtModified)); DBUtil.DB.ExecuteNonQuery(cm, tr); //Process keywords DBUtil.ProcessKeywords(tr,this.mID,RootObjectTypes.WorkorderItemTravel,IsNew,AyaBizUtils.Break(false,mNotes,mTravelDetails)); MarkOld();//db is now synched with object //Successful update so //change modification time to match this.mModified.Date=dtModified; #endregion } #endregion add/update #endregion }//end WorkorderItemTravel }//end namespace GZTW.AyaNova.BLL