Files
ayanova7/source/bizobjects/AyaLib/GZTW.AyaNova.BLL/ClientNotifyEvent.cs
2022-05-31 20:12:00 +00:00

888 lines
27 KiB
C#

///////////////////////////////////////////////////////////
// ClientNotifyEvent.cs
// Implementation of Class ClientNotifyEvent
// CSLA type: Editable Root
// Created on: 10-December-2008
// Object design: John
// Coded: 10-December-2008
///////////////////////////////////////////////////////////
using System;
using System.Data;
using CSLA.Data;
using GZTW.Data;
using CSLA;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
//case 53
namespace GZTW.AyaNova.BLL
{
/// <summary>
/// ClientNotifyEvent object
/// Insert and manage client notification events
///
/// </summary>
[Serializable]
public class ClientNotifyEvent : BusinessBase
{
#pragma warning disable 1591
#region Attributes
private Guid mID;
private SmartDate mCreated;
private SmartDate mModified;
private Guid mCreator;
private Guid mModifier;
private Guid mClientID = Guid.Empty;
private SmartDate mDeliverAfter;
private byte[] mContent=null;
private int mObjectSize;
#endregion
#region Constructor
/// <summary>
/// Private constructor to prevent direct instantiation
/// </summary>
private ClientNotifyEvent()
{
//New ID
mID = Guid.NewGuid();
//Set record history to defaults
mCreated = new SmartDate(DBUtil.CurrentWorkingDateTime);
mModified = new SmartDate();
mCreator = Guid.Empty;
mModifier = Guid.Empty;
//case 1163
mDeliverAfter = new SmartDate(DBUtil.CurrentWorkingDateTime - TimeSpan.FromSeconds(30));//deliver after 30 seconds ago just in case
ClientID = Guid.Empty;
mObjectSize = 0;
}
#endregion
#region Business properties
/// <summary>
/// Internal Unique GUID value of ClientNotifyEvent record in database
/// </summary>
public Guid ID
{
get
{
return mID;
}
}
/// <summary>
/// Get created date
///
///
/// </summary>
public string Created
{
get
{
return mCreated.ToString();
}
}
/// <summary>
/// Get modified date
///
///
/// </summary>
public string Modified
{
get
{
return mModified.ToString();
}
}
/// <summary>
/// Get user record ID of person who created this record
///
///
/// </summary>
public Guid Creator
{
get
{
return mCreator;
}
}
/// <summary>
/// Get user ID of person who modified this record
///
///
/// </summary>
public Guid Modifier
{
get
{
return mModifier;
}
}
/// <summary>
/// AyaNova object ID
/// </summary>
public Guid ClientID
{
get
{
return mClientID;
}
set
{
if (mClientID != value)
{
mClientID = value;
BrokenRules.Assert("ClientID", "Error.Object.RequiredFieldEmpty,ClientNotifyEvent.Label.ClientID", "ClientID", value == Guid.Empty);
MarkDirty();
}
}
}
/// <summary>
/// Deliver after date, used only
/// for follow up client notifications
/// </summary>
public DateTime DeliverAfter
{
get
{
return mDeliverAfter.Date;
}
set
{
mDeliverAfter.Date = value;
}
}
/// <summary>
/// Get the MIME content
///
/// </summary>
public string GetContentAsString
{
get
{
return Encoding.Unicode.GetString(mContent);
}
}
public System.IO.MemoryStream GetContent()
{
//if (mContent.Length == mObjectSize)//it's not compressed so just return it
return new System.IO.MemoryStream(mContent);
// else//it *is* compressed so decompress and return
// return new System.IO.MemoryStream(AyaBizUtils.Decompress(mContent));
}
/// <summary>
/// Set the content based on string
/// </summary>
/// <param name="sContent"></param>
public void SetContent(string sContent)
{
using (MemoryStream ms = new MemoryStream(System.Text.Encoding.Unicode.GetBytes(sContent)))
{
SetContent(ms);
}
}
public void SetContent(System.IO.Stream mStream)
{
mObjectSize = (int)mStream.Length;
mStream.Position = 0;
byte[] bData = new byte[mStream.Length];
mStream.Read(bData, 0, (int)mStream.Length);
mContent = bData;//just store, compression not needed here
//mContent = AyaBizUtils.Compress(bData);
////did it compress smaller?
////don't want to store uncompressible files that are actually larger after compression
//if (mContent.Length >= mObjectSize)
//{
// //yup, it's bigger compressed, so store the uncompressed version instead
// mContent = bData;
//}
MarkDirty();
}
/// <summary>
/// Byte array set content
/// </summary>
/// <param name="bData"></param>
public void SetContent(byte[] bData)
{
mObjectSize = (int)bData.LongLength;
//mStream.Position = 0;
//byte[] bData = new byte[mStream.Length];
//mStream.Read(bData, 0, (int)mStream.Length);
// mContent = AyaBizUtils.Compress(bData);
//did it compress smaller?
//don't want to store uncompressible files that are actually larger after compression
//if (mContent.Length >= mObjectSize)
//{
//yup, it's bigger compressed, so store the uncompressed version instead
mContent = bData;
//}
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.ClientNotifyEvent")
)
);
}
#endregion
#region System.object overrides
public override string ToString()
{
return "ClientNotifyEvent" + mID.ToString();
}
///
/// <param name="obj"></param>
public override bool Equals(Object obj)
{
if (obj == null || GetType() != obj.GetType()) return false;
ClientNotifyEvent c = (ClientNotifyEvent)obj;
return mID == c.mID;
}
public override int GetHashCode()
{
return ("ClientNotifyEvent" + mID).GetHashCode();
}
#endregion
#region Static methods
/// <summary>
/// Overload
/// </summary>
/// <param name="type"></param>
/// <param name="ClientID"></param>
/// <param name="WorkorderStatusID"></param>
/// <param name="wonumber"></param>
/// <param name="contact"></param>
/// <param name="cref"></param>
/// <param name="csrdetails"></param>
/// <param name="WorkorderID"></param>
/// <param name="wosummary"></param>
/// <param name="csrtitle"></param>
internal static void ProcessEvent(ClientNotifyEventType type, Guid ClientID, Guid WorkorderStatusID,
string wonumber, string contact, string cref, string csrdetails, Guid WorkorderID, string wosummary, string csrtitle)
{
ProcessEvent(type, ClientID, WorkorderStatusID, wonumber, contact, cref, csrdetails, WorkorderID, wosummary, csrtitle, WorkorderQuoteStatusTypes.NotSet);
}
/// <summary>
/// Generate a new client notification if appropriate
/// </summary>
/// <param name="type"></param>
/// <param name="ClientID"></param>
/// <param name="WorkorderStatusID"></param>
/// <param name="wonumber"></param>
/// <param name="contact"></param>
/// <param name="cref"></param>
/// <param name="csrdetails"></param>
/// <param name="WorkorderID"></param>
/// <param name="wosummary"></param>
/// <param name="csrtitle"></param>
/// <param name="quoteStatus"></param>
internal static void ProcessEvent(ClientNotifyEventType type, Guid ClientID, Guid WorkorderStatusID,
string wonumber, string contact, string cref, string csrdetails, Guid WorkorderID,string wosummary, string csrtitle, WorkorderQuoteStatusTypes quoteStatus)
{
ClientList cl = ClientList.GetListForSingleItem(ClientID);
if (cl.Count < 1) return;
if (!cl[0].LT_Client_Label_Notification) return;
if (string.IsNullOrEmpty(cl[0].LT_Client_Label_Email)) return;
Region r = Region.GetItem(cl[0].LT_O_Region.Value);
if (!r.ClientNotification) return;
string sTemplate = "";
//case 1151
Guid gAttachReportID = Guid.Empty;
switch (type)
{
case ClientNotifyEventType.CSRAccepted:
{
if (!r.NotifyCSRAccepted) return;
sTemplate = r.NotifyCSRMSG;
}
break;
case ClientNotifyEventType.CSRRejected:
{
if (!r.NotifyCSRRejected) return;
sTemplate = r.NotifyCSRRejectMSG;
}
break;
case ClientNotifyEventType.NewWorkorder:
{
if (!r.NotifyNewWO) return;
sTemplate = r.NotifyNewWOMSG;
}
break;
case ClientNotifyEventType.WorkorderClosed:
{
if (!r.NotifyWOClosed) return;
sTemplate = r.NotifyWOClosedMSG;
//added for case 1151
if (r.NotifyWOClosedAttachWO)
gAttachReportID = r.NotifyWOClosedRPT;
}
break;
case ClientNotifyEventType.WorkorderFollowUp:
{
if (!r.NotifyWOFollowUp) return;
sTemplate = r.NotifyWOFollowUpMSG;
}
break;
case ClientNotifyEventType.WorkorderStatusSet:
{
//if (!r.NotifyWOStatus) return;
//if (WorkorderStatusID == Guid.Empty || WorkorderStatusID != r.NotifyWOStatusID) return;
//sTemplate = r.NotifyWOStatMSG;
//case 1151
if (WorkorderStatusID == Guid.Empty) return;
System.Text.StringBuilder stb = new StringBuilder();
foreach (RegionWoStatusNotifyItem rwsni in r.WoStatusNotifyItems)
{
if (rwsni.Active && rwsni.NotifyWOStatusID == WorkorderStatusID)
{
sTemplate=rwsni.NotifyWOStatMSG;
gAttachReportID = rwsni.WoReportID;
break;
}
}
}
break;
//case 1499
case ClientNotifyEventType.QuoteStatusSet:
{
if (!r.NotifyQuoteStatus) return;
if (r.NotifyQuoteStatusType != quoteStatus) return;
sTemplate = r.NotifyQuoteStatMSG;
if (r.NotifyQuoteStatusRPT!=Guid.Empty)
gAttachReportID = r.NotifyQuoteStatusRPT;
}
break;
}
if(string.IsNullOrEmpty(sTemplate)) return;
#region Template processing
WorkorderStatusPickList statpick = WorkorderStatusPickList.GetList();
//fill in template
//Match all keywords and substitute queried data for them
MatchCollection matches = Regex.Matches(sTemplate, @"\[(.|\n)*?\]", RegexOptions.IgnorePatternWhitespace
| RegexOptions.Compiled);
foreach (Match KeyMatch in matches)
{
switch (KeyMatch.Value)
{
case "[WorkorderService.Label.ServiceNumber]":
sTemplate=sTemplate.Replace(KeyMatch.Value, wonumber);
break;
case "[O.WorkorderStatus]":
if (statpick.Contains(WorkorderStatusID))
sTemplate = sTemplate.Replace(KeyMatch.Value, statpick[WorkorderStatusID].Name);
else
sTemplate = sTemplate.Replace(KeyMatch.Value, "");
break;
case "[Workorder.Label.CustomerContactName]":
sTemplate = sTemplate.Replace(KeyMatch.Value, contact);
break;
case "[Workorder.Label.CustomerReferenceNumber]":
sTemplate = sTemplate.Replace(KeyMatch.Value, cref);
break;
case "[Region.Label.WBIUrl]":
sTemplate = sTemplate.Replace(KeyMatch.Value, r.WBIUrl);
break;
case "[Client.Label.Name]":
sTemplate = sTemplate.Replace(KeyMatch.Value, cl[0].LT_O_Client.Display);
break;
case "[ClientServiceRequest.Label.Details]":
sTemplate = sTemplate.Replace(KeyMatch.Value, csrdetails);
break;
case "[Workorder.Label.Summary]":
sTemplate = sTemplate.Replace(KeyMatch.Value, wosummary);
break;
case "[ClientServiceRequest.Label.Title]":
sTemplate = sTemplate.Replace(KeyMatch.Value, csrtitle);
break;
//case 1499
case "[WorkorderQuote.Label.QuoteNumber]":
sTemplate = sTemplate.Replace(KeyMatch.Value, wonumber);
break;
}
}
#endregion template
if(string.IsNullOrEmpty(sTemplate)) return;
//subject line first line or first 100 characters of template
string sSubject="";
//Let's get the default 100 characters or less first
if (sTemplate.Length < 101)
sSubject = sTemplate;
else
sSubject = sTemplate.Substring(0, 100);
//fine tune if there is a return or linefeed within the bounds of reason
int n = sTemplate.IndexOfAny(new char[] { '\n', '\r' });
if (n != -1 && n<102 && n > 2)
{
sSubject = sTemplate.Substring(0, n);//case 1984 was n-1
}
//generate email
System.Text.StringBuilder sb = new StringBuilder();
sb.Append("CLIENTNOTIFYEVENT|");
//Email email = new Email();
// email.UnlockComponent("AYANVA.CB1052023_c9TZbuFYBd7f");
// email.Mailer = "AyaNova service management software licensed to " + AyaBizUtils.REGTO;
//email.Body = sTemplate;
sb.Append(sTemplate);
sb.Append("|");
//email.Subject = sSubject;
sb.Append(sSubject);
sb.Append("|");
//email.AddTo("", cl[0].LT_Client_Label_Email);
sb.Append(cl[0].LT_Client_Label_Email);
sb.Append("|");
//email.From = r.ReplyToEmail;
sb.Append(r.ReplyToEmail);
//ATTACH REPORT?
//case 1151 modified to add status change, b4 was only on closed
//indicate which wo to attach and which report to use
//(saves looking it up later)
if (gAttachReportID!=Guid.Empty)
{
//put in delimiter for previous item
sb.Append("|");
//email.AddHeaderField("WorkorderID", WorkorderID.ToString());
sb.Append(WorkorderID.ToString());
sb.Append("|");
//email.AddHeaderField("ReportID", r.NotifyWOClosedRPT.ToString());
sb.Append(gAttachReportID.ToString());
}
ClientNotifyEvent cn = ClientNotifyEvent.NewItem();
cn.ClientID = ClientID;
if (type == ClientNotifyEventType.WorkorderFollowUp)
cn.DeliverAfter += TimeSpan.FromDays(r.NotifyWOFollowUpDays);
cn.SetContent(sb.ToString());
cn.Save();
}
/// <summary>
/// Create new ClientNotifyEvent
/// </summary>
/// <returns>Empty ClientNotifyEvent object</returns>
public static ClientNotifyEvent NewItem()
{
ClientNotifyEvent c;
//if (AyaBizUtils.Right("Object.ClientNotifyEvent") > (int)SecurityLevelTypes.ReadOnly)
//{
c = new ClientNotifyEvent();
return c;
//}
//else
// throw new System.Security.SecurityException(
// string.Format(
// LocalizedTextTable.GetLocalizedTextDirect("Error.Security.NotAuthorizedToCreate"),
// LocalizedTextTable.GetLocalizedTextDirect("O.ClientNotifyEvent")));
}
/// <summary>
/// Fetch existing ClientNotifyEvent
/// </summary>
/// <returns>ClientNotifyEvent</returns>
/// <param name="ID">ClientNotifyEvent Guid</param>
public static ClientNotifyEvent GetItem(Guid ID)
{
return (ClientNotifyEvent)DataPortal.Fetch(new Criteria(ID,Guid.Empty));
}
/// <summary>
/// Delete ClientNotifyEvent
/// </summary>
/// <param name="ID">ClientNotifyEvent applicationID</param>
public static void DeleteItem(Guid ID)
{
DataPortal.Delete(new Criteria(ID, Guid.Empty));
}
/// <summary>
/// Delete all events for a specified client
/// used when saving a client record that has it's send notifications
/// unchecked and when deleting a client
/// </summary>
/// <param name="ClientID">Client ID</param>
public static void DeleteAllNotifyEventsForClient(Guid ClientID)
{
DataPortal.Delete(new Criteria(Guid.Empty, ClientID));
}
#endregion
#region DAL DATA ACCESS
#region Fetch
///
/// <param name="Criteria"></param>
protected override void DataPortal_Fetch(object Criteria)
{
Criteria crit = (Criteria)Criteria;
SafeDataReader dr = null;
try
{
dr = DBUtil.GetReaderFromSQLString("SELECT * FROM aClientNotifyEvent WHERE aID=@ID;", crit.ID);
if (!dr.Read())
DBUtil.ThrowFetchError("ClientNotifyEvent ID: " + crit.ID.ToString());
//Standard fields
mID = dr.GetGuid("aID");
mCreated = DBUtil.ToLocal(dr.GetSmartDate("aCreated"));
mModified = DBUtil.ToLocal(dr.GetSmartDate("aModified"));
mDeliverAfter = DBUtil.ToLocal(dr.GetSmartDate("ADELIVERAFTER"));
mCreator = dr.GetGuid("aCreator");
mModifier = dr.GetGuid("aModifier");
//ClientNotifyEvent fields
mObjectSize = dr.GetInt32("AOBJECTSIZE");
ClientID = dr.GetGuid("aClientID");
//allocate a place to store it
mContent = new Byte[mObjectSize];
//retrieve the (compressed) bytes
dr.GetBytes("AOBJECT", 0, mContent, 0, mContent.Length);
if(dr!=null) dr.Close();
}
finally
{
if (dr != null) dr.Close();
}
MarkOld();
}
#endregion fetch
#region Update
/// <summary>
/// Called by DataPortal to delete/add/update data into the database
/// </summary>
protected override void DataPortal_Update()
{
//--------------------------
//case 3827
//Remove any entries deliverafter older than 7 days
DBCommandWrapper cmTrim = DBUtil.GetCommandFromSQL(
"DELETE FROM aClientNotifyEvent " +
"WHERE (aDeliverAfter < @SEVENDAYSAGO)"
);
cmTrim.AddInParameter("@SEVENDAYSAGO", DbType.DateTime, DBUtil.ToUTC(DBUtil.CurrentWorkingDateTime.AddDays(-7)));
DBUtil.DB.ExecuteNonQuery(cmTrim);
//------------------------
// If not a new record, check if record was modified
//by another user since original retrieval:
if (!IsNew)
DBUtil.CheckSafeToUpdate(this.mModified.Date, this.mID, "aClientNotifyEvent");
#region Delete
if (IsDeleted)
{
throw new System.NotSupportedException("ClientNotifyEvent->Update->Delete: not supported for this object, call the static/shared ClientNotifyEvent.DeleteItem() method instead");
}
#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 aClientNotifyEvent (aID, aCreated,aModified,aCreator,aModifier, " +
"aClientID, aDeliverAfter, AOBJECT,AOBJECTSIZE) " +
"VALUES (@ID,@Created,@Modified,@CurrentUserID,@CurrentUserID, " +
"@ClientID, @DeliverAfter, @OBJECT,@OBJECTSIZE)"
);
else
cm = DBUtil.GetCommandFromSQL(
"UPDATE aClientNotifyEvent SET aID=@ID, " +
"aModified=@Modified,aModifier=@CurrentUserID, " +
"aClientID=@ClientID, " +
"aDeliverAfter=@DeliverAfter, " +
"AOBJECT=@OBJECT, AOBJECTSIZE=@OBJECTSIZE " +
"WHERE aID=@ID"
);
//ClientNotifyEvent fields
cm.AddInParameter("@ID", DbType.Guid, mID);
cm.AddInParameter("@ClientID", DbType.Guid, mClientID);
cm.AddInParameter("@DeliverAfter", DbType.DateTime, DBUtil.ToUTC(mDeliverAfter.Date));
cm.AddInParameter("@OBJECT", DbType.Object, mContent);
cm.AddInParameter("@OBJECTSIZE", DbType.Int32, mContent.GetLength(0));
//Standard fields
cm.AddInParameter("@CurrentUserID", DbType.Guid, CurrentUserID);
cm.AddInParameter("@Created", DbType.DateTime, DBUtil.ToUTC(mCreated).DBValue);
cm.AddInParameter("@Modified", DbType.DateTime, DBUtil.ToUTC(dtModified));
using (IDbConnection connection = DBUtil.DB.GetConnection())
{
connection.Open();
IDbTransaction transaction = connection.BeginTransaction();
try
{
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;
}
#endregion
}
#endregion update
#region Delete
/// <summary>
/// Remove a ClientNotifyEvent record
/// </summary>
/// <param name="Criteria"></param>
protected override void DataPortal_Delete(object Criteria)
{
Criteria crit = (Criteria)Criteria;
DBCommandWrapper cmDelete = null;
//Delete *all* events for a client
if (crit.ClientID != Guid.Empty)
{
cmDelete = DBUtil.GetCommandFromSQL("DELETE FROM aClientNotifyEvent WHERE aClientID = @ID");
cmDelete.AddInParameter("@ID", DbType.Guid, crit.ClientID);
}
else
{
//Delete object
cmDelete = DBUtil.GetCommandFromSQL("DELETE FROM aClientNotifyEvent WHERE aID = @ID;");
cmDelete.AddInParameter("@ID", DbType.Guid, crit.ID);
}
using (IDbConnection connection = DBUtil.DB.GetConnection())
{
connection.Open();
IDbTransaction transaction = connection.BeginTransaction();
try
{
DBUtil.DB.ExecuteNonQuery(cmDelete, transaction);
// Commit the transaction
transaction.Commit();
}
catch
{
// Rollback transaction
transaction.Rollback();
throw;
}
finally
{
connection.Close();
}
}
}
#endregion delete
#endregion
#region Override IsValid / IsDirty
public override bool IsValid
{
get
{
return base.IsValid ;
}
}
public override bool IsDirty
{
get
{
return base.IsDirty ;
}
}
#endregion
#region criteria
/// <summary>
/// Criteria for identifying existing object
/// </summary>
[Serializable]
private class Criteria
{
public Guid ID;
public Guid ClientID;
public Criteria(Guid _ID, Guid _ClientID)
{
ID = _ID;
ClientID = _ClientID;
}
}
#endregion
}//end ClientNotifyEvent
#region Notification events
public enum ClientNotifyEventType : int
{
CSRAccepted=1,
CSRRejected=2,
NewWorkorder=3,
WorkorderStatusSet=4,
WorkorderClosed=5,
WorkorderFollowUp=6,
QuoteStatusSet=7//case 1499
}
#endregion
#pragma warning restore 1591
}//end namespace GZTW.AyaNova.BLL