Files
2018-06-29 19:47:36 +00:00

927 lines
25 KiB
C#

///////////////////////////////////////////////////////////
// WorkorderService.cs
// Implementation of Class WorkorderService
// CSLA type: Editable Child
// Created on: 07-Jun-2004 8:41:36 AM
// Object design: Joyce
// Coded: John 19-July-2004
///////////////////////////////////////////////////////////
using System;
using System.Data;
using CSLA.Data;
using CSLA;
using System.Threading;
using CSLA.Security;
using GZTW.Data;
using System.ComponentModel;
namespace GZTW.AyaNova.BLL
{
/// <summary>
/// Service header component of a <see cref="Workorder"/> object of <see cref="WorkorderTypes"/> Service
/// A workorder that is used to track service and parts provided to a <see cref="Client"/>
/// </summary>
[Serializable]
public class WorkorderService : BusinessBase {
#region Attributes
private bool bReadOnly;
private Guid mID;
private Guid mCreator;
private Guid mModifier;
private SmartDate mCreated;
private SmartDate mModified;
private Guid mWorkorderID;
private Guid mWorkorderStatusID;
private SmartDate mServiceDate;
private string mInvoiceNumber="";
private int mServiceNumber;
private Guid mQuoteWorkorderID;
private Guid mWorkorderPreventiveMaintenanceWorkorderID;
private Guid mClientRequestID;
private SmartDate mCloseByDate;
//marked internal so that the Workorder object
//can see if the close by date has changed for
//Processing notification events
//This is set to true when the
//close by date property is changed
internal bool mCloseByDateSignificant=false;
//ditto, but with status
internal bool mStatusSignificant=false;
//case 1346
private AySignature mSignature = null;
#endregion
#region Constructor
private WorkorderService()
{
//Set to read / write initially so that properties
//can be set
bReadOnly=false;
//Child object
MarkAsChild();
//New ID
mID = Guid.NewGuid();
//default is zero which is tied into stored procedure
//if it gets a zero then it will *not* try to set the ID
//but will use identity value instead
mServiceNumber=0;
mServiceDate = new SmartDate(DBUtil.CurrentWorkingDateTime);
//Set record history to defaults
mCreated = new SmartDate(DBUtil.CurrentWorkingDateTime);
mModified=new SmartDate();
mCreator=Guid.Empty;
mModifier=Guid.Empty;
mCloseByDate=new SmartDate();
if(AyaBizUtils.GlobalSettings.WorkorderCloseByAge>0)
{
//Notification for closebydate's might be on, so
//set the property triggering a flag that there
//is a change of close by date using the current date and time
//and adding the number of minutes in the global setting default
mCloseByDate.Date = DBUtil.CurrentWorkingDateTime.AddMinutes(AyaBizUtils.GlobalSettings.WorkorderCloseByAge);
mCloseByDateSignificant=true;
}
//case 1346
mSignature = new AySignature();
}
#endregion
#region BusinessProperties
//---Common properties
/// <summary>
/// Initial created date of this object
/// </summary>
public string Created
{
get
{
return mCreated.ToString();
}
}
/// <summary>
/// User ID of who initially created this object
/// </summary>
public Guid Creator
{
get
{
return mCreator;
}
}
/// <summary>
/// Last modified date of this object
/// </summary>
public string Modified
{
get
{
return mModified.ToString();
}
}
/// <summary>
/// User ID of who last modified this object
/// </summary>
public Guid Modifier
{
get
{
return mModifier;
}
}
/// <summary>
/// Unique ID of this object
/// </summary>
public Guid ID
{
get
{
return mID;
}
}
//---WorkorderService specific properties
/// <summary>
/// ID of Workorder (type = WorkorderPreventiveMaintenance) that this WorkorderService object was
/// created from
/// If not made from a PreventiveMaintenanc can be null
/// </summary>
public Guid WorkorderPreventiveMaintenanceWorkorderID
{
get
{
return mWorkorderPreventiveMaintenanceWorkorderID;
}
set
{
if(bReadOnly)
ThrowSetError();
else
{
if(mWorkorderPreventiveMaintenanceWorkorderID!=value)
{
mWorkorderPreventiveMaintenanceWorkorderID = value;
MarkDirty();
}
}
}
}
/// <summary>
/// ID of Workorder (type WorkorderQuote) that this WorkorderService object was created from
/// If not made from a quote, than can be null
/// </summary>
public Guid QuoteWorkorderID
{
get
{
return mQuoteWorkorderID;
}
}
/// <summary>
/// ID of ClientRequest that this WorkorderService object was created from
/// If not made from a ClientRequest can be null
/// Not editable by the user
/// </summary>
public Guid ClientRequestID
{
get
{
return mClientRequestID;
}
}
/// <summary>
/// Incremental number from sql server
/// ** USE AS A READ ONLY FIELD ONLY **
/// It is writeable only for the purpose of initial import
/// into a fresh, empty database
/// but should never normally be set after that.
/// </summary>
public int ServiceNumber
{
get
{
return mServiceNumber;
}
set
{
if(bReadOnly)
ThrowSetError();
else
{
if(mServiceNumber!=value)
{
mServiceNumber = value;
MarkDirty();
}
}
}
}
/// <summary>
/// Takes first the created date but than can be overwritten by the user i.e
/// WorkorderService info was obtained yesterday, but not actually created til today. this
/// way user can edit the ServiceDate and use for response time etc
/// </summary>
public object ServiceDate
{
get
{
return mServiceDate.DBValue;
}
set
{
if(bReadOnly)
ThrowSetError();
else
{
if (!AyaBizUtils.SmartDateEquals(mServiceDate, value)) //Case 298
{
mServiceDate.DBValue = value;
BrokenRules.Assert(
"ServiceDateInvalid",
"Error.Object.RequiredFieldEmpty,WorkorderService.Label.ServiceDate",
"ServiceDate",
mServiceDate.IsEmpty);
MarkDirty();
}
}
}
}
/// <summary>
/// direct access to smartdate value
/// used by workorder dal code to
/// flag client last service date
/// </summary>
internal SmartDate sdServiceDate
{
get
{
return mServiceDate;
}
}
/// <summary>
/// Status of entire service workorder
/// </summary>
public Guid WorkorderStatusID
{
//Uses same selection list of Status object - but this way allows for possibility
// of different ways of reporting (either via status on workorder or status on
// individual service items)
// Need to set so that if user changed workorderstatus, it checks if serviceitems
// are same status as selected - if not, gives message asking if user wishes to
// change all serviceitems to match Servicestatus
get
{
return mWorkorderStatusID;
}
set
{
if(bReadOnly)
ThrowSetError();
else
{
if(mWorkorderStatusID!=value)
{
//flag status change for event notification
mStatusSignificant=true;
mWorkorderStatusID = value;
MarkDirty();
}
}
}
}
/// <summary>
/// One invoice number for entire workorder and all of its service items - if
/// indivdual service items invoiced out separately, they should move the items to
/// their own workorder.
/// </summary>
public string InvoiceNumber
{
get
{
return mInvoiceNumber;
}
set
{
if(bReadOnly)
ThrowSetError();
else
{
if(mInvoiceNumber!=value)
{
mInvoiceNumber = value;
MarkDirty();
}
}
}
}
/// <summary>
/// ID of root object this address belongs to (workorder)
/// </summary>
public Guid WorkorderID
{
get
{
return mWorkorderID;
}
set
{
if(bReadOnly)
ThrowSetError();
else
{
if(mWorkorderID!=value)
{
mWorkorderID = value;
MarkDirty();
}
}
}
}
/// <summary>
/// This is a user definable date and time used to indicate when a service workorder
/// should be closed by. It's used to identify workorders that have been left to
/// languish and not serviced promptly.
///
/// A user needs the special Object.WorkorderService.CloseByDate right to be able
/// to modify this even if they have full rights to the workorder object itself
/// </summary>
public object CloseByDate
{
get
{
return mCloseByDate.DBValue;
}
set
{
if(bReadOnly)
ThrowSetError();
else
{
//User must have special rights to change this
if(AyaBizUtils.Right("Object.WorkorderService.CloseByDate")<(int)SecurityLevelTypes.ReadWrite)
{
throw new System.Security.SecurityException
(
string.Format
(
LocalizedTextTable.GetLocalizedTextDirect("Error.Security.NotAuthorizedToChange"),
LocalizedTextTable.GetLocalizedTextDirect("O.WorkorderService.CloseByDate")
)
);
}
if (!AyaBizUtils.SmartDateEquals(mCloseByDate, value)) //Case 298
{
mCloseByDateSignificant=true;
mCloseByDate.DBValue = value;
MarkDirty();
}
}
}
}
/// <summary>
/// Smart date version used by workorder notification Processor
/// </summary>
internal SmartDate sdCloseByDate
{
get
{
return mCloseByDate;
}
}
/// <summary>
/// AySignature object
///
/// </summary>
public AySignature Signature
{
get
{
if (mSignature == null) mSignature = new AySignature("");
return mSignature;
}
}
/// <summary>
/// Used internally to set the signature code from the client
/// Not to be set via code directly
/// </summary>
[Browsable(false)]
public string SetSignature
{
set
{
if (bReadOnly)
ThrowSetError();
else
{
if (Signature.SignatureCode != value)
{
mSignature = new AySignature(value);
mSignature.HostCapturedDateTime = new SmartDate(DateTime.Now);
MarkDirty();
}
}
}
}
/// <summary>
/// Used internally to clear the signature code from the client
/// Not to be set via code directly
/// </summary>
[Browsable(false)]
public bool ClearSignature
{
set
{
if (bReadOnly)
ThrowSetError();
else
{
if (value && Signature.HasSignature)
{
Signature.Clear();
MarkDirty();
}
}
}
}
/// <summary>
/// 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)
/// </summary>
private void ThrowSetError()
{
throw new System.Security.SecurityException
(
string.Format
(
LocalizedTextTable.GetLocalizedTextDirect("Error.Security.NotAuthorizedToChange"),
LocalizedTextTable.GetLocalizedTextDirect("O.WorkorderService")
)
);
}
#endregion
#region Searching
/// <summary>
/// Returns a search result object based on search terms
/// for the ID specified
/// </summary>
/// <param name="ID"></param>
/// <param name="searchTerms"></param>
/// <returns></returns>
public static SearchResult GetSearchResult(Guid ID, string[]searchTerms)
{
//case 1387
if (Workorder.RightsToWorkorder(WorkorderIDFetcher.GetWorkorderByRelative(RootObjectTypes.WorkorderService, 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, aInvoiceNumber, ASERVICENUMBER, " +
// "FROM aWorkorderService WHERE (aID " +
// "= @ID)"
dr=DBUtil.GetReaderFromSQLString(
//Case 88
"SELECT AWORKORDERSERVICE.AINVOICENUMBER, AWORKORDERSERVICE.ASERVICENUMBER, aClient.aRegionID AS ACLIENTREGION, ACLIENT.ANAME AS ACLIENTNAME, " +
"AWORKORDERSERVICE.aCreator, " +
" AWORKORDERSERVICE.aModifier, AWORKORDERSERVICE.aCreated, " +
" AWORKORDERSERVICE.aModified " +
"FROM ACLIENT INNER JOIN AWORKORDER " +
"ON ACLIENT.AID = AWORKORDER.ACLIENTID RIGHT " +
"OUTER JOIN AWORKORDERSERVICE ON AWORKORDER.AID = " +
"AWORKORDERSERVICE.AWORKORDERID " +
"WHERE (AWORKORDERSERVICE.AID = @ID)"
,ID);
if(!dr.Read())
return new SearchResult();//DBUtil.ThrowFetchError("SearchResult for WorkorderItemLaborID: " + ID.ToString());
if (!AyaBizUtils.InYourRegion(dr.GetGuid("ACLIENTREGION"))) return new SearchResult();//case 58
//Case 88
sr.Description = LocalizedTextTable.GetLocalizedTextDirect("O.WorkorderService") + " " + dr.GetInt32("aServiceNumber").ToString() + " " + dr.GetString("ACLIENTNAME");
//sr.Description="";
sb.Append(dr.GetString("aInvoiceNumber"));
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.WorkorderService;
return sr;
}
#endregion
#region System.object overrides
/// <summary>
///
/// </summary>
/// <returns></returns>
public override string ToString()
{
return "WorkorderService" + mID.ToString();
}
/// <summary>
///
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public override bool Equals(Object obj)
{
if ( obj == null || GetType ( ) != obj.GetType ( ) ) return false;
WorkorderService c=(WorkorderService)obj;
return mID==c.mID;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
return ("WorkorderService" + mID).GetHashCode();
}
#endregion
#region Static methods
/// <summary>
/// Create item
/// </summary>
/// <param name="obj">Parent ID</param>
/// <returns>New Item</returns>
internal static WorkorderService NewItem(Workorder obj)
{
//case 1387 no need to check rights here because parent workorder object now checks correct rights by type
//if(AyaBizUtils.IsGenerator || AyaBizUtils.Right("Object.WorkorderService")>(int)SecurityLevelTypes.ReadOnly)
//{
WorkorderService child=new WorkorderService();
child.mWorkorderID=obj.ID;
return child;
//}
//else
// throw new System.Security.SecurityException(
// string.Format(
// LocalizedTextTable.GetLocalizedTextDirect("Error.Security.NotAuthorizedToCreate"),
// LocalizedTextTable.GetLocalizedTextDirect("O.WorkorderService")));
}
/// <summary>
/// Retrieve item
/// </summary>
/// <param name="dr">Data reader</param>
/// <returns>item from database</returns>
internal static WorkorderService GetItem(SafeDataReader dr)
{
//case 1387 no need to check rights here because parent workorder object now checks correct rights by type
//if(AyaBizUtils.Right("Object.WorkorderService")>(int)SecurityLevelTypes.NoAccess)
//{
WorkorderService child = new WorkorderService();
child.Fetch(dr);
return child;
//}
//else
// throw new System.Security.SecurityException(
// string.Format(
// LocalizedTextTable.GetLocalizedTextDirect("Error.Security.NotAuthorizedToRetrieve"),
// LocalizedTextTable.GetLocalizedTextDirect("O.WorkorderService")));
}
/// <summary>
/// Sets new starting seed number for service workorders
///
/// </summary>
/// <param name="newID"></param>
public static void SetVisibleIDNumber(int newID)
{
VisibleIDNumber.SetVisibleIDNumber(newID);
}
#endregion
#region DAL DATA ACCESS
#region Fetch
/// <summary>
/// Fetch from db
/// </summary>
/// <param name="dr"></param>
private void Fetch(SafeDataReader dr)
{
//Standard items
mCreated=DBUtil.ToLocal(dr.GetSmartDate("aCreated"));
mCreator=dr.GetGuid("aCreator");
mModified=DBUtil.ToLocal(dr.GetSmartDate("aModified"));
mModifier=dr.GetGuid("aModifier");
mID=dr.GetGuid("aID");
//WorkorderService specific parameters
mClientRequestID=dr.GetGuid("aClientRequestID");
mInvoiceNumber=dr.GetString("aInvoiceNumber");
mWorkorderPreventiveMaintenanceWorkorderID=dr.GetGuid("aPreventiveMaintenanceID");
mQuoteWorkorderID=dr.GetGuid("aQuoteWorkorderID");
mServiceDate=DBUtil.ToLocal(dr.GetSmartDate("aServiceDate"));
mServiceNumber=dr.GetInt32("aServiceNumber");
mWorkorderStatusID=dr.GetGuid("aWorkorderStatusID");
mWorkorderID=dr.GetGuid("aWorkorderID");
mCloseByDate=DBUtil.ToLocal(dr.GetSmartDate("aCloseByDate"));
//case 1346
mSignature.SignatureCode = dr.GetString("ASIGNATURE");
mSignature.HostCapturedDateTime = DBUtil.ToLocal(dr.GetSmartDate("ASIGNED"));
//Get access rights level
bReadOnly=AyaBizUtils.Right("Object.WorkorderService")<(int)SecurityLevelTypes.ReadWrite;
MarkOld();
}
#endregion
#region Add / Update
/// <summary>
/// Persist object to database
/// </summary>
/// <param name="obj">Parent object</param>
/// <param name="tr">Parents transaction object</param>
internal void Update(Workorder 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, "aWorkorderService", tr);//case 1960
#region Delete
if(IsDeleted)
{
if(!IsNew)
{
DBCommandWrapper cmDelete = DBUtil.GetCommandFromSQL("DELETE FROM aWorkorderService WHERE aID=@ID;");
cmDelete.AddInParameter("@ID",DbType.Guid,this.mID);
DBUtil.DB.ExecuteNonQuery(cmDelete, tr);
}
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?
{
//CHECK IF IMPORTING...
//If a new record has a service number already then it's importing
//WARNING: THIS CODE WORKS ONLY IF THE IMPORTING DATA IS ALWAYS INCREMENTING THE
//WO NUMBER.
if(this.mServiceNumber!=0)//importing?
SetVisibleIDNumber(this.mServiceNumber);
cm=DBUtil.GetCommandFromSQL(
"INSERT INTO aWorkorderService (aWorkorderID, aID, aWorkorderStatusID, " +
"aServiceDate, " +
"aInvoiceNumber, aQuoteWorkorderID, aClientRequestID, " +
"aPreventiveMaintenanceID, aCloseByDate, ASIGNATURE, ASIGNED, aCreated,aModified,aCreator, " +
"aModifier) VALUES (@WorkorderID,@ID,@WorkorderStatusID, " +
"@ServiceDate, @InvoiceNumber, " +
"@QuoteWorkorderID,@ClientRequestID, @PreventiveMaintenanceID, @CloseByDate, @SIGNATURE, @SIGNED, " +
"@Created, @Modified, @CurrentUserID, @CurrentUserID)"
);
}
else
cm=DBUtil.GetCommandFromSQL(
"UPDATE aWorkorderService SET aWorkorderID=@WorkorderID, " +
"aID=@ID, aWorkorderStatusID=@WorkorderStatusID, " +
"aServiceDate=@ServiceDate, " +
"aInvoiceNumber=@InvoiceNumber, " +
"aQuoteWorkorderID=@QuoteWorkorderID, aClientRequestID=@ClientRequestID, " +
"aPreventiveMaintenanceID=@PreventiveMaintenanceID, " +
"aCloseByDate=@CloseByDate, ASIGNATURE=@SIGNATURE, ASIGNED=@SIGNED, " +
"aModifier=@CurrentUserID, aModified=@Modified " +
"WHERE aID=@ID"
);
//WorkorderService specific parameters
cm.AddInParameter("@ID",DbType.Guid,mID);
cm.AddInParameter("@ClientRequestID",DbType.Guid,mClientRequestID);
cm.AddInParameter("@InvoiceNumber",DbType.String,mInvoiceNumber);
cm.AddInParameter("@PreventiveMaintenanceID",DbType.Guid,mWorkorderPreventiveMaintenanceWorkorderID);
cm.AddInParameter("@QuoteWorkorderID",DbType.Guid,mQuoteWorkorderID);
cm.AddInParameter("@ServiceDate",DbType.DateTime,DBUtil.ToUTC(mServiceDate).DBValue);
cm.AddInParameter("@WorkorderStatusID",DbType.Guid,mWorkorderStatusID);
cm.AddInParameter("@WorkorderID",DbType.Guid,mWorkorderID);
cm.AddInParameter("@CloseByDate",DbType.DateTime,DBUtil.ToUTC(mCloseByDate).DBValue);
//case 1346
cm.AddLargeStringInParameter("@SIGNATURE", mSignature.SignatureCode);
cm.AddInParameter("@SIGNED", DbType.DateTime, DBUtil.ToUTC(mSignature.HostCapturedDateTime).DBValue);
//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);
//Get new DB generated identity value
if(IsNew)
this.mServiceNumber=DBUtil.GetIdentity("aServiceNumber","aWorkorderService",this.mID,tr);
//Process keywords
DBUtil.ProcessKeywords(tr,this.mID,RootObjectTypes.WorkorderService,IsNew,AyaBizUtils.Break(false,
mInvoiceNumber));
MarkOld();//db is now synched with object
//Successful update so
//change modification time to match
this.mModified.Date=dtModified;
#endregion
}
#endregion
#endregion
#region Set VisibleIDNumber
#pragma warning disable 1591
/// <summary>
/// Set the DB generated visible ID number
/// to a new user chosen starting point
/// </summary>
[Serializable(), System.ComponentModel.Browsable(false)]
public class VisibleIDNumber//DO_NOT_OBFUSCATE
{
int _newStartID = -1;
public VisibleIDNumber(int newStartID)
{
_newStartID = newStartID;
}
public static void SetVisibleIDNumber(int newStartID)
{
DataPortal.Update(new VisibleIDNumber(newStartID));
}
public void DataPortal_Update()
{
//Find the highest existing number
Object o=DBUtil.GetScalarFromSQLString(
"SELECT MAX(aServiceNumber) FROM aWorkorderService"
);
if(o==null || o==System.DBNull.Value) o=0;
int nHighestExisting=(int)o;
//ensure new number is larger than highest existing one
if(_newStartID<nHighestExisting)
throw new ApplicationException(
string.Format(
LocalizedTextTable.GetLocalizedTextDirect("Error.AutoIncrement.NumberTooLow"),
(nHighestExisting+1).ToString()));
switch(DBUtil.DB.DBType)
{
case DataBaseType.FireBird:
{
if(_newStartID!=0) _newStartID--;
string sql="SET Generator GEN_ASERVICENUMBER TO " + _newStartID.ToString();
DBUtil.DB.ExecuteNonQuery(CommandType.Text,sql);
}
break;
case DataBaseType.MSSQL:
{if(_newStartID!=0) _newStartID--;
string sql="DBCC CHECKIDENT (aWorkorderService, RESEED, " + _newStartID.ToString()+")";
DBUtil.DB.ExecuteNonQuery(CommandType.Text,sql);
}
break;
default:
throw new ApplicationException("UNKNOWN DB TYPE IN START SEED UPDATE");
}
}
}
#pragma warning restore 1591
#endregion set visibleIDnumber
}//end WorkorderService
}//end namespace GZTW.AyaNova.BLL