using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using GZTW.AyaNova.BLL; using System.Collections; using Infragistics.Win; using Infragistics.Win.UltraWinGrid; using System.Threading; namespace AyaNovaOL { public partial class MsgToWo : Form { #region Read only list objects initialization //Read only lists used for quick lookup // private PriorityPickList mPriorityList; //private UnitPickList mClientUnitList; private RatePickList mRateList; // private PartPickList mPartList; private UserListScheduleable mUserList; //private UserPickList mAllUsers; // private TaxCodeList mTaxList; // private VendorPickList mVendors; // private TaskPickList mTaskList; // private LoanItemPickList mLoanItemList; //Case 640 //private PartWarehousePickList mWarehouseList; //case 1121 // private WorkorderItemTypePickList mTypeList; /// /// /// private void LoadReadOnlyLists() { //case 1039 //log.Debug("LoadReadOnlyLists"); // mPriorityList = PriorityPickList.GetList(); // mClientUnitList = UnitPickList.GetListByClient(mWorkorder.ClientID); if (mWorkorder.IsTemplate) mRateList = RatePickList.GetListAllActiveRates(); else { if (mWorkorder.ContractResolved() == null) mRateList = RatePickList.GetList(true); else mRateList = RatePickList.GetListWithContract(mWorkorder.ContractIDResolved()); } //case 1160 - this is redundant, the part list is loaded on demand when required //mPartList=PartPickList.GetAllParts(); mUserList = UserListScheduleable.GetList(); //mAllUsers = UserPickList.GetList(false);//case 58 not regional // mTaxList = TaxCodeList.GetList(mWorkorder.ListOfTaxCodesSelected()); // mVendors = VendorPickList.GetList(); // mTaskList = TaskPickList.GetList(); // mLoanItemList = LoanItemPickList.GetList(true); //Case 640 // mWarehouseList = PartWarehousePickList.GetActiveOnlyListWithExceptions(mWorkorder.ListOfPartWarehousesSelected()); //case 1121 // mTypeList = WorkorderItemTypePickList.GetList(); } #endregion #region Init / loadform / Closeform /// /// Used to track whether the close was done by the program /// or done by the user clicking on the upper left corner X control /// bool bClosingHandled = false; public MsgToWo() { InitializeComponent(); this.Icon = Resource1.ServiceWorkorder16icon; } public string EmailText { get; set; } public Workorder mWorkorder { get; set; } public WorkorderItem mWorkorderItem { get; set; } private void MsgToWo_Load(object sender, EventArgs e) { Util.Localize(this); if (mWorkorder.WorkorderService.ServiceNumber != 0) this.Text = Util.LocaleText.GetLocalizedText("O.WorkorderService") + " " + mWorkorder.WorkorderService.ServiceNumber.ToString(); else this.Text = Util.LocaleText.GetLocalizedText("O.WorkorderService"); LoadReadOnlyLists(); FillComboBoxes(); DataBind(); Application.ThreadException += new ThreadExceptionEventHandler( Application_ThreadException); // Application.Idle += new EventHandler(Application_Idle); } public static void Application_ThreadException( object sender, ThreadExceptionEventArgs e) { // Handle exception. //This is a workaround to a weird problem //where a serialization exception cannot load csla happens //if a user moves off a schedule item while entering it but not fully //can't figure out why it's happening but it's safely ignored if (e.Exception is System.Runtime.Serialization.SerializationException) { return; } // The exception object is contained in e.Exception. MessageBox.Show("Unhandled exception: \r\n" + e.Exception.Message + "\r\n====================\r\n" + e.Exception.StackTrace); } private void MsgToWo_FormClosing(object sender, FormClosingEventArgs e) { if (!bClosingHandled) { //Save record if necessary //User may opt to not cancel exit if (!RecordUpdate(RecordActionType.PromptToSave)) { e.Cancel = true; return; } } Application.ThreadException -= new ThreadExceptionEventHandler( Application_ThreadException); } #endregion init loadform #region Sync private void Application_Idle(object sender, EventArgs e) { btnOK.Enabled = (mWorkorder.IsSavable && mWorkorder.IsSaveAllowed); this.Text = DateTime.Now.ToString(); } #endregion sync #region combo boxes private void FillComboBoxes() { #region project Dictionary dProjects = new Dictionary(); dProjects.Add(Guid.Empty, "-"); ProjectList pl = ProjectList.GetList(""); foreach (ProjectList.ProjectListInfo i in pl) { dProjects.Add(i.LT_O_Project.Value, i.LT_O_Project.Display); } cbProjectID.DataSource = new BindingSource(dProjects, ""); cbProjectID.ValueMember = "Key"; cbProjectID.DisplayMember = "Value"; #endregion projects #region categories { GenericNVList l = GenericNVList.GetList("WORKORDERCATEGORY", "ID", "NAME", true, false, false); Dictionary dCategories = new Dictionary(); dCategories.Add(Guid.Empty, "-"); foreach (DictionaryEntry d in l.BindableList) dCategories.Add(new Guid(d.Key.ToString()), d.Value.ToString()); cbWorkorderCategoryID.DataSource = new BindingSource(dCategories, ""); cbWorkorderCategoryID.ValueMember = "Key"; cbWorkorderCategoryID.DisplayMember = "Value"; } #endregion #region Status WorkorderStatusPickList wsp = WorkorderStatusPickList.GetList(); Dictionary dStatusList = new Dictionary(); dStatusList.Add(Guid.Empty, "-"); foreach (WorkorderStatusPickList.WorkorderStatusPickListInfo i in wsp) dStatusList.Add(i.ID, i.Name); cbWorkorderStatusID.DataSource = new BindingSource(dStatusList, ""); cbWorkorderStatusID.ValueMember = "Key"; cbWorkorderStatusID.DisplayMember = "Value"; #endregion status //Workorder Item combo boxes #region Status Dictionary dWIStatusList = new Dictionary(); dWIStatusList.Add(Guid.Empty, "-"); foreach (WorkorderStatusPickList.WorkorderStatusPickListInfo i in wsp) dWIStatusList.Add(i.ID, i.Name); cbWorkorderItemStatusID.DataSource = new BindingSource(dWIStatusList, ""); cbWorkorderItemStatusID.ValueMember = "Key"; cbWorkorderItemStatusID.DisplayMember = "Value"; #endregion status #region Priority { PriorityPickList ppl = PriorityPickList.GetList(); Dictionary dPriorityList = new Dictionary(); dPriorityList.Add(Guid.Empty, "-"); foreach (PriorityPickList.PriorityPickListInfo i in ppl) dPriorityList.Add(i.ID, i.Name); cbWorkorderItemPriorityID.DataSource = new BindingSource(dPriorityList, ""); cbWorkorderItemPriorityID.ValueMember = "Key"; cbWorkorderItemPriorityID.DisplayMember = "Value"; } #endregion Priority #region Type { WorkorderItemTypePickList tpl = WorkorderItemTypePickList.GetList(); Dictionary dTypeList = new Dictionary(); dTypeList.Add(Guid.Empty, "-"); foreach (WorkorderItemTypePickList.WorkorderItemTypePickListInfo i in tpl) dTypeList.Add(i.ID, i.Name); cbWorkorderItemTypeID.DataSource = new BindingSource(dTypeList, ""); cbWorkorderItemTypeID.ValueMember = "Key"; cbWorkorderItemTypeID.DisplayMember = "Value"; } #endregion Type #region Unit { UnitPickList upl = UnitPickList.GetListByClient(mWorkorder.ClientID); Dictionary dUnitList = new Dictionary(); dUnitList.Add(Guid.Empty, "-"); foreach (UnitPickList.UnitPickListInfo i in upl) dUnitList.Add(i.ID, i.UnitName()); cbUnitID.DataSource = new BindingSource(dUnitList, ""); cbUnitID.ValueMember = "Key"; cbUnitID.DisplayMember = "Value"; } #endregion Unit #region UnitServiceType { GenericNVList l = GenericNVList.GetList("UNITSERVICETYPE", "ID", "NAME", true, false, false); Dictionary dUnitServiceTypes = new Dictionary(); dUnitServiceTypes.Add(Guid.Empty, "-"); foreach (DictionaryEntry d in l.BindableList) dUnitServiceTypes.Add(new Guid(d.Key.ToString()), d.Value.ToString()); cbUnitServiceTypeID.DataSource = new BindingSource(dUnitServiceTypes, ""); cbUnitServiceTypeID.ValueMember = "Key"; cbUnitServiceTypeID.DisplayMember = "Value"; } #endregion } #endregion combo boxes #region Form DataBinding and BrokenRules handling private bool AmBinding = false; /// /// Bind controls to business objects /// private void DataBind() { AmBinding = true; //Subscribe to broken rules changed event OnBrokenRulesChanged mWorkorder.GetBrokenRulesCollection().ListChanged += new System.ComponentModel.ListChangedEventHandler(OnBrokenRulesChanged); //=-=-=-=-=-=- Form Field bindings =-=-=-=-=-=-=-=-=-=-=-= //Not bound but needs to be filled edClient.Text = mWorkorder.NameAndAddress; //Text editors Util.BindField(edSummary, "Text", mWorkorder, "Summary"); Util.BindField(edCustomerReferenceNumber, "Text", mWorkorder, "CustomerReferenceNumber"); Util.BindField(edInternalReferenceNumber, "Text", mWorkorder, "InternalReferenceNumber"); Util.BindField(edCustomerContactName, "Text", mWorkorder, "CustomerContactName"); Util.BindField(edWorkorderItemSummary, "Text", mWorkorderItem, "Summary"); Util.BindField(edWorkorderItemTechNotes, "Text", mWorkorderItem, "TechNotes"); //Combo boxes Util.BindField(cbWorkorderCategoryID, "SelectedValue", mWorkorder, "WorkorderCategoryID"); Util.BindField(cbProjectID, "SelectedValue", mWorkorder, "ProjectID"); Util.BindField(cbWorkorderStatusID, "SelectedValue", mWorkorder.WorkorderService, "WorkorderStatusID"); Util.BindField(cbWorkorderItemStatusID, "SelectedValue", mWorkorderItem, "WorkorderStatusID"); Util.BindField(cbWorkorderItemPriorityID, "SelectedValue", mWorkorderItem, "PriorityID"); Util.BindField(cbWorkorderItemTypeID, "SelectedValue", mWorkorderItem, "TypeID"); Util.BindField(cbUnitID, "SelectedValue", mWorkorderItem, "UnitID"); Util.BindField(cbUnitServiceTypeID, "SelectedValue", mWorkorderItem, "WorkorderItemUnitServiceTypeID"); //Check boxes Util.BindField(ckOnsite, "Checked", mWorkorder, "Onsite"); Util.BindField(ckWorkorderItemWarrantyService, "Checked", mWorkorderItem, "WarrantyService"); //Added: 2-Oct-2006 this.edSummary.MaxLength = 255; this.edCustomerContactName.MaxLength = 255; this.edCustomerReferenceNumber.MaxLength = 255; this.edInternalReferenceNumber.MaxLength = 255; this.edWorkorderItemSummary.MaxLength = 255; //DateTime Util.BindField(dtServiceDate, "Value", mWorkorder.WorkorderService, "ServiceDate"); Util.BindField(dtCloseByDate, "Value", mWorkorder.WorkorderService, "CloseByDate"); Util.BindField(dtWorkorderItemRequestDate, "Value", mWorkorderItem, "RequestDate"); //GRIDS Util.BindField(this.gridScheduledUsers, "DataSource", mWorkorderItem, "ScheduledUsers"); //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //Bind IsDirty property to hidden checkbox to //ensure isdirtychanged event is available //to data binding infrastructure Util.BindField(ckIsDirty, "Checked", mWorkorder, "IsDirty"); //Setup initial link to broken rules OnBrokenRulesChanged(null, null); AmBinding = false; } /// /// Handle a change in broken rules /// /// /// private void OnBrokenRulesChanged(object sender, System.ComponentModel.ListChangedEventArgs e) { Util.BrokenRuleFeedback(this, mWorkorder, epWO); } #endregion #region ScheduledUsers items grid events / Initialization private bool bScheduledUsersGridIntialized = false; private void gridScheduledUsers_InitializeLayout(object sender, Infragistics.Win.UltraWinGrid.InitializeLayoutEventArgs e) { if (bScheduledUsersGridIntialized || gridScheduledUsers.DisplayLayout.Bands[0].Columns.Count == 0) return; //case 1039 //log.Debug("gridScheduledUsers_InitializeLayout"); gridScheduledUsers.DisplayLayout.Override.HeaderClickAction = HeaderClickAction.SortSingle; gridScheduledUsers.DisplayLayout.Override.AllowAddNew = AllowAddNew.TemplateOnBottom; Util.GridPreLocalize("WorkorderItemScheduledUser", this.gridScheduledUsers.DisplayLayout.Bands[0]); Util.FetchGridLayout("WorkorderItemScheduledUsers", "", gridScheduledUsers); //Hide unwanted workorder item ScheduledUsers fields in that grid foreach (UltraGridColumn c in gridScheduledUsers.DisplayLayout.Bands[0].Columns) { c.Hidden = true; } //Show the ones we want to... gridScheduledUsers.DisplayLayout.Bands[0].Columns["UserID"].Hidden = false; gridScheduledUsers.DisplayLayout.Bands[0].Columns["ServiceRateID"].Hidden = false; gridScheduledUsers.DisplayLayout.Bands[0].Columns["StartDate"].Hidden = mWorkorder.IsTemplate; gridScheduledUsers.DisplayLayout.Bands[0].Columns["StartDate"].EditorComponent = this.GridCalendar; gridScheduledUsers.DisplayLayout.Bands[0].Columns["StopDate"].Hidden = mWorkorder.IsTemplate; gridScheduledUsers.DisplayLayout.Bands[0].Columns["StopDate"].EditorComponent = this.GridCalendar; gridScheduledUsers.DisplayLayout.Bands[0].Columns["EstimatedQuantity"].Hidden = false; gridScheduledUsers.DisplayLayout.Bands[0].Columns["EstimatedQuantity"].Format = "g29"; Util.LocalizeGrid(gridScheduledUsers); gridScheduledUsers.DisplayLayout.ValueLists.Clear(); //************************************************** //Populate value lists FillScheduledUserRatesList(); #region ======== Sheduleable users value list ======== //Clear any previous value list from this column gridScheduledUsers.DisplayLayout.Bands[0].Columns["UserID"].ValueList = null; //Add all potential active items ValueList vlTechs = new ValueList(); //Empty is valid choice here vlTechs.ValueListItems.Add(Guid.Empty, Util.NoSelectionString);//Case 318 foreach (UserListScheduleable.UserListScheduleableInfo ui in mUserList) { if (ui.Active == true) vlTechs.ValueListItems.Add(ui.ID, ui.Name(Util.GlobalSettings.DefaultScheduleableUserNameDisplayFormat)); } //Show sorted alphabetically vlTechs.SortStyle = ValueListSortStyle.Ascending; //Add manual items that are inactive but need to be displayed to list foreach (WorkorderItem wi in mWorkorder.WorkorderItems) { foreach (WorkorderItemScheduledUser wl in wi.ScheduledUsers) { //Is this schedtechs item's User ID in the list already? if (vlTechs.FindByDataValue(wl.UserID) != null) continue;//17-April-2006 was a break; causing the loop to end prematurely else { //Nope, add it to the list manually foreach (UserListScheduleable.UserListScheduleableInfo ui in mUserList) { if (ui.ID == wl.UserID) { ValueListItem vi = vlTechs.ValueListItems.Add(ui.ID, ui.Name(Util.GlobalSettings.DefaultScheduleableUserNameDisplayFormat)); vi.Appearance.ForeColor = System.Drawing.SystemColors.GrayText; } } } } } //Bind value lists to correct columns in grid gridScheduledUsers.DisplayLayout.Bands[0].Columns["UserID"].ValueList = vlTechs; //Set column to dropdownlist style so that user can not type an invalid value in a cell //but must select from the list only gridScheduledUsers.DisplayLayout.Bands[0].Columns["UserID"].Style = Infragistics.Win.UltraWinGrid.ColumnStyle.DropDownValidate;//Case 96 for autocomplete (was DropDownList) gridScheduledUsers.DisplayLayout.Bands[0].Columns["UserID"].AutoCompleteMode = Infragistics.Win.AutoCompleteMode.SuggestAppend; #endregion //Allow empty string entry on grid Util.SetTextColumnsNullable(gridScheduledUsers); //case 1105 if (mWorkorder.IsEditable) Util.GridAddDeleteButton(gridScheduledUsers); else Util.GridRemoveDeleteButton(gridScheduledUsers); //=========DONE============== bScheduledUsersGridIntialized = true; } private void FillScheduledUserRatesList() { //case 1039 //log.Debug("FillScheduledUserRatesList"); #region ======== Rates value list ======== //Clear any previous value list from this column gridScheduledUsers.DisplayLayout.Bands[0].Columns["ServiceRateID"].ValueList = null; //Add all potential active items ValueList vlRates = new ValueList(); //Empty not valid but looks better this way when new record is added //biz object's broken rules will catch any invalide entry anyway vlRates.ValueListItems.Add(Guid.Empty, "-");//Case 318 //fill list with active labor (service) rates foreach (RatePickList.RatePickListInfo ui in mRateList) { if ((ui.Selectable == true) && ui.RateType == RateTypes.Service) { vlRates.ValueListItems.Add(ui.ID, ui.Name); } } vlRates.SortStyle = ValueListSortStyle.Ascending; //Add manual items that are inactive but need to be displayed to list foreach (WorkorderItem wi in mWorkorder.WorkorderItems) { foreach (WorkorderItemScheduledUser wl in wi.ScheduledUsers) { //Is this labor item's service rate ID in the list already? if (vlRates.FindByDataValue(wl.ServiceRateID) != null) continue;//17-April-2006 was a break; causing the loop to end prematurely else { //Nope, add it to the list manually ValueListItem vi = vlRates.ValueListItems.Add(wl.ServiceRateID, mRateList[wl.ServiceRateID].Name); vi.Appearance.ForeColor = System.Drawing.SystemColors.GrayText; } } } //Bind value lists to correct columns in grid gridScheduledUsers.DisplayLayout.Bands[0].Columns["ServiceRateID"].ValueList = vlRates; //Set column to dropdownlist style so that user can not type an invalid value in a cell //but must select from the list only gridScheduledUsers.DisplayLayout.Bands[0].Columns["ServiceRateID"].Style = Infragistics.Win.UltraWinGrid.ColumnStyle.DropDownValidate;//Case 96 for autocomplete (was DropDownList) gridScheduledUsers.DisplayLayout.Bands[0].Columns["ServiceRateID"].AutoCompleteMode = Infragistics.Win.AutoCompleteMode.SuggestAppend; #endregion } /// /// /// /// /// private void gridScheduledUsers_BeforeRowInsert(object sender, Infragistics.Win.UltraWinGrid.BeforeRowInsertEventArgs e) { //case 1039 //log.Debug("gridScheduledUsers_BeforeRowInsert"); if (mWorkorder.Closed || mWorkorder.ServiceCompleted) return; mWorkorderItem.ScheduledUsers.Add(mWorkorderItem); e.Cancel = true; } /// /// Handle users changes and update grid as appropriate /// /// /// private void gridScheduledUsers_AfterCellUpdate(object sender, Infragistics.Win.UltraWinGrid.CellEventArgs e) { if ("StartDate" == e.Cell.Column.Key || "StopDate" == e.Cell.Column.Key) { //case 1251 if (!(e.Cell.Row.Cells["StopDate"].Value is DateTime)) return; if (!(e.Cell.Row.Cells["StartDate"].Value is DateTime)) return; DateTime dtStart = (DateTime)e.Cell.Row.Cells["StartDate"].Value; DateTime dtStop = (DateTime)e.Cell.Row.Cells["StopDate"].Value; if (dtStart == dtStop) return; TimeSpan ts = dtStop.Subtract(dtStart); e.Cell.Row.Cells["EstimatedQuantity"].Value = decimal.Round( (decimal)ts.TotalHours, 2, MidpointRounding.AwayFromZero); } } private void gridScheduledUsers_InitializeRow_1(object sender, InitializeRowEventArgs e) { //show broken rule icon if any Util.GridShowBrokenRulesErrorIcons(e); } private void gridScheduledUsers_MouseEnterElement_1(object sender, UIElementEventArgs e) { Util.GridShowBrokenRulesToolTip(e, tipError); } private void gridScheduledUsers_ClickCellButton(object sender, CellEventArgs e) { if (e.Cell.Column.Key == "REMOVE") gridScheduledUsers.DisplayLayout.ActiveRow.Delete(); } #endregion sched users grid private void btnTest_Click(object sender, EventArgs e) { MessageBox.Show("What's dirty:\r\n" + mWorkorder.WhatsDirty + "\r\n=-=-=-=-=-=-=-\r\nIsSavable:" + mWorkorder.IsSavable.ToString() + "\r\n" + "IsSaveAllowed:" + mWorkorder.IsSaveAllowed.ToString() + "\r\nBroken rules:\r\n" + mWorkorder.BrokenRulesText + "\r\nBroken rules collection count:\r\n" + mWorkorder.GetBrokenRulesCollection().Count.ToString()); } #region Business object editing / adding / deletion related code //Used to signal to main form that there are changes //which could affect it if true private bool mbChangesMade = false; public bool ChangesMade { get { return mbChangesMade; } } /// /// Update record and quit if requested /// /// /// True if handled, false if not handled private bool RecordUpdate(RecordActionType SaveType) { //case 1039 //if(log.IsDebugEnabled) //case 1039 //log.Debug("SaveHandler(Action="+SaveType.ToString()+")"); //switch the focus to a non-editable control //so that any changes in the current editable control //will get updated before attempting to save //probably don't need this here since we aren't using a menu just an ok button which takes focus off automatically anyway. // btnWorkorderCategoryID.Focus(); gridScheduledUsers.UpdateData(); //Added: 17-Nov-2006 to handle concurrency errors more gracefully try { #region Process savetype switch (SaveType) { case RecordActionType.SaveAndExit: //Save if necessary and exit if (mWorkorder.IsSavable) { mWorkorder.ApplyEdit(); mWorkorder.Save(); bClosingHandled = true; mbChangesMade = true; this.Close(); return true; } if (mWorkorder.IsDirty)//dirty and unsaveable due to broken rules { if (Util.PromptForBrokenRulesCancelSave() == DialogResult.Yes) { bClosingHandled = true; this.Close(); return true; } else return false; } //not dirty so just exit bClosingHandled = true; this.Close(); return true; case RecordActionType.SaveOnly: if (mWorkorder.IsSavable) { mWorkorder.ApplyEdit(); mWorkorder = (Workorder)mWorkorder.Save(); //case 1040 DataBind(); mbChangesMade = true; return true; } return true; case RecordActionType.PromptToSave: //Prompt to save and save if //required if (mWorkorder.IsDirty) { DialogResult dr = Util.PromptForSave(); if (dr == DialogResult.Cancel) { //Cancel return false; } if (dr == DialogResult.Yes) { //Save before exit if (mWorkorder.IsSavable) { mWorkorder.ApplyEdit(); mWorkorder.Save(); mbChangesMade = true; return true; } if (mWorkorder.IsDirty)//dirty and unsaveable due to broken rules { if (Util.PromptForBrokenRulesCancelSave() == DialogResult.Yes) { return true; } else return false; } } } return true; } #endregion process savetype } catch (Exception ex) { //crack the exception if (ex.InnerException != null) ex = ex.InnerException; if (ex is AyConcurrencyException) { MessageBox.Show(ex.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Information); //if (log.IsDebugEnabled) //case 1039 //log.Debug("Save record concurrency exception", ex); bClosingHandled = true; this.Close(); return false; } else throw; } return false; } #endregion private void btnCancel_Click(object sender, EventArgs e) { bClosingHandled = true; this.Close(); } private void btnOK_Click(object sender, EventArgs e) { RecordUpdate(RecordActionType.SaveAndExit); } private void gridScheduledUsers_BeforeRowCancelUpdate(object sender, CancelableRowEventArgs e) { //MessageBox.Show("BeforeRowCancelUpdate"); } }//end class }//end namespace