Files
ayanova7/source/bizobjects/AyaLib/GZTW.AyaNova.BLL/UIUserGridLastView.cs
2020-05-08 20:40:49 +00:00

803 lines
29 KiB
C#

///////////////////////////////////////////////////////////
// UIUserGridLastView.cs
// Implementation of Class UIUserGridLastView
// CSLA type: Editable Child
// Created on: 22-May-2006
// Object design: John
// Coded: John 22-May-2006
///////////////////////////////////////////////////////////
using System;
using System.Data;
using CSLA.Data;
using GZTW.Data;
using CSLA;
using System.Threading;
using CSLA.Security;
using System.Xml;
using System.Text;
namespace GZTW.AyaNova.BLL
{
#pragma warning disable 1591
/// <summary>
/// Used by user interface to
/// hold settings pertaining to a grids last
/// filter and order by settings
///
/// Replaces UIGridLayout for read only main grids to
/// facilitate changeover to saved filters and WBI interface
///
/// Used to ensure that the grids appear the same as the
/// user last left them in.
///
/// </summary>
[Serializable]
public class UIUserGridLastView : BusinessBase
{
#region Attributes
private Guid mUserID;
private string mGridKey;
private string mViewXML;
private Guid mFilterID;
//used for UI consumption
//generated from xml, not saved to db
//Case 637 private DataSet mViewDS;
//this was causing hassle so now it should generate ds every time as required
#endregion
#region Constructor
/// <summary>
/// Private constructor to prevent direct instantiation
/// </summary>
private UIUserGridLastView()
{
//Set as child object
MarkAsChild();
mUserID = CurrentUserID;
//Case 637 mViewDS = new DataSet();
mViewXML = "";
//default no filter
mFilterID = GridFilter.NoFilterID;
}
#endregion
#region Business properties
/// <summary>
/// User ID number
/// </summary>
public Guid UserID
{
get
{
return mUserID;
}
set
{
if (mUserID != value)
{
mUserID = value;
MarkDirty();
}
}
}
/// <summary>
///
/// </summary>
public string GridKey
{
get
{
return mGridKey;
}
set
{
if (mGridKey != value)
{
mGridKey = value;
MarkDirty();
}
}
}
/// <summary>
/// XML fragment used to store grid sql filter criteria, order of columns,
/// sort order and visibility of columns.
///
/// If a filter ID is non empty when this view is applied to a grid then
/// the saved filter takes precedence and the filter portion of the
/// xml is not applied to the grid.
///
/// If the filter ID is empty then the filter criteria in the XML is used.
/// </summary>
public string ViewXML
{
get
{
return mViewXML;
}
set
{
if (mViewXML != value)
{
mViewXML = UIUserGridLastView.ScrubOutContactFieldsFromViewXML(value, mGridKey);
MarkDirty();
//Change 03-July-2006 just discovered that if the
//dataset is not cleared before the readxml it doesn't apparently
//get updated at all
//mViewDS.Clear();
//System.IO.StringReader sr = new System.IO.StringReader(mViewXML);
//mViewDS.ReadXml(sr);
}
}
}
//Case 534
/// <summary>
/// XML fragment to replace views current
/// where item group criteria
///
/// (Fragment must contain open and closing WHEREITEMGROUP tags)
///
/// Used to programmatically substitute a filter in the last view
/// from the UI layer
/// (right click context menu on unit or client to view all workorders etc)
/// </summary>
public string SubstituteCriteria
{
//bugbug - not removing old filters before adding new filter case 770
set
{
//wait, this could be an issue, below it seems to anticipate this would be a normal condition
//I'm going to leave this out for now, prior attempt didn't actually "throw" it so it would have been benign
//if (!value.Contains("<WHEREITEMGROUP") || !value.Contains("</WHEREITEMGROUP"))
// throw new System.ApplicationException(
// "UIUserGridLastView->SubstituteCriteria: Error unexpected view xml (missing WHEREITEMGROUP tags)\r\n" +
// "ViewXML:\r\n"+
// mViewXML+
// "Substitute XML:\r\n"+
// value +
// "\r\nGridKey:"+this.GridKey + ", UserId: " + this.UserID +
// "\r\n---------eot-----"
// );//case 3759
int nStart = -1;
int nEnd = -1;
if (!mViewXML.Contains("WHEREITEMGROUP"))
{
//Get the position it will go in
nStart = mViewXML.IndexOf("</GRIDCRITERIA>", 0);
nEnd = nStart;
}
else
{
nStart = mViewXML.IndexOf("<WHEREITEMGROUP", 0);
nEnd = mViewXML.LastIndexOf("</WHEREITEMGROUP>");//case 770
nEnd = nEnd + 17;//length of </WHEREITEMGROUP>
}
//case 3759
if (nStart == -1 || nEnd == -1)
// throw new System.ApplicationException("UIUserGridLastView->SubstituteCriteria: Error could not determine placement of inserted WHEREITEMGROUP tag in view xml:\r\n" + mViewXML);
throw new System.ApplicationException("UIUserGridLastView->SubstituteCriteria: Error unexpected view xml\r\n" +
"ViewXML:\r\n" +
mViewXML +
"Substitute XML:\r\n" +
value +
"\r\nGridKey:" + this.GridKey + ", UserId: " + this.UserID +
"\r\n---------eot-----"
);
//BUGBUG: this line is throwing an exception for some users (adam tecnica uk)
//It needs to be wrapped in a try catch block or tested for sanity
//Also what is leading up to it is unclear, perhaps it should trigger a log entry giving as much detail as possible
/*
2017-11-16 12:12:55,971 [4864] FATAL AyaNova.Form1 - Unhandled exception
System.ArgumentOutOfRangeException: Length cannot be less than zero.
Parameter name: length
at System.String.Substring(Int32 startIndex, Int32 length)
at GZTW.AyaNova.BLL.UIUserGridLastView.set_SubstituteCriteria(String value)
at AyaNova.Util.D(Object A, ToolClickEventArgs B)
AyaNova.Util.ShowAll_ToolClick(Object sender, ToolClickEventArgs e)"
at Infragistics.Win.UltraWinToolbars.ToolBase.OnToolClick(ToolClickEventArgs e)
at Infragistics.Win.UltraWinToolbars.UltraToolbarsManager.FireEvent(ToolbarEventIds id, EventArgs e)
at Infragistics.Win.UltraWinToolbars.PopupMenuItemUIElement.DoClickProcessing(MouseEventArgs e)
at Infragistics.Win.UltraWinToolbars.PopupMenuItemUIElement.OnMouseUp(MouseEventArgs e)
at Infragistics.Win.TextUIElementBase.OnMouseUp(MouseEventArgs e)
at Infragistics.Win.ControlUIElementBase.ProcessMouseUpHelper(Object sender, MouseEventArgs e)
at Infragistics.Win.ControlUIElementBase.ProcessMouseUp(Object sender, MouseEventArgs e)
at Infragistics.Win.Utilities.ProcessEvent(Control control, ProcessEvent eventToProcess, EventArgs e)
at Infragistics.Win.UltraWinToolbars.PopupControlBase.OnMouseUp(MouseEventArgs e)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
2017-11-16 12:12:58,654 [4864] WARN AyaNova.Form1 - User opted to abort after exception. Exiting now
2017-11-16 12:12:58,779 [4864] FATAL AyaNova.Form1 - Unhandled exception
System.NullReferenceException: Object reference not set to an instance of an object.
at AyaNova.MainGrid.B(Object A, MouseEventArgs B)
<Entry OldName="AyaNova.MainGrid.Grid_MouseUp(Object sender, MouseEventArgs e)" NewName="AyaNova.MainGrid.B(Object A, MouseEventArgs B)" />
at System.Windows.Forms.Control.OnMouseUp(MouseEventArgs e)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
2017-11-16 12:12:58,794 [4864] WARN AyaNova.Form1 - User opted to continue after exception
2017-11-16 12:12:58,794 [4864] INFO AyaNova.Form1 - AyaNova has shut down OK
2020-05-08 Michael Mera same issue huge db:
2020-05-08 11:42:19,662 [9944] FATAL AyaNova.Form1 - Unhandled exception
System.ArgumentOutOfRangeException: Length cannot be less than zero.
Parameter name: length
at System.String.Substring(Int32 startIndex, Int32 length)
at GZTW.AyaNova.BLL.UIUserGridLastView.set_SubstituteCriteria(String value)
at AyaNova.Util.D(Object A, ToolClickEventArgs B)
at Infragistics.Win.UltraWinToolbars.ToolBase.OnToolClick(ToolClickEventArgs e)
at Infragistics.Win.UltraWinToolbars.UltraToolbarsManager.FireEvent(ToolbarEventIds id, EventArgs e)
at Infragistics.Win.UltraWinToolbars.PopupMenuItemUIElement.DoClickProcessing(MouseEventArgs e)
at Infragistics.Win.UltraWinToolbars.PopupMenuItemUIElement.OnMouseUp(MouseEventArgs e)
at Infragistics.Win.TextUIElementBase.OnMouseUp(MouseEventArgs e)
at Infragistics.Win.ControlUIElementBase.ProcessMouseUpHelper(Object sender, MouseEventArgs e)
at Infragistics.Win.ControlUIElementBase.ProcessMouseUp(Object sender, MouseEventArgs e)
at Infragistics.Win.Utilities.ProcessEvent(Control control, ProcessEvent eventToProcess, EventArgs e)
at Infragistics.Win.UltraWinToolbars.PopupControlBase.OnMouseUp(MouseEventArgs e)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
*/
//case 3759 for above
int StartViewXMLLength = nStart;
int EndViewXMLLength = mViewXML.Length - nEnd;
if (StartViewXMLLength < 0 || EndViewXMLLength < 0)
throw new System.ApplicationException("UIUserGridLastView->SubstituteCriteria: Error bad view xml\r\n" +
"ViewXML:\r\n" +
mViewXML +
"Substitute XML:\r\n" +
value +
"\r\n=-=-=-=-=-+\r\nStartViewXMLLength:" + StartViewXMLLength.ToString() +
", EndViewXMLLength:" + EndViewXMLLength.ToString() +
"\r\nGridKey:" + this.GridKey + ", UserId: " + this.UserID +
"\r\n---------eot-----"
);
//originally before this case
//mViewXML = mViewXML.Substring(0, nStart) + value + mViewXML.Substring(nEnd, mViewXML.Length-nEnd);
mViewXML = mViewXML.Substring(0, StartViewXMLLength) + value + mViewXML.Substring(nEnd, EndViewXMLLength);
//reset
MarkDirty();
//flag as unsaved custom filter
FilterID = GridFilter.NoFilterID;
}
}
/// <summary>
/// Guid of saved filter that was last being used
/// by the user when they closed AyaNova
///
/// Guid.Empty means the filter is not a saved one
/// and so filter settings are customized and should be used
/// based on the XML and not the saved filter ID
/// </summary>
public Guid FilterID
{
get
{
return mFilterID;
}
set
{
if (mFilterID != value)
{
mFilterID = value;
MarkDirty();
}
}
}
/// <summary>
/// Returns the order by portion of the xml
/// as a datatable
/// </summary>
public DataTable ViewOrder
{
get
{
if (ViewDS.Tables.Contains("COLUMNITEM"))
return ViewDS.Tables["COLUMNITEM"];
else
return new DataTable();
}
}
/// <summary>
/// returns the filter portion of the xml
/// as a datatable object
/// </summary>
public DataTable ViewFilter
{
get
{
if (ViewDS.Tables.Contains("WHEREITEMGROUP"))
return ViewDS.Tables["WHEREITEMGROUP"];
else
return new DataTable();
}
}
/// <summary>
/// true if there is a filter contained in the last view object
/// </summary>
public bool HasFilter
{
get
{
return (ViewDS.Tables.Contains("WHEREITEMGROUP"));
}
}
/// <summary>
/// Returns true if the column name in question is filtered
/// Used by UI layer
/// </summary>
/// <param name="sColumnName"></param>
/// <returns></returns>
public bool IsFiltered(string sColumnName)//case 173
{
DataTable dt = ViewFilter;
foreach (DataRow dr in dt.Rows)
{
if (dr["UI"].ToString() == sColumnName) return true;
}
return false;
}
//Case 637
private DataSet ViewDS
{
get
{
if (string.IsNullOrEmpty(mViewXML)) return new DataSet();
string s = AyaBizUtils.EscapeXml(mViewXML);//case 1724
System.IO.StringReader sr = new System.IO.StringReader(s);
DataSet ds = new DataSet();
ds.ReadXml(sr);
return ds;
}
}
#endregion
#region System.Object overrides
public override string ToString()
{
return "UIUserGridLastView" + mGridKey + mUserID.ToString();
}
///
/// <param name="obj"></param>
public override bool Equals(Object obj)
{
if (obj == null || GetType() != obj.GetType()) return false;
UIUserGridLastView c = (UIUserGridLastView)obj;
return ((mUserID == c.mUserID) && (mGridKey == c.mGridKey));
}
public override int GetHashCode()
{
return ("UIUserGridLastView" + mGridKey + mUserID).GetHashCode();
}
#endregion
#region static methods
/// <summary>
/// Get new object
/// </summary>
/// <returns></returns>
internal static UIUserGridLastView NewItem(string GridKey)
{
UIUserGridLastView child = new UIUserGridLastView();
child.GridKey = GridKey;
return child;
}
/// <summary>
/// GetItem
/// </summary>
/// <param name="dr"></param>
/// <returns></returns>
internal static UIUserGridLastView GetItem(SafeDataReader dr)
{
UIUserGridLastView child = new UIUserGridLastView();
child.Fetch(dr);
return child;
}
/// <summary>
/// Case 432, remove old contact field sort and filter from view xml
/// if possible attempt to sub for new comparable field (email etc)
/// </summary>
internal static string ScrubOutContactFieldsFromViewXML(string sxml, string gridkey)
{
//short circuit if none of the offending fields are there
if (sxml.IndexOf("aContact", StringComparison.InvariantCultureIgnoreCase) == -1 &&
sxml.IndexOf("aContactPhone.", StringComparison.InvariantCultureIgnoreCase) == -1)
return sxml;
string sRootObject = gridkey.Replace("List", "");
bool bUnknownObject = false;
if (sRootObject != "Vendor" && sRootObject != "Client" && sRootObject != "HeadOffice")
bUnknownObject = true;
DataSet ds = new DataSet();
System.IO.StringReader sr = new System.IO.StringReader(AyaBizUtils.EscapeXml(sxml));
ds.ReadXml(sr, XmlReadMode.InferSchema);
DataTable dtCM = ds.Tables[0];
DataTable dtGroup = new DataTable();
DataTable dtWhere = new DataTable();
if (ds.Tables.Count > 1)
dtGroup = ds.Tables[1];
if (ds.Tables.Count > 2)
dtWhere = ds.Tables[2];
int nCMRowCount = dtCM.Rows.Count;
int nGroupCount = dtGroup.Rows.Count;
#region ColumnItems
for (int x = 0; x < nCMRowCount; x++)
{
DataRow dr = dtCM.Rows[x];
if (dr["CM"].ToString().IndexOf("aContact.aEmailAddress", StringComparison.InvariantCultureIgnoreCase) != -1)
{
if (bUnknownObject)
{
dtCM.Rows.RemoveAt(x);
nCMRowCount--;
x--;
}
else
{
dr["CM"] = "a" + sRootObject + ".aEmail";
dr["UI"] = "LT_" + sRootObject + "_Label_Email";
}
}
else if (dr["CM"].ToString().IndexOf("aContact.aFirstName", StringComparison.InvariantCultureIgnoreCase) != -1)
{
//Always remove
dtCM.Rows.RemoveAt(x);
nCMRowCount--;
x--;
}
else if (dr["CM"].ToString().IndexOf("aContact.aLastName", StringComparison.InvariantCultureIgnoreCase) != -1)
{
if (bUnknownObject)
{
dtCM.Rows.RemoveAt(x);
nCMRowCount--;
x--;
}
else
{//Sub last name for entire contact field
dr["CM"] = "a" + sRootObject + ".aContact";
dr["UI"] = "LT_" + sRootObject + "_Label_Contact";
}
}
else if (dr["CM"].ToString().IndexOf("aContactPhone.aPhoneNumber", StringComparison.InvariantCultureIgnoreCase) != -1)
{
if (bUnknownObject)
{
dtCM.Rows.RemoveAt(x);
nCMRowCount--;
x--;
}
else
{//Sub last name for entire contact field
dr["CM"] = "a" + sRootObject + ".aPhone1";
dr["UI"] = "LT_" + sRootObject + "_Label_Phone1";
}
}
else if (dr["CM"].ToString().IndexOf("aContactPhone.aPhoneAreaCode", StringComparison.InvariantCultureIgnoreCase) != -1)
{
//Always remove
dtCM.Rows.RemoveAt(x);
nCMRowCount--;
x--;
}
}
#endregion ColumnItems
#region Group (whereitemgroup)
for (int x = 0; x < nGroupCount; x++)
{
DataRow dr = dtGroup.Rows[x];
if (dr["UI"].ToString().IndexOf("LT_Contact_Label_EmailAddress", StringComparison.InvariantCultureIgnoreCase) != -1)
{
if (bUnknownObject)
{
dtGroup.Rows.RemoveAt(x);
nGroupCount--;
x--;
}
else
{
dr["UI"] = "LT_" + sRootObject + "_Label_Email";
}
}
else if (dr["UI"].ToString().IndexOf("LT_Contact_Label_FirstName", StringComparison.InvariantCultureIgnoreCase) != -1)
{
//Always remove
dtGroup.Rows.RemoveAt(x);
nGroupCount--;
x--;
}
else if (dr["UI"].ToString().IndexOf("LT_Contact_Label_FirstName", StringComparison.InvariantCultureIgnoreCase) != -1)
{
if (bUnknownObject)
{
dtGroup.Rows.RemoveAt(x);
nGroupCount--;
x--;
}
else
{//Sub last name for entire contact field
dr["UI"] = "LT_" + sRootObject + "_Label_Contact";
}
}
else if (dr["UI"].ToString().IndexOf("LT_ContactPhone_Label_PhoneNumber", StringComparison.InvariantCultureIgnoreCase) != -1)
{
if (bUnknownObject)
{
dtGroup.Rows.RemoveAt(x);
nGroupCount--;
x--;
}
else
{//Sub last name for entire contact field
dr["UI"] = "LT_" + sRootObject + "_Label_Phone1";
}
}
else if (dr["UI"].ToString().IndexOf("LT_ContactPhone_Label_PhoneAreaCode", StringComparison.InvariantCultureIgnoreCase) != -1)
{
//Always remove
dtGroup.Rows.RemoveAt(x);
nGroupCount--;
x--;
}
}
#endregion Group (whereitemgroup)
#region Whereitems
int nWhereCount = dtWhere.Rows.Count;
for (int x = 0; x < nWhereCount; x++)
{
DataRow dr = dtWhere.Rows[x];
if (dr["CM"].ToString().IndexOf("aContact.aEmailAddress", StringComparison.InvariantCultureIgnoreCase) != -1)
{
if (bUnknownObject)
{
dtWhere.Rows.RemoveAt(x);
nWhereCount--;
x--;
}
else
{
dr["CM"] = "a" + sRootObject + ".aEmail";
dr["UI"] = "LT_" + sRootObject + "_Label_Email";
}
}
else if (dr["CM"].ToString().IndexOf("aContact.aFirstName", StringComparison.InvariantCultureIgnoreCase) != -1)
{
//Always remove
dtWhere.Rows.RemoveAt(x);
nWhereCount--;
x--;
}
else if (dr["CM"].ToString().IndexOf("aContact.aLastName", StringComparison.InvariantCultureIgnoreCase) != -1)
{
if (bUnknownObject)
{
dtWhere.Rows.RemoveAt(x);
nWhereCount--;
x--;
}
else
{//Sub last name for entire contact field
dr["CM"] = "a" + sRootObject + ".aContact";
dr["UI"] = "LT_" + sRootObject + "_Label_Contact";
}
}
else if (dr["CM"].ToString().IndexOf("aContactPhone.aPhoneNumber", StringComparison.InvariantCultureIgnoreCase) != -1)
{
if (bUnknownObject)
{
dtWhere.Rows.RemoveAt(x);
nWhereCount--;
x--;
}
else
{//Sub last name for entire contact field
dr["CM"] = "a" + sRootObject + ".aPhone1";
dr["UI"] = "LT_" + sRootObject + "_Label_Phone1";
}
}
else if (dr["CM"].ToString().IndexOf("aContactPhone.aPhoneAreaCode", StringComparison.InvariantCultureIgnoreCase) != -1)
{
//Always remove
dtWhere.Rows.RemoveAt(x);
nWhereCount--;
x--;
}
}
#endregion Whereitems
StringBuilder sbOut = new StringBuilder();
System.IO.StringWriter sw = new System.IO.StringWriter(sbOut);
ds.WriteXml(sw);
sw.Close();
return sbOut.ToString();
}
#endregion
#region DAL DATA ACCESS
/// <summary>
/// Fetch
/// </summary>
/// <param name="dr"></param>
private void Fetch(SafeDataReader dr)
{
//UIUserGridLastView fields
mGridKey = dr.GetString("aGridKey");
//Important: use the property so that the
//dataset get's filled which is in turn
//consumed by the UI
ViewXML = dr.GetString("aViewXML");
mFilterID = dr.GetGuid("aFilterID");
MarkOld();
}
/// <summary>
/// Update
/// </summary>
/// <param name="tr"></param>
internal void Update(IDbTransaction tr)
{
//No need to update if there is nothing changed
if (!this.IsDirty) return;
//No concurrency check here, maybe need it in future?
//shouldn't if users don't log in more than once under
//same account though.
// 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,"PartCategory");
#region Delete
if (IsDeleted)
{
if (!IsNew)
{
//Delete object and child objects
DBCommandWrapper cmDelete = DBUtil.GetCommandFromSQL("DELETE FROM aUIUserGridLastView WHERE aUserID=@UserID AND aGridKey=@GridKey");
cmDelete.AddInParameter("@UserID", DbType.String, mUserID);
cmDelete.AddInParameter("@GridKey", DbType.String, mGridKey);
DBUtil.DB.ExecuteNonQuery(cmDelete, tr);
//-----------------------------
}
MarkNew();
return;
}
#endregion
#region Add / Update
DBCommandWrapper cm = null;
if (IsNew)//Add or update?
cm = DBUtil.GetCommandFromSQL(
"INSERT INTO aUIUserGridLastView (aUserID, aGridKey, " +
"aViewXML, aFilterID) VALUES (@UserID, " +
"@GridKey,@ViewXML,@FilterID)"
);
else
cm = DBUtil.GetCommandFromSQL(
"UPDATE aUIUserGridLastView SET aUserID=@UserID, aGridKey=@GridKey, " +
"aViewXML=@ViewXML,aFilterID=@FilterID " +
"WHERE aUserID=@UserID AND aGridKey=@GridKey"
);
//UIUserGridLastView fields
cm.AddInParameter("@UserID", DbType.Guid, mUserID);
cm.AddInParameter("@GridKey", DbType.String, mGridKey);
cm.AddInParameter("@ViewXML", DbType.String, mViewXML);
cm.AddInParameter("@FilterID", DbType.Guid, mFilterID);
DBUtil.DB.ExecuteNonQuery(cm, tr);
MarkOld();//db is now synched with object
#endregion
}
#endregion
}//end UIUserGridLastView
#pragma warning restore 1591
}//end namespace GZTW.AyaNova.BLL