5725 lines
222 KiB
C#
5725 lines
222 KiB
C#
///////////////////////////////////////////////////////////
|
|
// Workorder.cs
|
|
// Implementation of Class Workorder
|
|
// CSLA type: Editable Root
|
|
// Created on: 07-Jun-2004 8:41:45 AM
|
|
// Object design: Joyce
|
|
// Coded: John 29-July-2004
|
|
///////////////////////////////////////////////////////////
|
|
|
|
using System;
|
|
using System.Data;
|
|
using CSLA.Data;
|
|
using GZTW.Data;
|
|
using CSLA;
|
|
using System.Threading;
|
|
using CSLA.Security;
|
|
using System.ComponentModel;
|
|
using System.Text;
|
|
|
|
namespace GZTW.AyaNova.BLL
|
|
{
|
|
/// <summary>
|
|
/// Workorder object - the heart of AyaNova.
|
|
/// This is the parent object of all forms of workorders including quotes, pm, service and template forms.
|
|
/// </summary>
|
|
[Serializable]
|
|
public class Workorder : BusinessBase
|
|
{
|
|
|
|
#region Attributes
|
|
|
|
private bool bReadOnly;
|
|
private Guid mID;
|
|
private SmartDate mCreated;
|
|
private SmartDate mModified;
|
|
private Guid mCreator;
|
|
private Guid mModifier;
|
|
private AssignedDocs mDocs;
|
|
|
|
//Workorder properties
|
|
private Guid mClientID;
|
|
private Guid mProjectID;
|
|
private string mInternalReferenceNumber = "";
|
|
private string mCustomerReferenceNumber = "";
|
|
private bool mOnsite;
|
|
private string mCustomerContactName = "";
|
|
//case 58
|
|
private Guid mRegionID;
|
|
|
|
private string mSummary = "";
|
|
private string mTemplateDescription = "";
|
|
private Guid mFormLayoutID;
|
|
private WorkorderTypes mWorkorderType;
|
|
//private bool mTemplate;
|
|
private Guid mWorkorderCategoryID;
|
|
|
|
//Children
|
|
private WorkorderQuote mQuote;
|
|
private WorkorderService mService;
|
|
private WorkorderPreventiveMaintenance mWorkorderPreventiveMaintenance;
|
|
private WorkorderItems mWorkorderItems;
|
|
|
|
|
|
|
|
|
|
|
|
private bool mUseInventory;
|
|
|
|
//applicable only if it's a service workorder
|
|
private bool mServiceCompleted;
|
|
private bool mClosed;
|
|
|
|
internal Guid mFromQuoteID;
|
|
internal Guid mFromPMID;
|
|
|
|
//case 1387
|
|
internal SecurityLevelTypes mRights;
|
|
|
|
//case 3132
|
|
private bool mTemplateFreshPrice;
|
|
|
|
#endregion
|
|
|
|
#region Constructor
|
|
|
|
/// <summary>
|
|
/// Private constructor to prevent direct instantiation
|
|
/// </summary>
|
|
private Workorder()
|
|
{
|
|
|
|
//Set to read / write initially so that properties
|
|
//can be set
|
|
bReadOnly = false;
|
|
|
|
//New ID
|
|
mID = Guid.NewGuid();
|
|
|
|
mWorkorderItems = WorkorderItems.NewItems();
|
|
|
|
//Built-in "Default" region
|
|
mRegionID = Region.DefaultRegionID;//case 58
|
|
|
|
//Set record history to defaults
|
|
mCreated = new SmartDate(DBUtil.CurrentWorkingDateTime);
|
|
mModified = new SmartDate();
|
|
mCreator = Guid.Empty;
|
|
mModifier = Guid.Empty;
|
|
mUseInventory = AyaBizUtils.GlobalSettings.UseInventory;
|
|
mClosed = false;
|
|
mServiceCompleted = false;
|
|
mDocs = AssignedDocs.NewItems();
|
|
//Changed 15-March-2006
|
|
mOnsite = true;
|
|
|
|
//case 3132
|
|
mTemplateFreshPrice = false;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Business properties
|
|
|
|
/// <summary>
|
|
/// Get internal id number Read only property because it's set internally, not
|
|
/// externally
|
|
/// </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>
|
|
/// <see cref="AssignedDoc"/> object collection assigned to this workorder
|
|
/// </summary>
|
|
public AssignedDocs Docs
|
|
{
|
|
get
|
|
{
|
|
return mDocs;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Category of workorder
|
|
/// </summary>
|
|
public Guid WorkorderCategoryID
|
|
{
|
|
get
|
|
{
|
|
return mWorkorderCategoryID;
|
|
}
|
|
set
|
|
{
|
|
if (bReadOnly)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if (mWorkorderCategoryID != value)
|
|
{
|
|
mWorkorderCategoryID = value;
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Client this work order applies to
|
|
/// </summary>
|
|
public Guid ClientID
|
|
{
|
|
get
|
|
{
|
|
return mClientID;
|
|
}
|
|
set
|
|
{
|
|
if (bReadOnly)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if (mClientID != value)
|
|
{
|
|
mClientID = value;
|
|
if (this.CustomerContactName == "")
|
|
{
|
|
Client c = Client.GetItemNoMRU(value);
|
|
|
|
this.CustomerContactName = c.Contact;
|
|
|
|
c = null;
|
|
}
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Brief description of the purpose of the workorder as a whole
|
|
/// displays on many reports and in various grids. Should be an overview
|
|
/// of what the service is about for the work order in general.
|
|
/// </summary>
|
|
public string Summary
|
|
{
|
|
get
|
|
{
|
|
return mSummary;
|
|
}
|
|
set
|
|
{
|
|
if (bReadOnly)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if (mSummary != value)
|
|
{
|
|
mSummary = value;
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Need to flesh out a lot more as refers to a collection etc
|
|
///
|
|
/// ID of the FormLayout which is object describing the field positions and field
|
|
/// titles of a workorder input form as designed by a user
|
|
/// </summary>
|
|
public Guid FormLayoutID
|
|
{
|
|
get
|
|
{
|
|
return mFormLayoutID;
|
|
}
|
|
set
|
|
{
|
|
if (bReadOnly)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if (mFormLayoutID != value)
|
|
{
|
|
mFormLayoutID = value;
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// GUID of project selected
|
|
/// </summary>
|
|
public Guid ProjectID
|
|
{
|
|
get
|
|
{
|
|
return mProjectID;
|
|
}
|
|
set
|
|
{
|
|
if (bReadOnly)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if (mProjectID != value)
|
|
{
|
|
mProjectID = value;
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// In addition to Workorder number - may have letters in it, therefore used in
|
|
/// addition to numerial wo number
|
|
/// </summary>
|
|
public string InternalReferenceNumber
|
|
{
|
|
get
|
|
{
|
|
return mInternalReferenceNumber;
|
|
}
|
|
set
|
|
{
|
|
if (bReadOnly)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if (mInternalReferenceNumber != value)
|
|
{
|
|
mInternalReferenceNumber = value;
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Client's reference number
|
|
/// </summary>
|
|
public string CustomerReferenceNumber
|
|
{
|
|
get
|
|
{
|
|
return mCustomerReferenceNumber;
|
|
}
|
|
set
|
|
{
|
|
if (bReadOnly)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if (mCustomerReferenceNumber != value)
|
|
{
|
|
mCustomerReferenceNumber = value;
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Onsite indicates at client site
|
|
/// Default is true
|
|
/// Can be set in regional settings
|
|
/// </summary>
|
|
public bool Onsite
|
|
{
|
|
get
|
|
{
|
|
return mOnsite;
|
|
}
|
|
set
|
|
{
|
|
if (bReadOnly)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if (mOnsite != value)
|
|
{
|
|
mOnsite = value;
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Takes as default name in client contact list when client first selected, but
|
|
/// can be edited by user
|
|
/// </summary>
|
|
public string CustomerContactName
|
|
{
|
|
get
|
|
{
|
|
return mCustomerContactName;
|
|
}
|
|
set
|
|
{
|
|
if (bReadOnly)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if (mCustomerContactName != value)
|
|
{
|
|
mCustomerContactName = value;
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Determines if a workorder is a template, a quote, a PM item, a workorder for a
|
|
/// client or an internal workorder
|
|
/// </summary>
|
|
public WorkorderTypes WorkorderType
|
|
{
|
|
get
|
|
{
|
|
return mWorkorderType;
|
|
}
|
|
set
|
|
{
|
|
if (bReadOnly)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if (mWorkorderType != value)
|
|
{
|
|
mWorkorderType = value;
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
///
|
|
/// Brief description of the purpose of the workorder template as a whole
|
|
/// displays on many reports and in various grids.
|
|
///
|
|
/// </summary>
|
|
public string TemplateDescription
|
|
{
|
|
get
|
|
{
|
|
return mTemplateDescription;
|
|
}
|
|
set
|
|
{
|
|
if (bReadOnly)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if (mTemplateDescription != value)
|
|
{
|
|
mTemplateDescription = value;
|
|
BrokenRules.Assert("TemplateDescriptionLength",
|
|
"Error.Object.FieldLengthExceeded255,Workorder.Label.TemplateDescription",
|
|
"TemplateDescription", value.Length > 255);
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Only used if this is a template workorder
|
|
/// Regular Service, Quote and PM work orders follow the client's region
|
|
///
|
|
/// Any attempt to set this field on a non template work order
|
|
/// will do nothing.
|
|
///
|
|
/// Limit template to specific region or available to all regions using Region.DefaultRegionID
|
|
/// </summary>
|
|
public Guid RegionID
|
|
{
|
|
get
|
|
{
|
|
return mRegionID;
|
|
}
|
|
set
|
|
{
|
|
if (bReadOnly)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if (this.IsTemplate)
|
|
{
|
|
if (mRegionID != value)
|
|
{
|
|
mRegionID = value;
|
|
|
|
BrokenRules.Assert("RegionIDRequired",
|
|
"Error.Object.RequiredFieldEmpty,O.Region",
|
|
"RegionID", value == Guid.Empty);
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//Child objects
|
|
|
|
/// <summary>
|
|
/// If not a WorkorderPreventiveMaintenance, is null
|
|
/// If a WorkorderPreventiveMaintenance contains the WorkorderPreventiveMaintenance child object
|
|
/// </summary>
|
|
public WorkorderPreventiveMaintenance WorkorderPreventiveMaintenance
|
|
{
|
|
get
|
|
{
|
|
return mWorkorderPreventiveMaintenance;
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// If not a WorkorderService, is null
|
|
/// If a WorkorderService contains the WorkorderService child object
|
|
/// </summary>
|
|
public WorkorderService WorkorderService
|
|
{
|
|
get
|
|
{
|
|
return mService;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Workorder items collection
|
|
/// </summary>
|
|
public WorkorderItems WorkorderItems
|
|
{
|
|
get
|
|
{
|
|
return mWorkorderItems;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// If not a quote, is null
|
|
/// If a quote, contains the WorkorderQuote child object
|
|
/// </summary>
|
|
public WorkorderQuote WorkorderQuote
|
|
{
|
|
get
|
|
{
|
|
return mQuote;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//*************** CONTRACT / SERVICEBANK RELATED CODE **************************
|
|
|
|
/// <summary>
|
|
/// Returns populated TypeAndID if the client or head office for this workorder is bankable
|
|
/// (If the unit is bankable that's handled separately)
|
|
///
|
|
/// Returns null if not bankable
|
|
/// </summary>
|
|
public TypeAndID BankableResolved()
|
|
{
|
|
if (AyaBizUtils.Lite) return null;
|
|
|
|
//internal service?
|
|
if (this.ClientID == Guid.Empty) return null;
|
|
|
|
//Case 576
|
|
return ServiceBankResolver.BankableObject(this.ClientID);
|
|
|
|
////CLIENT
|
|
//Client c = Client.GetItem(this.ClientID);
|
|
//if (c.UsesBanking)
|
|
// return new TypeAndID(RootObjectTypes.Client, this.ClientID);
|
|
|
|
////HEADOFFICE
|
|
//if (c.HeadOfficeID == Guid.Empty) return null;
|
|
|
|
//if (HeadOffice.GetItem(c.HeadOfficeID).UsesBanking)
|
|
// return new TypeAndID(RootObjectTypes.HeadOffice, c.HeadOfficeID);
|
|
|
|
//return null;
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks *all* possible bankable objects in this order:
|
|
/// Unit->Client->HeadOffice
|
|
/// If any of those objects are bankable then the type and id is returned
|
|
///
|
|
/// If none are bankable then it returns a type and ID of Guid empty and object type Nothing.
|
|
///
|
|
/// This method supersedes the original BankableResolved method and should be used in
|
|
/// it's place when there is a unit involved
|
|
/// </summary>
|
|
public TypeAndID BankableResolved(Guid WorkorderItemId)
|
|
{
|
|
if (this.WorkorderItems[WorkorderItemId].HasUnit)
|
|
{
|
|
Unit u = Unit.GetItem(this.WorkorderItems[WorkorderItemId].UnitID);
|
|
if (u != null && u.UsesBanking)
|
|
{
|
|
return new TypeAndID(RootObjectTypes.Unit, u.ID);
|
|
}
|
|
}
|
|
|
|
TypeAndID woTid = this.BankableResolved();
|
|
if (woTid == null)
|
|
return new TypeAndID(RootObjectTypes.Nothing, Guid.Empty);
|
|
else
|
|
return woTid;
|
|
}
|
|
|
|
|
|
//Added 28-Aug-2006 to speed up contract resolution for UI
|
|
//"cache" the resolved contract so the expense
|
|
//of determining it is only done once.
|
|
//contract resolved is used quite heavily by both
|
|
//web and winform UI's
|
|
private Contract mResolvedContract = null;
|
|
private bool mContractHasBeenResolved = false;
|
|
|
|
/// <summary>
|
|
/// Returns Contract that is most specific
|
|
/// or null if no contract
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public Contract ContractResolved()
|
|
{
|
|
//Added 28-Aug-2006 to speed up contract resolution for UI
|
|
if (mContractHasBeenResolved) return mResolvedContract;
|
|
|
|
//internal service?
|
|
if (this.ClientID == Guid.Empty)
|
|
{
|
|
mContractHasBeenResolved = true;
|
|
|
|
return null;
|
|
}
|
|
|
|
mResolvedContract = ContractResolver.ResolvedContract(mClientID);
|
|
mContractHasBeenResolved = true;
|
|
return mResolvedContract;
|
|
|
|
//Case 577
|
|
////CLIENT
|
|
//Client c=Client.GetItem(this.ClientID);
|
|
////Case 231 now check for contract in effect
|
|
////not just contract id exists
|
|
//if (c.ContractInEffect)
|
|
//{
|
|
// mContractHasBeenResolved = true;
|
|
// mResolvedContract= Contract.GetItem(c.ContractID);
|
|
|
|
// return mResolvedContract;
|
|
//}
|
|
|
|
////HEADOFFICE
|
|
//if (c.HeadOfficeID == Guid.Empty)
|
|
//{
|
|
// mContractHasBeenResolved = true;
|
|
// return null;
|
|
//}
|
|
|
|
////Case 231 changes to use new contractineffect property of
|
|
////head office instead of just returning the contract if it existed
|
|
////expired or not
|
|
//HeadOffice ho = HeadOffice.GetItem(c.HeadOfficeID);
|
|
|
|
//if (ho.ContractInEffect)
|
|
//{
|
|
// mContractHasBeenResolved = true;
|
|
// mResolvedContract= Contract.GetItem(ho.ContractID);
|
|
// return mResolvedContract;
|
|
//}
|
|
|
|
////Resolved to be no contract applicable
|
|
//mContractHasBeenResolved = true;
|
|
//return null;
|
|
}
|
|
|
|
|
|
//Added:17-Aug-2006 for wbi
|
|
/// <summary>
|
|
/// Returns ID only of Contract that is most specific to
|
|
/// this workorder or empty Guid if no Contract applies at all
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public Guid ContractIDResolved()
|
|
{
|
|
Contract c = ContractResolved();
|
|
if (c == null)
|
|
return Guid.Empty;
|
|
else
|
|
return c.ID;
|
|
}
|
|
|
|
//******************************************************************************
|
|
|
|
|
|
/// <summary>
|
|
/// Mirror of global object's UseInventory setting
|
|
/// </summary>
|
|
public bool UseInventory
|
|
{
|
|
get
|
|
{
|
|
return mUseInventory;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Move workorderItem from current workorder to another
|
|
/// (Requires full rights and not a closed or read only workorder)
|
|
/// </summary>
|
|
/// <param name="ToWorkorderID"></param>
|
|
/// <param name="WorkorderItemID"></param>
|
|
public void MoveWorkorderItem(Guid ToWorkorderID, Guid WorkorderItemID)
|
|
{
|
|
//case 1387 now checks rights to this object
|
|
if (this.mClosed || this.mServiceCompleted || Rights < SecurityLevelTypes.ReadWrite)
|
|
ThrowSetError();
|
|
|
|
//make sure the workorder is not dirty or unsaved
|
|
if (this.IsDirty || !this.IsValid)
|
|
{
|
|
throw new System.ApplicationException
|
|
(
|
|
LocalizedTextTable.GetLocalizedTextDirect("Workorder.Label.Error.NotMoveableUntilSavedAndValid")
|
|
);
|
|
|
|
}
|
|
|
|
//this will throw a localized exception of there is less than 2 workorder items
|
|
this.WorkorderItems.EnsureAtLeastOneWorkorderItem();
|
|
|
|
//Do the move
|
|
Workorder.WorkorderItemMover.Move(this.mID, ToWorkorderID, WorkorderItemID);
|
|
|
|
try
|
|
{
|
|
//flag as moved so it won't be updated
|
|
this.WorkorderItems[WorkorderItemID.ToString()].mMoved = true;
|
|
this.WorkorderItems.Remove(WorkorderItemID);
|
|
}
|
|
catch
|
|
{
|
|
//do nothing, it's an annoying visual thing only?
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Flag to indicate that service has been completed for this workorder
|
|
/// When true it means that all but workorder header items will become read only
|
|
/// this property can only be set from true to false by someone with full rights
|
|
/// to the workorder object
|
|
/// </summary>
|
|
public bool ServiceCompleted
|
|
{
|
|
get
|
|
{
|
|
return mServiceCompleted;
|
|
}
|
|
set
|
|
{
|
|
if (mWorkorderType != WorkorderTypes.Service)
|
|
return;
|
|
|
|
//Attempting to service completed a workorder with broken rules?
|
|
//Can't allow because if we make it read only there is no
|
|
//way to fix the broken rules
|
|
if (!this.IsValid && value == true)
|
|
{
|
|
throw new System.ApplicationException
|
|
(
|
|
LocalizedTextTable.GetLocalizedTextDirect("Workorder.Label.Error.NotCompleteableDueToErrors")
|
|
);
|
|
|
|
}
|
|
|
|
if (bReadOnly)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if (mServiceCompleted != value)
|
|
{
|
|
if (mServiceCompleted == true)
|
|
{
|
|
//User is attempting to set service to NOT completed, make sure they have rights...
|
|
|
|
//case 413 changed rights check from > than read/write to > than readonly
|
|
if (Rights > SecurityLevelTypes.ReadOnly)
|
|
{
|
|
mServiceCompleted = value;
|
|
MarkDirty();
|
|
//set all workorder items to correct status
|
|
this.mWorkorderItems.SetReadOnly(mServiceCompleted);
|
|
}
|
|
else
|
|
{
|
|
throw new System.Security.SecurityException
|
|
(
|
|
string.Format
|
|
(
|
|
LocalizedTextTable.GetLocalizedTextDirect("Error.Security.NotAuthorizedToChange"),
|
|
LocalizedTextTable.GetLocalizedTextDirect("O.WorkorderService")
|
|
)
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mServiceCompleted = value;
|
|
MarkDirty();
|
|
|
|
//set all workorder items to correct status
|
|
this.mWorkorderItems.SetReadOnly(mServiceCompleted);
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Used to close a workorder.
|
|
/// A closed workorder can never be re-opened, so this is a write once setting.
|
|
/// A closed workorder can no longer be edited in any manner permanently.
|
|
///
|
|
/// Closing a work order triggers a whost of tertiary methods that update related objects
|
|
/// this process can not be reversed.
|
|
/// </summary>
|
|
public bool Closed
|
|
{
|
|
get
|
|
{
|
|
return mClosed;
|
|
}
|
|
set
|
|
{
|
|
if (mWorkorderType != WorkorderTypes.Service)
|
|
return;
|
|
|
|
//case 986
|
|
////Attempt to re-open a closed workorder?
|
|
//if(mClosed==true && value==false)
|
|
//{//unclose
|
|
|
|
// throw new System.ApplicationException
|
|
// (
|
|
// LocalizedTextTable.GetLocalizedTextDirect("Workorder.Label.Error.ClosedIsPermanent")
|
|
// );
|
|
//}
|
|
|
|
if (value == true)//is it a close attempt instead of a reopen? case 986
|
|
{
|
|
//Attempting to close a workorder with broken rules?
|
|
//Can't allow because if we make it read only there is no
|
|
//way to fix the broken rules
|
|
if (!this.IsValid)
|
|
{
|
|
throw new System.ApplicationException
|
|
(
|
|
LocalizedTextTable.GetLocalizedTextDirect("Workorder.Label.Error.NotCloseableDueToErrors")
|
|
);
|
|
|
|
}
|
|
|
|
if (this.HasOutstandingLoanItems)
|
|
{
|
|
|
|
throw new System.ApplicationException
|
|
(
|
|
LocalizedTextTable.GetLocalizedTextDirect("Workorder.Label.Error.LoanItemsNotReturned")
|
|
);
|
|
|
|
}
|
|
|
|
//Case 398 (sort of, actually added when didn't fully understand the problem, but this should be here anyway
|
|
//to handle api use of closing a wo when it has parts on order)
|
|
if (this.HasPartRequestsOnOrder)
|
|
{
|
|
throw new System.ApplicationException
|
|
(
|
|
LocalizedTextTable.GetLocalizedTextDirect("Workorder.Label.Error.PartRequestsOnOrder")
|
|
);
|
|
}
|
|
|
|
//Case 398
|
|
if (this.HasPartRequestsUnOrdered)
|
|
{
|
|
throw new System.ApplicationException
|
|
(
|
|
LocalizedTextTable.GetLocalizedTextDirect("Workorder.Label.Error.PartRequestsUnOrdered")
|
|
);
|
|
}
|
|
}
|
|
|
|
if (bReadOnly)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if (mClosed != value)
|
|
{
|
|
mClosed = value;
|
|
MarkDirty();
|
|
|
|
}
|
|
|
|
if (mClosed)
|
|
{
|
|
|
|
//case 6
|
|
//Note that you can only close a service work order that's why there is no
|
|
//specific check here for type of workorder
|
|
if (AyaBizUtils.AllowAutomaticClosedWorkorderStatus && AyaBizUtils.GlobalSettings.WorkorderClosedStatus != Guid.Empty)
|
|
this.WorkorderService.WorkorderStatusID = AyaBizUtils.GlobalSettings.WorkorderClosedStatus;
|
|
//bReadOnly = true;
|
|
//set all workorder items to read only status
|
|
this.mWorkorderItems.SetReadOnly(true);
|
|
|
|
}
|
|
else
|
|
{
|
|
//case 986 - reopening a workorder
|
|
bReadOnly = false;
|
|
this.mWorkorderItems.SetReadOnly(false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//case 3132
|
|
/// <summary>
|
|
/// If a template setting to true will result in the prices being updated to current in the generated order
|
|
/// </summary>
|
|
public bool TemplateFreshPrice
|
|
{
|
|
get
|
|
{
|
|
return mTemplateFreshPrice;
|
|
}
|
|
set
|
|
{
|
|
if (bReadOnly)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if (mTemplateFreshPrice != value)
|
|
{
|
|
mTemplateFreshPrice = value;
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// False if any outstanding parts (not set to "Used in service")
|
|
/// True if all parts are set to used in service.
|
|
/// </summary>
|
|
public bool AllPartsUsed
|
|
{
|
|
get
|
|
{
|
|
//If it's not a service invoice then always return true
|
|
if (mWorkorderType != WorkorderTypes.Service)
|
|
return true;
|
|
|
|
foreach (WorkorderItem wi in this.WorkorderItems)
|
|
{
|
|
foreach (WorkorderItemPart wip in wi.Parts)
|
|
{
|
|
if (wip.Used != true)
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets all parts to used = true on entire workorder
|
|
/// </summary>
|
|
public void SetAllPartsUsed()
|
|
{
|
|
//If it's not a service invoice then nothing to set
|
|
if (mWorkorderType != WorkorderTypes.Service)
|
|
return;
|
|
|
|
foreach (WorkorderItem wi in this.WorkorderItems)
|
|
{
|
|
foreach (WorkorderItemPart wip in wi.Parts)
|
|
{
|
|
|
|
if (wip.Used != true)
|
|
wip.Used = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create a labor object from a scheduled user object to save entry time
|
|
/// </summary>
|
|
/// <param name="SourceWorkorderItemID"></param>
|
|
/// <param name="SourceWorkorderItemScheduledUserID"></param>
|
|
/// <returns></returns>
|
|
public Guid CreateLaborFromScheduledUser(Guid SourceWorkorderItemID, Guid SourceWorkorderItemScheduledUserID)
|
|
{
|
|
if (this.bReadOnly) return Guid.Empty;
|
|
if (mWorkorderType != WorkorderTypes.Service) return Guid.Empty;
|
|
if (mClosed || mServiceCompleted) return Guid.Empty;
|
|
|
|
foreach (WorkorderItem wi in this.WorkorderItems)
|
|
{
|
|
if (wi.ID == SourceWorkorderItemID)
|
|
{
|
|
foreach (WorkorderItemScheduledUser u in wi.ScheduledUsers)
|
|
{
|
|
if (u.ID == SourceWorkorderItemScheduledUserID)
|
|
{
|
|
WorkorderItemLabor wil = wi.Labors.Add(wi);
|
|
wil.UserID = u.UserID;
|
|
wil.ServiceStartDate = u.StartDate;
|
|
wil.ServiceStopDate = u.StopDate;
|
|
wil.ServiceRateID = u.ServiceRateID;
|
|
wil.ServiceRateQuantity = u.EstimatedQuantity;
|
|
return wil.ID;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//records not found
|
|
return Guid.Empty;
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Find the workorder item ID that contains the object passed in
|
|
/// </summary>
|
|
/// <param name="DescendantObjectType">Type of workorder item descendant object</param>
|
|
/// <param name="DescendantID">ID of descendant of workorder item</param>
|
|
/// <returns></returns>
|
|
public Guid GetWorkorderItemIDFromDescendant(RootObjectTypes DescendantObjectType, Guid DescendantID)
|
|
{
|
|
foreach (WorkorderItem wi in this.WorkorderItems)
|
|
{
|
|
switch (DescendantObjectType)
|
|
{
|
|
case RootObjectTypes.WorkorderItemLabor:
|
|
{
|
|
foreach (WorkorderItemLabor d in wi.Labors)
|
|
{ if (d.ID == DescendantID) return wi.ID; }
|
|
}
|
|
break;
|
|
case RootObjectTypes.WorkorderItemMiscExpense:
|
|
{
|
|
foreach (WorkorderItemMiscExpense d in wi.Expenses)
|
|
{ if (d.ID == DescendantID) return wi.ID; }
|
|
}
|
|
break;
|
|
case RootObjectTypes.WorkorderItemOutsideService:
|
|
{
|
|
if (wi.OutsideService.ID == DescendantID) return wi.ID;
|
|
}
|
|
break;
|
|
case RootObjectTypes.WorkorderItemPart:
|
|
{
|
|
foreach (WorkorderItemPart d in wi.Parts)
|
|
{ if (d.ID == DescendantID) return wi.ID; }
|
|
}
|
|
break;
|
|
case RootObjectTypes.WorkorderItemScheduledUser:
|
|
{
|
|
foreach (WorkorderItemScheduledUser d in wi.ScheduledUsers)
|
|
{ if (d.ID == DescendantID) return wi.ID; }
|
|
}
|
|
break;
|
|
case RootObjectTypes.WorkorderItemTravel:
|
|
{
|
|
foreach (WorkorderItemTravel d in wi.Travels)
|
|
{ if (d.ID == DescendantID) return wi.ID; }
|
|
}
|
|
break;
|
|
case RootObjectTypes.WorkorderItemPartRequest://case 1086
|
|
{
|
|
foreach (WorkorderItemPartRequest d in wi.PartRequests)
|
|
{ if (d.ID == DescendantID) return wi.ID; }
|
|
}
|
|
break;
|
|
case RootObjectTypes.WorkorderItemLoan://case 1975
|
|
{
|
|
foreach (WorkorderItemLoan d in wi.Loans)
|
|
{ if (d.ID == DescendantID) return wi.ID; }
|
|
}
|
|
break;
|
|
#if(DEBUG)
|
|
default:
|
|
throw new System.NotSupportedException("Workorder->GetWorkorderItemIDFromDescendant Error - object type not supported: " + DescendantObjectType.ToString());
|
|
#endif
|
|
|
|
|
|
}
|
|
}
|
|
|
|
//Not found
|
|
return Guid.Empty;
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// ID of quote that created this workorder
|
|
/// Set internally when the Quote workorder generates a service
|
|
/// workorder.
|
|
/// </summary>
|
|
public Guid FromQuoteID
|
|
{
|
|
get
|
|
{
|
|
return mFromQuoteID;
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// ID of PreventiveMaintenance that created this workorder
|
|
/// Set internally when the PM workorder generates a service
|
|
/// workorder.
|
|
/// </summary>
|
|
public Guid FromPMID
|
|
{
|
|
get
|
|
{
|
|
return mFromPMID;
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// True if on a service workorder there are any parts with a reserved quantity > 0
|
|
///
|
|
/// Non service workorders (quotes / pm) always return false
|
|
///
|
|
/// Used in Workorder form to determine whether to show the
|
|
/// reserved parts field or not.
|
|
///
|
|
/// Reserved parts are only on workorders generated from P.M. or quotes
|
|
/// when inventory is being used.
|
|
/// </summary>
|
|
public bool HasReservedParts
|
|
{
|
|
get
|
|
{
|
|
//If it's not a service invoice then always return false
|
|
if (mWorkorderType != WorkorderTypes.Service)
|
|
return false;
|
|
|
|
foreach (WorkorderItem wi in this.WorkorderItems)
|
|
{
|
|
foreach (WorkorderItemPart wip in wi.Parts)
|
|
{
|
|
if (wip.QuantityReserved > 0)
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// True means there are loan items not yet returned
|
|
///
|
|
///
|
|
/// </summary>
|
|
public bool HasOutstandingLoanItems
|
|
{
|
|
get
|
|
{
|
|
//If it's not a service invoice then always return false
|
|
if (mWorkorderType != WorkorderTypes.Service)
|
|
return false;
|
|
|
|
foreach (WorkorderItem wi in this.WorkorderItems)
|
|
{
|
|
foreach (WorkorderItemLoan w in wi.Loans)
|
|
{
|
|
if (w.ReturnDate == System.DBNull.Value)
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// True means there are WorkorderItemPartRequest items
|
|
/// still on order and not fully received
|
|
///
|
|
/// Note: if GlobalSettings.UseInventory is set to false this will
|
|
/// always return false
|
|
/// </summary>
|
|
public bool HasPartRequestsOnOrder
|
|
{
|
|
get
|
|
{
|
|
//If it's not a service invoice then always return false
|
|
if (mWorkorderType != WorkorderTypes.Service)
|
|
return false;
|
|
|
|
//case 932
|
|
if (!AyaBizUtils.GlobalSettings.UseInventory)
|
|
return false;
|
|
|
|
foreach (WorkorderItem wi in this.WorkorderItems)
|
|
{
|
|
if (wi.HasPartRequestsOnOrder)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
//Case 398
|
|
/// <summary>
|
|
/// True means there are WorkorderItemPartRequest items
|
|
/// not yet ordered or received
|
|
///
|
|
/// Note: if GlobalSettings.UseInventory is false this will always return false
|
|
///
|
|
/// </summary>
|
|
public bool HasPartRequestsUnOrdered
|
|
{
|
|
get
|
|
{
|
|
//If it's not a service invoice then always return false
|
|
if (mWorkorderType != WorkorderTypes.Service)
|
|
return false;
|
|
|
|
//case 932
|
|
if (!AyaBizUtils.GlobalSettings.UseInventory)
|
|
return false;
|
|
|
|
foreach (WorkorderItem wi in this.WorkorderItems)
|
|
{
|
|
if (wi.HasPartRequestsUnOrdered)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
//Added 25-April-2006 to ensure a serial number can't be selected twice
|
|
/// <summary>
|
|
/// Returns true if the serial number record is selected
|
|
/// anywhere in the workorder item parts collections
|
|
/// </summary>
|
|
/// <param name="PartSerialID">ID of PartSerial record</param>
|
|
/// <returns></returns>
|
|
public bool HasSerialNumberSelected(Guid PartSerialID)
|
|
{
|
|
foreach (WorkorderItem wi in this.WorkorderItems)
|
|
{
|
|
foreach (WorkorderItemPart p in wi.Parts)
|
|
{
|
|
if (p.PartSerialID == PartSerialID)
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
//Added:17-Aug-2006 for wbi
|
|
/// <summary>
|
|
/// A List of Guid's of labor rates selected
|
|
/// anywhere in this work order.
|
|
///
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public System.Collections.Generic.List<Guid> ListOfLaborRatesSelected()
|
|
{
|
|
System.Collections.Generic.List<Guid> l = new System.Collections.Generic.List<Guid>();
|
|
//Add manual items that are inactive but need to be displayed to list
|
|
//from the AllRates
|
|
foreach (WorkorderItem wi in this.WorkorderItems)
|
|
{
|
|
foreach (WorkorderItemLabor wl in wi.Labors)
|
|
{
|
|
if (!l.Contains(wl.ServiceRateID))
|
|
l.Add(wl.ServiceRateID);
|
|
|
|
|
|
}
|
|
}
|
|
return l;
|
|
}
|
|
|
|
//Added:18-Aug-2006 for wbi
|
|
/// <summary>
|
|
/// A List of Guid's of units selected
|
|
/// anywhere in this work order.
|
|
///
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public System.Collections.Generic.List<Guid> ListOfUnitsSelected()
|
|
{
|
|
System.Collections.Generic.List<Guid> l = new System.Collections.Generic.List<Guid>();
|
|
|
|
foreach (WorkorderItem wi in this.WorkorderItems)
|
|
{
|
|
if (wi.UnitID != Guid.Empty && !l.Contains(wi.UnitID))
|
|
l.Add(wi.UnitID);
|
|
}
|
|
return l;
|
|
}
|
|
|
|
//Added:18-Aug-2006 for wbi
|
|
/// <summary>
|
|
/// A List of Guid's of labor users selected
|
|
/// anywhere in this work order.
|
|
///
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public System.Collections.Generic.List<Guid> ListOfLaborUsersSelected()
|
|
{
|
|
System.Collections.Generic.List<Guid> l = new System.Collections.Generic.List<Guid>();
|
|
foreach (WorkorderItem wi in this.WorkorderItems)
|
|
{
|
|
foreach (WorkorderItemLabor wl in wi.Labors)
|
|
{
|
|
if (!l.Contains(wl.UserID))
|
|
l.Add(wl.UserID);
|
|
|
|
|
|
}
|
|
}
|
|
return l;
|
|
}
|
|
|
|
//Added:18-Aug-2006 for wbi
|
|
/// <summary>
|
|
/// A List of Guid's of travel user id's selected
|
|
/// anywhere in this work order.
|
|
///
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public System.Collections.Generic.List<Guid> ListOfTravelUsersSelected()
|
|
{
|
|
System.Collections.Generic.List<Guid> l = new System.Collections.Generic.List<Guid>();
|
|
foreach (WorkorderItem wi in this.WorkorderItems)
|
|
{
|
|
foreach (WorkorderItemTravel wl in wi.Travels)
|
|
{
|
|
if (!l.Contains(wl.UserID))
|
|
l.Add(wl.UserID);
|
|
|
|
|
|
}
|
|
}
|
|
return l;
|
|
}
|
|
|
|
//Added:18-Aug-2006 for wbi
|
|
/// <summary>
|
|
/// A List of Guid's of travel rates selected
|
|
/// anywhere in this work order.
|
|
///
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public System.Collections.Generic.List<Guid> ListOfTravelRatesSelected()
|
|
{
|
|
System.Collections.Generic.List<Guid> l = new System.Collections.Generic.List<Guid>();
|
|
|
|
foreach (WorkorderItem wi in this.WorkorderItems)
|
|
{
|
|
foreach (WorkorderItemTravel wl in wi.Travels)
|
|
{
|
|
if (!l.Contains(wl.TravelRateID))
|
|
l.Add(wl.TravelRateID);
|
|
|
|
|
|
}
|
|
}
|
|
return l;
|
|
}
|
|
|
|
//Added:18-Aug-2006 for wbi
|
|
/// <summary>
|
|
/// A List of Guid's of parts selected
|
|
/// anywhere in this work order.
|
|
///
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public System.Collections.Generic.List<Guid> ListOfPartsSelected()
|
|
{
|
|
System.Collections.Generic.List<Guid> l = new System.Collections.Generic.List<Guid>();
|
|
|
|
foreach (WorkorderItem wi in this.WorkorderItems)
|
|
{
|
|
foreach (WorkorderItemPart wl in wi.Parts)
|
|
{
|
|
if (!l.Contains(wl.PartID))
|
|
l.Add(wl.PartID);
|
|
|
|
|
|
}
|
|
}
|
|
return l;
|
|
}
|
|
|
|
//Case 640
|
|
/// <summary>
|
|
/// A List of Guid's of Part Warehouses selected
|
|
/// anywhere in this work order.
|
|
///
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public System.Collections.Generic.List<Guid> ListOfPartWarehousesSelected()
|
|
{
|
|
System.Collections.Generic.List<Guid> l = new System.Collections.Generic.List<Guid>();
|
|
|
|
foreach (WorkorderItem wi in this.WorkorderItems)
|
|
{
|
|
foreach (WorkorderItemPart wl in wi.Parts)
|
|
{
|
|
if (!l.Contains(wl.PartWarehouseID))
|
|
l.Add(wl.PartWarehouseID);
|
|
|
|
|
|
}
|
|
}
|
|
return l;
|
|
}
|
|
|
|
//Added:22-Aug-2006 for wbi
|
|
/// <summary>
|
|
/// A List of Guid's of Scheduleable users selected
|
|
/// anywhere in this work order.
|
|
///
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public System.Collections.Generic.List<Guid> ListOfScheduledUsersSelected()
|
|
{
|
|
System.Collections.Generic.List<Guid> l = new System.Collections.Generic.List<Guid>();
|
|
foreach (WorkorderItem wi in this.WorkorderItems)
|
|
{
|
|
foreach (WorkorderItemScheduledUser wl in wi.ScheduledUsers)
|
|
{
|
|
if (!l.Contains(wl.UserID))
|
|
l.Add(wl.UserID);
|
|
|
|
|
|
}
|
|
}
|
|
return l;
|
|
}
|
|
|
|
//Added:22-Aug-2006 for wbi
|
|
/// <summary>
|
|
/// A List of Guid's of Scheduleable users suggested labor rates selected
|
|
/// anywhere in this work order.
|
|
///
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public System.Collections.Generic.List<Guid> ListOfScheduledUsersLaborRatesSelected()
|
|
{
|
|
System.Collections.Generic.List<Guid> l = new System.Collections.Generic.List<Guid>();
|
|
|
|
foreach (WorkorderItem wi in this.WorkorderItems)
|
|
{
|
|
foreach (WorkorderItemScheduledUser wl in wi.ScheduledUsers)
|
|
{
|
|
if (!l.Contains(wl.ServiceRateID))
|
|
l.Add(wl.ServiceRateID);
|
|
|
|
|
|
}
|
|
}
|
|
return l;
|
|
}
|
|
|
|
//Added:22-Aug-2006 for wbi
|
|
/// <summary>
|
|
/// A List of Guid's of Misc expense users selected
|
|
/// anywhere in this work order.
|
|
///
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public System.Collections.Generic.List<Guid> ListOfMiscExpenseUsersSelected()
|
|
{
|
|
System.Collections.Generic.List<Guid> l = new System.Collections.Generic.List<Guid>();
|
|
foreach (WorkorderItem wi in this.WorkorderItems)
|
|
{
|
|
foreach (WorkorderItemMiscExpense wl in wi.Expenses)
|
|
{
|
|
if (!l.Contains(wl.UserID))
|
|
l.Add(wl.UserID);
|
|
|
|
|
|
}
|
|
}
|
|
return l;
|
|
}
|
|
|
|
//Added:22-Aug-2006 for wbi
|
|
/// <summary>
|
|
/// A List of Guid's of Loan items selected
|
|
/// anywhere in this work order.
|
|
///
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public System.Collections.Generic.List<Guid> ListOfLoanItemsSelected()
|
|
{
|
|
System.Collections.Generic.List<Guid> l = new System.Collections.Generic.List<Guid>();
|
|
foreach (WorkorderItem wi in this.WorkorderItems)
|
|
{
|
|
foreach (WorkorderItemLoan wl in wi.Loans)
|
|
{
|
|
if (!l.Contains(wl.LoanItemID))
|
|
l.Add(wl.LoanItemID);
|
|
|
|
|
|
}
|
|
}
|
|
return l;
|
|
}
|
|
|
|
|
|
//Added:28-Sept-2006 for wbi
|
|
|
|
/// <summary>
|
|
/// A List of Guid's of serial numbers selected
|
|
/// anywhere in this work order.
|
|
///
|
|
/// Used to prevent duplicate sn selection by presening
|
|
/// user with only available sn's
|
|
/// </summary>
|
|
/// <param name="excludeID">A partserial ID to exclude (not add to this list)
|
|
/// even when present. This is used to not exclude the currently selected
|
|
/// serial number during editing</param>
|
|
/// <returns></returns>
|
|
public System.Collections.Generic.List<Guid> ListOfSerialNumbersSelected(Guid excludeID)
|
|
{
|
|
System.Collections.Generic.List<Guid> l = new System.Collections.Generic.List<Guid>();
|
|
foreach (WorkorderItem wi in this.WorkorderItems)
|
|
{
|
|
foreach (WorkorderItemPart wl in wi.Parts)
|
|
{
|
|
if (!l.Contains(wl.PartSerialID) && wl.PartSerialID != excludeID)
|
|
l.Add(wl.PartSerialID);
|
|
|
|
|
|
}
|
|
}
|
|
return l;
|
|
}
|
|
|
|
|
|
//Case 11
|
|
|
|
/// <summary>
|
|
/// A List of Guid's of workorder item status selected
|
|
/// anywhere in this work orders workorder items collection.
|
|
///
|
|
/// Used to determine which inactive status still need to be added
|
|
/// to list for existing workorders
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public System.Collections.Generic.List<Guid> ListOfWorkorderItemStatusSelected()
|
|
{
|
|
System.Collections.Generic.List<Guid> l = new System.Collections.Generic.List<Guid>();
|
|
foreach (WorkorderItem wi in this.WorkorderItems)
|
|
{
|
|
if (!l.Contains(wi.WorkorderStatusID))
|
|
l.Add(wi.WorkorderStatusID);
|
|
|
|
}
|
|
return l;
|
|
}
|
|
|
|
//case 1121
|
|
/// <summary>
|
|
/// A List of Guid's of workorder item priorities selected
|
|
/// anywhere in this work orders workorder items collection.
|
|
///
|
|
/// Used to determine which inactive priorities still need to be added
|
|
/// to list for existing workorders
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public System.Collections.Generic.List<Guid> ListOfWorkorderItemPrioritiesSelected()
|
|
{
|
|
System.Collections.Generic.List<Guid> l = new System.Collections.Generic.List<Guid>();
|
|
foreach (WorkorderItem wi in this.WorkorderItems)
|
|
{
|
|
if (!l.Contains(wi.PriorityID))
|
|
l.Add(wi.PriorityID);
|
|
}
|
|
return l;
|
|
}
|
|
|
|
//case 1121
|
|
/// <summary>
|
|
/// A List of Guid's of workorder item types selected
|
|
/// anywhere in this work orders workorder items collection.
|
|
///
|
|
/// Used to determine which inactive types still need to be added
|
|
/// to list for existing workorders
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public System.Collections.Generic.List<Guid> ListOfWorkorderItemTypesSelected()
|
|
{
|
|
System.Collections.Generic.List<Guid> l = new System.Collections.Generic.List<Guid>();
|
|
foreach (WorkorderItem wi in this.WorkorderItems)
|
|
{
|
|
if (!l.Contains(wi.TypeID))
|
|
l.Add(wi.TypeID);
|
|
}
|
|
return l;
|
|
}
|
|
|
|
|
|
|
|
//Case 360 tax codes
|
|
/// <summary>
|
|
/// A List of Guid's of tax codes selected
|
|
/// anywhere in this work order.
|
|
///
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public System.Collections.Generic.List<Guid> ListOfTaxCodesSelected()
|
|
{
|
|
System.Collections.Generic.List<Guid> l = new System.Collections.Generic.List<Guid>();
|
|
foreach (WorkorderItem wi in this.WorkorderItems)
|
|
{
|
|
foreach (WorkorderItemLabor wl in wi.Labors)
|
|
{
|
|
if (!l.Contains(wl.TaxRateSaleID))
|
|
l.Add(wl.TaxRateSaleID);
|
|
}
|
|
|
|
foreach (WorkorderItemTravel wt in wi.Travels)
|
|
{
|
|
if (!l.Contains(wt.TaxRateSaleID))
|
|
l.Add(wt.TaxRateSaleID);
|
|
}
|
|
|
|
foreach (WorkorderItemPart wp in wi.Parts)
|
|
{
|
|
if (!l.Contains(wp.TaxPartSaleID))
|
|
l.Add(wp.TaxPartSaleID);
|
|
}
|
|
|
|
foreach (WorkorderItemMiscExpense we in wi.Expenses)
|
|
{
|
|
if (!l.Contains(we.ChargeTaxCodeID))
|
|
l.Add(we.ChargeTaxCodeID);
|
|
}
|
|
|
|
foreach (WorkorderItemLoan wa in wi.Loans)
|
|
{
|
|
if (!l.Contains(wa.TaxCodeID))
|
|
l.Add(wa.TaxCodeID);
|
|
}
|
|
}
|
|
return l;
|
|
}
|
|
|
|
|
|
|
|
//Added 04-Nov-2006 the following bunch of properties for AyaNova WBI
|
|
|
|
/// <summary>
|
|
/// Quick check if workorder is editable or not
|
|
/// Workorder is not editable if insufficient rights to workorder object
|
|
/// Workorder is not editable if closed=true
|
|
/// Workorder is not editable if Servicecompleted=true with the single exception
|
|
/// of ServiceCompleted which can be checked for using the IsServicecompletedEditable property
|
|
/// </summary>
|
|
public bool IsEditable
|
|
{
|
|
get
|
|
{
|
|
if (Rights < SecurityLevelTypes.ReadWrite) return false;
|
|
if (Closed) return false;
|
|
if (WorkorderType == WorkorderTypes.Service && ServiceCompleted) return false;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Confirms if service completed can be changed or not
|
|
/// Use in conjunction with IsEditable to handle
|
|
/// UI enablement of edit controls or to check before
|
|
/// updating through API
|
|
/// </summary>
|
|
public bool IsServiceCompletedEditable
|
|
{
|
|
get
|
|
{
|
|
if (Rights < SecurityLevelTypes.ReadWrite) return false;
|
|
if (Closed) return false;
|
|
return true;
|
|
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Quick check if workorder item is editable or not
|
|
/// First checks if workorder is editable, if yes then checks rights
|
|
/// to WorkorderItem object
|
|
/// </summary>
|
|
public bool IsWorkorderItemEditable//case 1562
|
|
{
|
|
get
|
|
{
|
|
if (!IsEditable) return false;
|
|
if (AyaBizUtils.Right(RootObjectTypes.WorkorderItem) < (int)SecurityLevelTypes.ReadWrite) return false;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Quick check if workorder item is deletable or not
|
|
/// First checks if workorder is editable, if yes then checks rights
|
|
/// to WorkorderItem object
|
|
/// </summary>
|
|
public bool IsWorkorderItemDeletable//case 1562
|
|
{
|
|
get
|
|
{
|
|
if (!IsEditable) return false;
|
|
if (AyaBizUtils.Right(RootObjectTypes.WorkorderItem) < (int)SecurityLevelTypes.ReadWriteDelete) return false;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Quick check if workorder item child is editable or not
|
|
/// First checks IsWorkorderItemEditable, if yes then checks rights
|
|
/// to object type specified
|
|
///
|
|
/// (note that it doesn't check if the type is a valid child object of a workorder item or not, only
|
|
/// what the current users rights to it are.)
|
|
/// </summary>
|
|
public bool IsWorkorderItemChildEditable(RootObjectTypes WorkorderItemChildObjectType)//case 1562
|
|
{
|
|
|
|
if (!IsWorkorderItemEditable) return false;
|
|
if (AyaBizUtils.Right(WorkorderItemChildObjectType) < (int)SecurityLevelTypes.ReadWrite) return false;
|
|
return true;
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Quick check if workorder item child can be deleted.
|
|
/// (note that it doesn't check if the type is a valid child object of a workorder item or not, only
|
|
/// what the current users rights to it are.)
|
|
/// </summary>
|
|
public bool IsWorkorderItemChildDeletable(RootObjectTypes WorkorderItemChildObjectType)//case 1562
|
|
{
|
|
|
|
if (!IsWorkorderItemEditable) return false;
|
|
if (AyaBizUtils.Right(WorkorderItemChildObjectType) < (int)SecurityLevelTypes.ReadWriteDelete) return false;
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Quick check if workorder item child is viewable or not
|
|
/// </summary>
|
|
public bool IsWorkorderItemChildViewable(RootObjectTypes WorkorderItemChildObjectType)//case 1975
|
|
{
|
|
return (AyaBizUtils.Right(WorkorderItemChildObjectType) > (int)SecurityLevelTypes.NoAccess);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Fetches effective rights to workorder item child object
|
|
/// taking into account the rights to the Workorder, the WorkorderItem and
|
|
/// also the state of the workorder (closed/service completed etc)
|
|
/// </summary>
|
|
public SecurityLevelTypes WorkorderItemChildEffectiveRights(RootObjectTypes WorkorderItemChildObjectType)//case 1975
|
|
{
|
|
if (!IsWorkorderItemEditable) return SecurityLevelTypes.ReadOnly;
|
|
return (SecurityLevelTypes)AyaBizUtils.Right(WorkorderItemChildObjectType);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Confirms if Invoice number can be changed or not
|
|
/// Invoice number can only be changed if a workorder is set
|
|
/// to service completed=true and not closed
|
|
/// (and user has sufficient rights)
|
|
/// </summary>
|
|
public bool IsInvoiceNumberEditable
|
|
{
|
|
get
|
|
{
|
|
if (Rights < SecurityLevelTypes.ReadWrite) return false;
|
|
if (Closed) return false;
|
|
if (!ServiceCompleted) return false;
|
|
return true;
|
|
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Confirms if workorder status can be changed or not
|
|
/// </summary>
|
|
public bool IsWorkorderStatusEditable
|
|
{
|
|
get
|
|
{
|
|
if (Rights < SecurityLevelTypes.ReadWrite) return false;
|
|
if (Closed) return false;
|
|
return true;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Confirms if workorder can be signed or not
|
|
/// Signature can only be changed if a workorder is set
|
|
/// to service completed=true and not closed
|
|
/// (and user has sufficient rights)
|
|
/// </summary>
|
|
public bool IsSignable
|
|
{
|
|
get
|
|
{
|
|
if (Rights < SecurityLevelTypes.ReadWrite) return false;
|
|
if (Closed) return false;
|
|
if (!ServiceCompleted) return false;
|
|
return true;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Returns true if workorder type is WorkorderTypes.Service
|
|
/// </summary>
|
|
public bool IsServiceWorkorder
|
|
{
|
|
get
|
|
{
|
|
return (WorkorderType == WorkorderTypes.Service);
|
|
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns true if workorder type is WorkorderTypes.TemplateService
|
|
/// </summary>
|
|
public bool IsServiceTemplateWorkorder
|
|
{
|
|
get
|
|
{
|
|
return (WorkorderType == WorkorderTypes.TemplateService);
|
|
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns true if workorder type is WorkorderTypes.TemplateQuote
|
|
/// </summary>
|
|
public bool IsQuoteTemplateWorkorder
|
|
{
|
|
get
|
|
{
|
|
return (WorkorderType == WorkorderTypes.TemplateQuote);
|
|
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns true if workorder type is WorkorderTypes.TemplatePreventiveMaintenance
|
|
/// </summary>
|
|
public bool IsPreventiveMaintenanceTemplateWorkorder
|
|
{
|
|
get
|
|
{
|
|
return (WorkorderType == WorkorderTypes.TemplatePreventiveMaintenance);
|
|
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns true if workorder type is WorkorderTypes.Service
|
|
/// </summary>
|
|
public bool IsTemplate
|
|
{
|
|
get
|
|
{
|
|
if (WorkorderType == WorkorderTypes.TemplateService ||
|
|
WorkorderType == WorkorderTypes.TemplateQuote ||
|
|
WorkorderType == WorkorderTypes.TemplatePreventiveMaintenance
|
|
) return true;
|
|
return false;
|
|
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns true if sufficient rights and workorder is not closed
|
|
/// or service completed
|
|
/// </summary>
|
|
public bool IsDeleteable
|
|
{
|
|
get
|
|
{
|
|
if (Closed) return false;
|
|
if (Rights < SecurityLevelTypes.ReadWriteDelete) return false;
|
|
if (ServiceCompleted) return false;
|
|
//case 875 - this property is used by wbi only so far and
|
|
//should have had this check originally
|
|
if (HasPartRequestsOnOrder) return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns true if sufficient rights to save workorder and workorder is not closed
|
|
///
|
|
/// </summary>
|
|
public bool IsSaveAllowed
|
|
{
|
|
get
|
|
{
|
|
if (Closed) return false;
|
|
if (Rights < SecurityLevelTypes.ReadWrite) return false;
|
|
return true;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Returns true if sufficient rights to
|
|
/// change close by date
|
|
/// (Object.WorkorderService.CloseByDate)
|
|
/// and workorder is editable
|
|
///
|
|
/// </summary>
|
|
public bool IsCloseByDateAllowed
|
|
{
|
|
get
|
|
{
|
|
if (!IsEditable) return false;
|
|
if (AyaBizUtils.Right("Object.WorkorderService.CloseByDate") < (int)SecurityLevelTypes.ReadWrite) return false;
|
|
return true;
|
|
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Returns true if sufficient rights to
|
|
/// outside service fields
|
|
/// (Object.WorkorderItemOutsideService)
|
|
/// and workorder is editable
|
|
///
|
|
/// </summary>
|
|
public bool IsOutsideServiceAllowed
|
|
{
|
|
get
|
|
{
|
|
if (!IsEditable) return false;
|
|
if (AyaBizUtils.Right("Object.WorkorderItemOutsideService") < (int)SecurityLevelTypes.ReadWrite) return false;
|
|
return true;
|
|
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns true if workorder is closeable
|
|
/// Closeable=sufficient rights and workorder is in a state where
|
|
/// it can be closed.
|
|
///
|
|
/// This is primarily used to enable UI buttons to close the work order.
|
|
/// </summary>
|
|
public bool IsCloseAllowed
|
|
{
|
|
get
|
|
{
|
|
//Case 350 - rewrote this to work properly
|
|
|
|
bool bIsCloseAllowed = true;
|
|
|
|
if (!this.ServiceCompleted)
|
|
bIsCloseAllowed = false;
|
|
|
|
if (bIsCloseAllowed && AyaBizUtils.Right("Object.Workorder.Close") < (int)SecurityLevelTypes.ReadWrite)
|
|
bIsCloseAllowed = false;
|
|
|
|
if (bIsCloseAllowed && Rights < SecurityLevelTypes.ReadWrite)
|
|
bIsCloseAllowed = false;
|
|
|
|
if (bIsCloseAllowed && this.Closed)
|
|
bIsCloseAllowed = false;
|
|
|
|
|
|
return bIsCloseAllowed;
|
|
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Returns true if workorder is reopenable
|
|
/// reopenable=sufficient rights and workorder is in a state where
|
|
/// it can be closed.
|
|
///
|
|
/// This is primarily used to enable UI buttons to reopen the work order.
|
|
/// </summary>
|
|
public bool IsReopenAllowed
|
|
{
|
|
get
|
|
{
|
|
//Case 350 - rewrote this to work properly
|
|
|
|
if (!this.Closed)
|
|
return false;
|
|
|
|
if (!User.IsAdmin && !AyaBizUtils.Lite)//case 1172
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
}
|
|
|
|
//Case 455
|
|
/// <summary>
|
|
/// Diagnostic method used to determine what has been changed
|
|
/// in any node of the workorder hiearchy
|
|
/// (this method is used for development testing and diagnosis
|
|
/// during utility and add-on software development)
|
|
/// </summary>
|
|
public string WhatsDirty
|
|
{
|
|
get
|
|
{
|
|
if (!IsDirty) return "Nothing";
|
|
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
|
|
|
sb.Append("Dirty (changed and unsaved) objects in workorder tree:\r\n");
|
|
|
|
if (base.IsDirty)
|
|
sb.Append("WorkorderHeader\r\n");
|
|
|
|
if ((this.WorkorderType == WorkorderTypes.PreventiveMaintenance || this.WorkorderType == WorkorderTypes.TemplatePreventiveMaintenance) && mWorkorderPreventiveMaintenance.IsDirty)
|
|
sb.Append("WorkorderPreventiveMaintenance\r\n");
|
|
|
|
if ((this.WorkorderType == WorkorderTypes.Quote || this.WorkorderType == WorkorderTypes.TemplateQuote) && mQuote.IsDirty)
|
|
sb.Append("WorkOrderQuote\r\n");
|
|
|
|
if ((this.WorkorderType == WorkorderTypes.Service || this.WorkorderType == WorkorderTypes.TemplateService) && mService.IsDirty)
|
|
sb.Append("WorkorderService\r\n");
|
|
|
|
if (mDocs.IsDirty)
|
|
sb.Append("AssignedDocs\r\n");
|
|
|
|
if (mWorkorderItems.IsDirty)
|
|
{
|
|
sb.Append("The following WorkorderItems are dirty:\r\n");
|
|
foreach (WorkorderItem wi in this.mWorkorderItems)
|
|
{
|
|
if (wi.IsDirty)
|
|
{
|
|
sb.Append("Item: " + wi.TechNotes + "\r\n");
|
|
if (wi.Expenses.IsDirty)
|
|
sb.Append("\tExpenses\r\n");
|
|
if (wi.Labors.IsDirty)
|
|
sb.Append("\tLabors\r\n");
|
|
|
|
if (wi.Loans.IsDirty)
|
|
sb.Append("\tLoans\r\n");
|
|
if (wi.OutsideService.IsDirty)
|
|
sb.Append("\tOutsideService\r\n");
|
|
if (wi.PartRequests.IsDirty)
|
|
sb.Append("\tPartRequests\r\n");
|
|
if (wi.Parts.IsDirty)
|
|
sb.Append("\tParts\r\n");
|
|
if (wi.ScheduledUsers.IsDirty)
|
|
sb.Append("\tScheduledUsers\r\n");
|
|
if (wi.Travels.IsDirty)
|
|
sb.Append("\tTravels\r\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
return sb.ToString();
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Diagnostic method used to determine what business rules are broken
|
|
/// in any node of the workorder hiearchy
|
|
/// (this method is used for development testing and diagnosis
|
|
/// during utility and add-on software development)
|
|
/// </summary>
|
|
public string WhatsBroken
|
|
{
|
|
get
|
|
{
|
|
if (IsValid) return "Nothing";
|
|
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
|
|
|
sb.Append("Objects with broken rules in workorder tree:\r\n");
|
|
|
|
if (!base.IsValid)
|
|
{
|
|
sb.AppendLine("WorkorderHeader broken rules:");
|
|
sb.AppendLine(base.BrokenRulesText);
|
|
}
|
|
|
|
if ((this.WorkorderType == WorkorderTypes.PreventiveMaintenance || this.WorkorderType == WorkorderTypes.TemplatePreventiveMaintenance) && (!mWorkorderPreventiveMaintenance.IsValid))
|
|
sb.AppendLine("WorkorderPreventiveMaintenance\r\n" + mWorkorderPreventiveMaintenance.BrokenRulesText);
|
|
|
|
|
|
if ((this.WorkorderType == WorkorderTypes.Quote || this.WorkorderType == WorkorderTypes.TemplateQuote) && (!mQuote.IsValid))
|
|
sb.AppendLine("WorkOrderQuote\r\n" + mQuote.BrokenRulesText);
|
|
|
|
|
|
if ((this.WorkorderType == WorkorderTypes.Service || this.WorkorderType == WorkorderTypes.TemplateService) && (!mService.IsValid))
|
|
sb.AppendLine("WorkorderService\r\n" + mService.BrokenRulesText);
|
|
|
|
|
|
|
|
foreach (WorkorderItem wi in this.mWorkorderItems)
|
|
{
|
|
if (!wi.IsValid)
|
|
{
|
|
sb.AppendLine("WorkorderItem: " + wi.TechNotes);
|
|
if (!wi.Expenses.IsValid)
|
|
{
|
|
foreach (WorkorderItemMiscExpense i in wi.Expenses)
|
|
{
|
|
if (!i.IsValid)
|
|
sb.AppendLine("\tExpense (name) " + i.Name + "\r\n" + i.BrokenRulesText);
|
|
}
|
|
}
|
|
|
|
if (!wi.Labors.IsValid)
|
|
{
|
|
foreach (WorkorderItemLabor i in wi.Labors)
|
|
{
|
|
if (!i.IsValid)
|
|
sb.AppendLine("\tLabor (start date time)" + i.ServiceStartDate.ToString() + "\r\n" + i.BrokenRulesText);
|
|
}
|
|
}
|
|
|
|
if (!wi.Loans.IsValid)
|
|
{
|
|
foreach (WorkorderItemLoan i in wi.Loans)
|
|
{
|
|
if (!i.IsValid)
|
|
sb.AppendLine("\tLoan (out date) " + i.OutDate.ToString() + "\r\n" + i.BrokenRulesText);
|
|
}
|
|
}
|
|
|
|
|
|
if (!wi.OutsideService.IsValid)
|
|
sb.AppendLine("\tOutsideService\r\n" + wi.OutsideService.BrokenRulesText);
|
|
|
|
if (!wi.PartRequests.IsValid)
|
|
{
|
|
foreach (WorkorderItemPartRequest i in wi.PartRequests)
|
|
{
|
|
if (!i.IsValid)
|
|
sb.AppendLine("\tPartRequest (qty) " + i.Quantity.ToString() + "\r\n" + i.BrokenRulesText);
|
|
}
|
|
}
|
|
|
|
if (!wi.Parts.IsValid)
|
|
{
|
|
foreach (WorkorderItemPart i in wi.Parts)
|
|
{
|
|
if (!i.IsValid)
|
|
sb.AppendLine("\tPart (price - qty) " + i.Price.ToString() + " - " + i.Quantity.ToString() + "\r\n" + i.BrokenRulesText);
|
|
}
|
|
}
|
|
|
|
if (!wi.ScheduledUsers.IsValid)
|
|
{
|
|
foreach (WorkorderItemScheduledUser i in wi.ScheduledUsers)
|
|
{
|
|
if (!i.IsValid)
|
|
sb.AppendLine("\tScheduledUser (start date) " + i.StartDate.ToString() + "\r\n" + i.BrokenRulesText);
|
|
}
|
|
}
|
|
|
|
if (!wi.Travels.IsValid)
|
|
{
|
|
foreach (WorkorderItemTravel i in wi.Travels)
|
|
{
|
|
if (!i.IsValid)
|
|
sb.AppendLine("\tTravel (start date time)" + i.TravelStartDate.ToString() + "\r\n" + i.BrokenRulesText);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
return sb.ToString();
|
|
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Name and address to display on work order form
|
|
/// or template type name if it's a template
|
|
/// </summary>
|
|
public string NameAndAddress
|
|
{
|
|
get
|
|
{
|
|
if (IsTemplate)
|
|
return EnumDescConverter.GetEnumDescription(RootObjectTypeFromWorkorderType(mWorkorderType));
|
|
else
|
|
{
|
|
//Need a selected Client to be able to do this
|
|
//If there isn't one, then bail
|
|
if (ClientID == Guid.Empty)
|
|
{
|
|
return LocalizedTextTable.GetLocalizedTextDirect("Unit.Label.CompanyOwned");
|
|
|
|
}
|
|
|
|
//retrieve the client record
|
|
Client c = Client.GetItemNoMRU(ClientID);
|
|
|
|
StringBuilder b = new StringBuilder();
|
|
b.Append(c.Name);
|
|
b.Append("\r\n");
|
|
b.Append(c.GoToAddress.FullAddress);
|
|
b.Append("\r\n");
|
|
b.Append(c.GetPrimaryContactDefaultContactInfo());
|
|
|
|
if (c.TechNotes != "")
|
|
{
|
|
b.Append(LocalizedTextTable.GetLocalizedTextDirect("Client.Label.TechNotes"));
|
|
b.Append(":\r\n");
|
|
b.Append(c.TechNotes);
|
|
}
|
|
|
|
return b.ToString();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// RootObjectType and id suitable
|
|
/// for FollowUp schedulemarkers
|
|
/// (returns the derived RootObjectType and
|
|
/// accompanying ID. I.E. if this workorder
|
|
/// is a quote then the typeandid is a rootobjectypes.quote
|
|
/// and the id is of the quote object itself, not the workorder)
|
|
/// </summary>
|
|
public TypeAndID FollowTypeAndID
|
|
{
|
|
get
|
|
{
|
|
RootObjectTypes rotype = Workorder.RootObjectTypeFromWorkorderType(this.WorkorderType);
|
|
switch (this.WorkorderType)
|
|
{
|
|
case WorkorderTypes.Quote:
|
|
case WorkorderTypes.TemplateQuote:
|
|
return new TypeAndID(rotype, mQuote.ID);
|
|
|
|
case WorkorderTypes.Service:
|
|
case WorkorderTypes.TemplateService:
|
|
return new TypeAndID(RootObjectTypes.Workorder, mID);
|
|
|
|
case WorkorderTypes.PreventiveMaintenance:
|
|
case WorkorderTypes.TemplatePreventiveMaintenance:
|
|
return new TypeAndID(rotype, this.mWorkorderPreventiveMaintenance.ID);
|
|
default:
|
|
return new TypeAndID(RootObjectTypes.Nothing, Guid.Empty);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Flag - indicates if current user can open the wiki page for this object
|
|
/// See <see cref="WikiPage.ShowWikiLink(RootObjectTypes, Guid)"/> method for details
|
|
///
|
|
/// This is cached for the lifetime of this object
|
|
/// </summary>
|
|
|
|
public bool CanWiki//case 73
|
|
{
|
|
get
|
|
{
|
|
if (!bCanWiki.HasValue)
|
|
bCanWiki = WikiPage.ShowWikiLink(RootObjectType, mID);
|
|
return bCanWiki.Value;
|
|
}
|
|
|
|
}
|
|
//cache the result in case the UI calls this repeatedly
|
|
private bool? bCanWiki = null;
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Flag - indicates if this object has a wikipage or not
|
|
///
|
|
/// </summary>
|
|
public bool HasWiki//case 1630
|
|
{
|
|
get
|
|
{
|
|
return WikiPageExistanceChecker.WikiPageExists(mID);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//case 941
|
|
/// <summary>
|
|
/// Returns the general RootObjectType associated with this workorder's workorder type
|
|
/// </summary>
|
|
public RootObjectTypes RootObjectType
|
|
{
|
|
get
|
|
{
|
|
switch (mWorkorderType)
|
|
{
|
|
case WorkorderTypes.Service:
|
|
return RootObjectTypes.WorkorderService;//case 1387
|
|
|
|
case WorkorderTypes.Quote:
|
|
return RootObjectTypes.WorkorderQuote;
|
|
|
|
case WorkorderTypes.PreventiveMaintenance:
|
|
return RootObjectTypes.WorkorderPreventiveMaintenance;
|
|
|
|
case WorkorderTypes.TemplateService:
|
|
return RootObjectTypes.WorkorderServiceTemplate;
|
|
|
|
case WorkorderTypes.TemplateQuote:
|
|
return RootObjectTypes.WorkorderQuoteTemplate;
|
|
|
|
case WorkorderTypes.TemplatePreventiveMaintenance:
|
|
return RootObjectTypes.WorkorderPreventiveMaintenanceTemplate;
|
|
|
|
default:
|
|
return RootObjectTypes.Nothing;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
//case 866
|
|
/// <summary>
|
|
/// Generate a unit for the current workorder's client
|
|
/// from specified WorkorderItemPartID for current work order
|
|
/// </summary>
|
|
/// <returns>A new unit ready to edit</returns>
|
|
public Unit GenerateUnitFromPart(Guid WorkorderItemPartID)
|
|
{
|
|
WorkorderItemPart src = null;
|
|
foreach (WorkorderItem wi in mWorkorderItems)
|
|
{
|
|
if (src != null) break;
|
|
foreach (WorkorderItemPart wip in wi.Parts)
|
|
{
|
|
if (wip.ID == WorkorderItemPartID)
|
|
{
|
|
src = wip;
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
if (src == null) throw new System.ApplicationException("GenerateUnitFromPart -> WorkorderItemPartID specified not found in Workorder");
|
|
Part p = Part.GetItem(src.PartID);
|
|
Client c = Client.GetItem(mClientID);
|
|
string sSerial = DBUtil.CurrentWorkingDateTime.ToString();
|
|
if (src.PartSerialID != Guid.Empty)
|
|
{
|
|
sSerial = PartSerial.GetSerialNumberFromPartSerialID(src.PartSerialID);
|
|
}
|
|
Unit u = Unit.NewItem();
|
|
u.Active = true;
|
|
u.ClientID = mClientID;
|
|
u.Serial = sSerial;
|
|
u.Description = p.Name;
|
|
Address.Copy(c.GoToAddress, u.GoToAddress);
|
|
u.PurchasedDate = this.mService.ServiceDate;
|
|
u.BoughtHere = true;
|
|
|
|
return u;
|
|
|
|
}
|
|
|
|
//case 866
|
|
/// <summary>
|
|
/// Check to see if current thread user has more than read only rights to Object.Unit
|
|
/// </summary>
|
|
public bool CanGenerateUnit
|
|
{
|
|
get
|
|
{
|
|
return (AyaBizUtils.Right("Object.Unit") > (int)SecurityLevelTypes.ReadOnly);
|
|
}
|
|
}
|
|
|
|
//case 1387
|
|
/// <summary>
|
|
/// Current user's rights to this service workorder / quote / pm / template
|
|
/// </summary>
|
|
public SecurityLevelTypes Rights
|
|
{
|
|
get
|
|
{
|
|
return mRights;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Read only UI convenience method to get the unique visible ID number presented to the user
|
|
/// regardless of type (quote, service, pm, template)
|
|
/// </summary>
|
|
public string uiDisplayVisibleIDNumber
|
|
{
|
|
get
|
|
{
|
|
switch (mWorkorderType)
|
|
{
|
|
case WorkorderTypes.Service:
|
|
case WorkorderTypes.TemplateService:
|
|
return mService.ServiceNumber.ToString();
|
|
|
|
case WorkorderTypes.Quote:
|
|
case WorkorderTypes.TemplateQuote:
|
|
return mQuote.QuoteNumber.ToString();
|
|
|
|
case WorkorderTypes.PreventiveMaintenance:
|
|
case WorkorderTypes.TemplatePreventiveMaintenance:
|
|
return mWorkorderPreventiveMaintenance.PreventiveMaintenanceNumber.ToString();
|
|
|
|
default:
|
|
return "Workorder->uiDisplayVisibleIDNumber unsupported type:" + mWorkorderType.ToString();
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Read only UI convenience method to get the name of the client
|
|
/// </summary>
|
|
public string uiDisplayclientName
|
|
{
|
|
get
|
|
{
|
|
return NameFetcher.GetItem(RootObjectTypes.Client, mClientID, true).RecordName;
|
|
}
|
|
}
|
|
//case 1975
|
|
/// <summary>
|
|
/// Read only UI convenience method to get the status of the workorder regardless of type
|
|
/// (quote, service, pm)
|
|
/// </summary>
|
|
public string uiDisplayHeaderStatus
|
|
{
|
|
get
|
|
{
|
|
switch (mWorkorderType)
|
|
{
|
|
case WorkorderTypes.Service:
|
|
case WorkorderTypes.TemplateService:
|
|
{
|
|
if (mService.WorkorderStatusID == Guid.Empty) return "-";
|
|
return NameFetcher.GetItem(RootObjectTypes.WorkorderStatus, mService.WorkorderStatusID, true).RecordName;
|
|
}
|
|
|
|
case WorkorderTypes.Quote:
|
|
case WorkorderTypes.TemplateQuote:
|
|
{
|
|
return EnumDescConverter.GetEnumDescription(mQuote.QuoteStatus);
|
|
}
|
|
|
|
case WorkorderTypes.PreventiveMaintenance:
|
|
case WorkorderTypes.TemplatePreventiveMaintenance:
|
|
{
|
|
if (mWorkorderPreventiveMaintenance.WorkorderStatusID == Guid.Empty) return "-";
|
|
return NameFetcher.GetItem(RootObjectTypes.WorkorderStatus, mWorkorderPreventiveMaintenance.WorkorderStatusID, true).RecordName;
|
|
}
|
|
|
|
default:
|
|
return "Workorder->uiDisplayHeaderStatus unsupported type:" + mWorkorderType.ToString();
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Read only UI convenience property
|
|
/// true if client for this workorder has popup notes
|
|
/// </summary>
|
|
public bool uiHasPopupNotes
|
|
{
|
|
get
|
|
{
|
|
//insurance
|
|
if (mClientID == Guid.Empty) return false;
|
|
return (!string.IsNullOrWhiteSpace(ClientPopUpNotesFetcher.GetNotes(mClientID)));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Read only UI convenience method to get popup notes for this workorder's client
|
|
/// </summary>
|
|
public string uiPopupNotes
|
|
{
|
|
get
|
|
{
|
|
//insurance
|
|
if (mClientID == Guid.Empty) return string.Empty;
|
|
return ClientPopUpNotesFetcher.GetNotes(mClientID);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Read only UI convenience method to get this workorder's client object
|
|
/// </summary>
|
|
public Client uiClient
|
|
{
|
|
get
|
|
{
|
|
//insurance
|
|
if (mClientID == Guid.Empty) return null;
|
|
return Client.GetItemNoMRU(mClientID);
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Read only UI convenience property
|
|
/// true if there is a contract in effect for this workorder
|
|
/// </summary>
|
|
public bool uiHasContract
|
|
{
|
|
get
|
|
{
|
|
return ContractResolved() != null;
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Read only UI convenienece property
|
|
/// Resolves rights based on users security level as well as
|
|
/// workorder closed / service completed status
|
|
/// </summary>
|
|
public SecurityLevelTypes uiResolvedRights
|
|
{
|
|
get
|
|
{
|
|
SecurityLevelTypes baseLevel = (SecurityLevelTypes)AyaBizUtils.Right(this.RootObjectType);
|
|
//if they have limited rights in any case then just return them as they will be the most
|
|
//limited of all rights
|
|
if (baseLevel < SecurityLevelTypes.ReadWrite)
|
|
return baseLevel;
|
|
if (mServiceCompleted || mClosed)
|
|
return SecurityLevelTypes.ReadOnly;
|
|
|
|
return baseLevel;
|
|
|
|
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Read only UI convenience property
|
|
/// true if this workorder can have a signature
|
|
/// </summary>
|
|
public bool uiCanViewSignaturePanel
|
|
{
|
|
get
|
|
{
|
|
if (mWorkorderType != WorkorderTypes.Service) return false;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
//case 1975
|
|
/// <summary>
|
|
/// Report key to use for summary reports for this workorder type
|
|
/// </summary>
|
|
public string SummaryReportKey
|
|
{
|
|
get
|
|
{
|
|
switch (mWorkorderType)
|
|
{
|
|
case WorkorderTypes.Service:
|
|
return WorkorderServiceList.ReportKey;
|
|
case WorkorderTypes.Quote:
|
|
return WorkorderQuoteList.ReportKey;
|
|
case WorkorderTypes.PreventiveMaintenance:
|
|
return WorkorderPMList.ReportKey;
|
|
default:
|
|
return string.Empty;
|
|
}
|
|
}
|
|
}
|
|
|
|
//case 1975
|
|
/// <summary>
|
|
/// Report key to use for detailed reports for this workorder type
|
|
/// </summary>
|
|
public string DetailedReportKey
|
|
{
|
|
get
|
|
{
|
|
switch (mWorkorderType)
|
|
{
|
|
case WorkorderTypes.Service:
|
|
return WorkorderServiceDetailedReportData.ReportKey;
|
|
case WorkorderTypes.Quote:
|
|
return WorkorderQuoteDetailedReportData.ReportKey;
|
|
case WorkorderTypes.PreventiveMaintenance:
|
|
return WorkorderPMDetailedReportData.ReportKey;
|
|
default:
|
|
return string.Empty;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Read only UI convenience property
|
|
/// true if this workorder can be signed
|
|
/// </summary>
|
|
public bool uiCanSign
|
|
{
|
|
get
|
|
{
|
|
if (mWorkorderType != WorkorderTypes.Service) return false;
|
|
if (mClosed) return false;
|
|
if (mRights < SecurityLevelTypes.ReadWrite) return false;
|
|
if (!mServiceCompleted) return false;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Read only UI convenience property
|
|
/// true if this workorder has a signature
|
|
/// </summary>
|
|
public bool uiHasSignature
|
|
{
|
|
get
|
|
{
|
|
if (mWorkorderType != WorkorderTypes.Service) return false;
|
|
return mService.Signature.HasSignature;
|
|
}
|
|
}
|
|
|
|
|
|
/// <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.Workorder")
|
|
)
|
|
);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region System.object overrides
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public override string ToString()
|
|
{
|
|
return "WO Header" + mID.ToString();
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="obj"></param>
|
|
/// <returns></returns>
|
|
public override bool Equals(Object obj)
|
|
{
|
|
if (obj == null || GetType() != obj.GetType()) return false;
|
|
Workorder c = (Workorder)obj;
|
|
return mID == c.mID;
|
|
}
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public override int GetHashCode()
|
|
{
|
|
return ("WO Header" + mID.ToString()).GetHashCode();
|
|
}
|
|
#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)
|
|
{
|
|
SearchResult sr = new SearchResult();
|
|
|
|
|
|
|
|
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
|
|
|
SafeDataReader dr = null;
|
|
try
|
|
{
|
|
dr = DBUtil.GetReaderFromSQLString(
|
|
|
|
"SELECT aWorkorder.aID, aWorkorder.aCreated, aWorkorder.aModified, " +
|
|
" aWorkorder.aModifier, aWorkorder.aCreator, aWorkorder.ATemplateDescription, " +//Case 670
|
|
" aClient.aName, aClient.aRegionID AS ACLIENTREGION, aWorkorder.aInternalReferenceNumber, " +
|
|
" aWorkorder.aCustomerReferenceNumber, " +
|
|
" aWorkorder.aCustomerContactName, aWorkorder.aSummary, " +
|
|
" aWorkorder.aWorkorderType, aWorkorderQuote.aQuoteNumber, " +
|
|
" aWorkorderService.aServiceNumber, aWorkorderPreventiveMaintenance.aPreventiveMaintenanceNumber " +
|
|
"FROM aWorkorder LEFT OUTER JOIN aWorkorderPreventiveMaintenance " +
|
|
"ON aWorkorder.aID " +
|
|
"= aWorkorderPreventiveMaintenance.aWorkorderID " +
|
|
"LEFT OUTER JOIN aWorkorderService ON aWorkorder.aID " +
|
|
"= aWorkorderService.aWorkorderID LEFT OUTER " +
|
|
"JOIN aWorkorderQuote ON aWorkorder.aID = aWorkorderQuote.aWorkorderID " +
|
|
"LEFT OUTER JOIN aClient " +
|
|
"ON aWorkorder.aClientID = aClient.aID WHERE " +
|
|
"(aWorkorder.aID = @ID)"
|
|
, ID);
|
|
|
|
if (!dr.Read())
|
|
return new SearchResult();//DBUtil.ThrowFetchError("SearchResult for WorkorderID: " + ID.ToString());
|
|
|
|
if (!AyaBizUtils.InYourRegion(dr.GetGuid("ACLIENTREGION"))) return new SearchResult();//case 58
|
|
|
|
WorkorderTypes wotype = (WorkorderTypes)dr.GetInt16("aWorkorderType");
|
|
|
|
if ((SecurityLevelTypes)AyaBizUtils.Right(Workorder.RootObjectTypeFromWorkorderType(wotype)) < SecurityLevelTypes.ReadOnly)
|
|
return new SearchResult();
|
|
|
|
|
|
switch (wotype)
|
|
{
|
|
case WorkorderTypes.PreventiveMaintenance:
|
|
sr.Description = LocalizedTextTable.GetLocalizedTextDirect("O.PreventiveMaintenance") + " " + dr.GetInt32("aPreventiveMaintenanceNumber").ToString() + " " + dr.GetString("aName");
|
|
break;
|
|
case WorkorderTypes.Quote:
|
|
sr.Description = LocalizedTextTable.GetLocalizedTextDirect("O.WorkorderQuote") + " " + dr.GetInt32("aQuoteNumber").ToString() + " " + dr.GetString("aName");
|
|
break;
|
|
case WorkorderTypes.Service:
|
|
sr.Description = LocalizedTextTable.GetLocalizedTextDirect("O.Workorder") + " " + dr.GetInt32("aServiceNumber").ToString() + " " + dr.GetString("aName");
|
|
break;
|
|
case WorkorderTypes.TemplatePreventiveMaintenance:
|
|
sr.Description = LocalizedTextTable.GetLocalizedTextDirect("O.PreventiveMaintenanceTemplate") + " " + dr.GetInt32("aPreventiveMaintenanceNumber").ToString() + " " + dr.GetString("aName");
|
|
break;
|
|
case WorkorderTypes.TemplateQuote:
|
|
sr.Description = LocalizedTextTable.GetLocalizedTextDirect("O.WorkorderQuoteTemplate") + " " + dr.GetInt32("aQuoteNumber").ToString() + " " + dr.GetString("aName");
|
|
break;
|
|
case WorkorderTypes.TemplateService:
|
|
sr.Description = LocalizedTextTable.GetLocalizedTextDirect("O.WorkorderServiceTemplate") + " " + dr.GetInt32("aServiceNumber").ToString() + " " + dr.GetString("aName");
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
sb.Append(sr.Description);
|
|
sb.Append(" ");
|
|
|
|
sb.Append(dr.GetString("aTemplateDescription"));
|
|
sb.Append(" ");
|
|
|
|
sb.Append(dr.GetString("aInternalReferenceNumber"));
|
|
sb.Append(" ");
|
|
sb.Append(dr.GetString("aCustomerReferenceNumber"));
|
|
sb.Append(" ");
|
|
sb.Append(dr.GetString("aCustomerContactName"));
|
|
sb.Append(" ");
|
|
sb.Append(dr.GetString("aSummary"));
|
|
sb.Append(" ");
|
|
|
|
|
|
|
|
|
|
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.Workorder;
|
|
|
|
return sr;
|
|
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Static methods
|
|
|
|
#region New item
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Generate a new workorder / quote / pm from
|
|
/// supplied template and client ID
|
|
/// </summary>
|
|
/// <param name="TemplateID">REquired</param>
|
|
/// <param name="ClientID">Required</param>
|
|
/// <returns></returns>
|
|
public static Workorder NewItem(Guid TemplateID, Guid ClientID)
|
|
{
|
|
if (Guid.Empty == ClientID)
|
|
{
|
|
throw new System.ApplicationException("Workorder->NewItem(ClientID): Required, empty is not a valid value");
|
|
}
|
|
|
|
Workorder t = Workorder.GetItem(TemplateID);
|
|
if (null == t || !t.IsTemplate)
|
|
{
|
|
throw new System.ApplicationException("Workorder->NewItem(TemplateID): TemplateID not found or is not a template");
|
|
}
|
|
Workorder dest = null;
|
|
switch (t.WorkorderType)
|
|
{
|
|
case WorkorderTypes.TemplatePreventiveMaintenance:
|
|
dest = NewItem(WorkorderTypes.PreventiveMaintenance);
|
|
break;
|
|
|
|
case WorkorderTypes.TemplateQuote:
|
|
dest = NewItem(WorkorderTypes.Quote);
|
|
break;
|
|
|
|
case WorkorderTypes.TemplateService:
|
|
dest = NewItem(WorkorderTypes.Service);
|
|
break;
|
|
|
|
}
|
|
|
|
dest.ClientID = ClientID;
|
|
|
|
return CopyTemplateToWorkorder(t, dest);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Create a new workorder overload to accept a root object type rather than a <see cref="WorkorderTypes"/> enum
|
|
/// </summary>
|
|
/// <param name="rootObjectType">Must be a valid workorder type of RootObject, i.e. quote, pm, service</param>
|
|
/// <returns>New workorder</returns>
|
|
public static Workorder NewItem(RootObjectTypes rootObjectType)
|
|
{
|
|
WorkorderTypes wt = WorkorderTypeFromRootObjectType(rootObjectType);
|
|
if (wt == WorkorderTypes.Unknown)
|
|
throw new System.ApplicationException("Workorder->NewItem(RootObjectType) \"" + rootObjectType.ToString() + "\" is not a valid root object type to match a work order");
|
|
|
|
return NewItem(wt);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create new Workorder
|
|
/// </summary>
|
|
/// <returns>Workorder</returns>
|
|
public static Workorder NewItem(WorkorderTypes WorkorderType)
|
|
{
|
|
|
|
|
|
|
|
Workorder c;
|
|
//set rights
|
|
//case 1387
|
|
c = new Workorder();
|
|
c.mRights = (SecurityLevelTypes)AyaBizUtils.Right(Workorder.RootObjectTypeFromWorkorderType(WorkorderType));
|
|
|
|
|
|
if (AyaBizUtils.IsGenerator || c.mRights > SecurityLevelTypes.ReadOnly)
|
|
{
|
|
|
|
//case 3646 removed this block
|
|
////Count the workorders if it's a trial, sb no more than 30
|
|
//if(AyaBizUtils.Trial)
|
|
//{
|
|
|
|
// if(WorkorderCountFetcher.GetItem()>29)
|
|
// throw new TrialException(LocalizedTextTable.GetLocalizedTextDirect("Error.Trial.Restricted"));
|
|
|
|
//}
|
|
|
|
//c = new Workorder();
|
|
c.WorkorderType = WorkorderType;
|
|
switch (WorkorderType)
|
|
{
|
|
case WorkorderTypes.PreventiveMaintenance:
|
|
case WorkorderTypes.TemplatePreventiveMaintenance:
|
|
c.mWorkorderPreventiveMaintenance = WorkorderPreventiveMaintenance.NewItem(c);
|
|
break;
|
|
case WorkorderTypes.Quote:
|
|
case WorkorderTypes.TemplateQuote:
|
|
c.mQuote = WorkorderQuote.NewItem(c);
|
|
break;
|
|
case WorkorderTypes.Service:
|
|
case WorkorderTypes.TemplateService:
|
|
c.mService = WorkorderService.NewItem(c);
|
|
break;
|
|
|
|
}
|
|
//A new workorder *always* has at least one workorder item,
|
|
//so add it now...
|
|
c.WorkorderItems.Add(c);
|
|
return c;
|
|
}
|
|
else
|
|
throw new System.Security.SecurityException(
|
|
string.Format(
|
|
LocalizedTextTable.GetLocalizedTextDirect("Error.Security.NotAuthorizedToCreate"),
|
|
LocalizedTextTable.GetLocalizedTextDirect("O.Workorder")));
|
|
|
|
|
|
|
|
}
|
|
#endregion
|
|
|
|
#region Get by various id's
|
|
/// <summary>
|
|
/// Fetch existing Workorder, track MRU
|
|
/// </summary>
|
|
/// <returns>Workorder</returns>
|
|
/// <param name="_ID">Workorder Guid</param>
|
|
public static Workorder GetItem(Guid _ID)
|
|
{
|
|
return GetItemMRU(_ID, true);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Fetch existing Workorder, don't track in MRU list
|
|
/// </summary>
|
|
/// <returns>Workorder</returns>
|
|
/// <param name="_ID">Workorder Guid</param>
|
|
public static Workorder GetItemNoMRU(Guid _ID)
|
|
{
|
|
return GetItemMRU(_ID, false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determines current user's rights to specific workorder object
|
|
/// be it a quote or service workorder or pm or template etc.
|
|
/// </summary>
|
|
/// <param name="_ID"></param>
|
|
/// <returns></returns>
|
|
public static SecurityLevelTypes RightsToWorkorder(Guid _ID)
|
|
{
|
|
//case 2018 commented out try block so proper error is bubbled up instead of security exception
|
|
//try
|
|
//{
|
|
|
|
//case 3626
|
|
if (_ID == Guid.Empty) return SecurityLevelTypes.NoAccess;
|
|
|
|
return (SecurityLevelTypes)AyaBizUtils.Right(Workorder.RootObjectTypeFromWorkorderType(WorkorderTypeFetcher.GetItem(_ID)));
|
|
//}
|
|
//catch { }
|
|
|
|
//return SecurityLevelTypes.NoAccess;
|
|
}
|
|
/// <summary>
|
|
/// Get item optionally track MRU
|
|
/// See <see cref="UserMRU"/>
|
|
/// </summary>
|
|
/// <param name="_ID"></param>
|
|
/// <param name="TrackMRU"></param>
|
|
/// <returns></returns>
|
|
public static Workorder GetItemMRU(Guid _ID, bool TrackMRU)
|
|
{
|
|
if (ScheduleableUserCountFetcher.GetItem() > AyaBizUtils.GlobalX.ScheduleableUsers)
|
|
{
|
|
throw new System.Security.SecurityException(
|
|
"\r\nLICENSE VIOLATION\r\n\r\n" +
|
|
"AyaNova has detected an attempt to circumvent AyaNova licensing.\r\n\r\n" +
|
|
"This database is licensed for " + AyaBizUtils.GlobalX.ScheduleableUsers.ToString() + " scheduleable users\r\n" +
|
|
"Currently there are " + ScheduleableUserCountFetcher.GetItem().ToString() + " scheduleable users active.\r\n\r\n" +
|
|
"All AyaNova accounts other than Manager have been suspended until\r\n" +
|
|
"the extra scheduleable users that are not licensed are\r\n" +
|
|
"set inactive, removed or changed to non-scheduleable users\r\n" +
|
|
"to bring this database back into license compliance.\r\n\r\n" +
|
|
|
|
"Directly editing the AyaNova database can lead to lost or damaged data\r\n" +
|
|
"Please ensure no one tampers with the AyaNova database in future.\r\n\r\n" +
|
|
"** License violations are logged for the protection of the licensee and licensor **");
|
|
}
|
|
|
|
if (RightsToWorkorder(_ID) > SecurityLevelTypes.NoAccess)
|
|
return (Workorder)DataPortal.Fetch(new Criteria(RootObjectTypes.Workorder, _ID, TrackMRU));
|
|
else
|
|
throw new System.Security.SecurityException(
|
|
string.Format(
|
|
LocalizedTextTable.GetLocalizedTextDirect("Error.Security.NotAuthorizedToRetrieve"),
|
|
LocalizedTextTable.GetLocalizedTextDirect("O.Workorder")));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Fetch existing Workorder by related item ID
|
|
///
|
|
/// Given a rootobjectType and an ID opens the work order that hosts
|
|
/// that rootobject type and ID
|
|
///
|
|
/// (Tracks MRU)
|
|
/// </summary>
|
|
/// <returns>Workorder</returns>
|
|
/// <param name="RootObject">Related object type i.e.</param>
|
|
/// <param name="_ID">Related object from a workorder hiearchy (child/grandchild etc) Guid</param>
|
|
/// <example>
|
|
/// Fetching a work order when you only know the workorderitempart object's ID
|
|
/// <code>
|
|
/// Workorder w = Workorder.GetWorkorderByRelative(RootObjectTypes.WorkorderItemPart, WorkorderItemPartID);
|
|
/// </code>
|
|
/// </example>
|
|
public static Workorder GetWorkorderByRelative(RootObjectTypes RootObject, Guid _ID)
|
|
{
|
|
return GetWorkorderByRelativeMRU(RootObject, _ID, true);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Fetch existing Workorder by related item ID
|
|
///
|
|
/// Given a rootobjectType and an ID opens the work order that hosts
|
|
/// that rootobject type and ID
|
|
///
|
|
/// (Does NOT track MRU)
|
|
/// </summary>
|
|
/// <returns>Workorder</returns>
|
|
/// <param name="RootObject">Related object type i.e.</param>
|
|
/// <param name="_ID">Related object from a workorder hiearchy (child/grandchild etc) Guid</param>
|
|
/// <example>
|
|
/// Fetching a work order when you only know the workorderitempart object's ID
|
|
/// <code>
|
|
/// Workorder w = Workorder.GetWorkorderByRelative(RootObjectTypes.WorkorderItemPart, WorkorderItemPartID);
|
|
/// </code>
|
|
/// </example>
|
|
public static Workorder GetWorkorderByRelativeNoMRU(RootObjectTypes RootObject, Guid _ID)
|
|
{
|
|
return GetWorkorderByRelativeMRU(RootObject, _ID, false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Fetch existing Workorder by related item ID
|
|
///
|
|
/// Given a rootobjectType and an ID opens the work order that hosts
|
|
/// that rootobject type and ID
|
|
///
|
|
/// (Optionally track MRU)
|
|
/// </summary>
|
|
/// <returns>Workorder</returns>
|
|
/// <param name="RootObject">Related object type i.e.</param>
|
|
/// <param name="_ID">Related object from a workorder hiearchy (child/grandchild etc) Guid</param>
|
|
/// <param name="TrackMRU">True for MRU tracking (so it appears in users most recently used list in UI) or false to "stealth" open it with no MRU tracking</param>
|
|
/// <example>
|
|
/// Fetching a work order when you only know the workorderitempart object's ID
|
|
/// <code>
|
|
/// Workorder w = Workorder.GetWorkorderByRelative(RootObjectTypes.WorkorderItemPart, WorkorderItemPartID);
|
|
/// </code>
|
|
/// </example>
|
|
public static Workorder GetWorkorderByRelativeMRU(RootObjectTypes RootObject, Guid _ID, bool TrackMRU)
|
|
{
|
|
switch (RootObject)
|
|
{
|
|
case RootObjectTypes.WorkorderItem:
|
|
break;
|
|
case RootObjectTypes.WorkorderItemLabor:
|
|
break;
|
|
case RootObjectTypes.WorkorderItemTravel:
|
|
break;
|
|
case RootObjectTypes.WorkorderItemScheduledUser:
|
|
break;
|
|
case RootObjectTypes.WorkorderItemOutsideService:
|
|
break;
|
|
case RootObjectTypes.WorkorderItemPartRequest:
|
|
break;
|
|
case RootObjectTypes.WorkorderItemPart:
|
|
break;
|
|
case RootObjectTypes.WorkorderPreventiveMaintenance:
|
|
break;
|
|
case RootObjectTypes.WorkorderQuote:
|
|
break;
|
|
case RootObjectTypes.WorkorderService:
|
|
break;
|
|
case RootObjectTypes.WorkorderItemLoan:
|
|
break;
|
|
case RootObjectTypes.WorkorderItemMiscExpense:
|
|
break;
|
|
default:
|
|
throw new System.NotSupportedException("GetWorkorderByDescendant(" + RootObject.ToString() + ") not supported");
|
|
}
|
|
|
|
Guid gWorkorderID = WorkorderIDFetcher.GetWorkorderByRelative(RootObject, _ID);
|
|
if (RightsToWorkorder(gWorkorderID) > SecurityLevelTypes.NoAccess)
|
|
{
|
|
return (Workorder)DataPortal.Fetch(new Criteria(RootObjectTypes.Workorder, gWorkorderID, TrackMRU));
|
|
}
|
|
else
|
|
throw new System.Security.SecurityException(
|
|
string.Format(
|
|
LocalizedTextTable.GetLocalizedTextDirect("Error.Security.NotAuthorizedToRetrieve"),
|
|
LocalizedTextTable.GetLocalizedTextDirect("O.Workorder")));
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Retrieve internal ID from Workorder Number and type
|
|
/// </summary>
|
|
/// <param name="WorkorderNumber">Service number, Quote number or Preventive maintenance number</param>
|
|
/// <param name="Type">Type of workorder (service, quote, pm)</param>
|
|
/// <returns>Guid of workorder in database or Guid.Empty if not found or input string invalid</returns>
|
|
/// <seealso cref="WorkorderTypes">
|
|
/// See WorkorderTypes enum </seealso>
|
|
public static Guid GetIDFromNumber(string WorkorderNumber, WorkorderTypes Type)
|
|
{
|
|
return WorkorderInternalIDFetcher.GetItem(WorkorderNumber, Type);
|
|
}
|
|
|
|
|
|
|
|
//case 1477
|
|
/// <summary>
|
|
/// Given a workorder's child or grandchild ID returns
|
|
/// that object
|
|
/// </summary>
|
|
/// <typeparam name="T">Type of workorder descendant, i.e. WorkorderItemPart.
|
|
/// Note: this is not a RootObjectType, this is a generic parameter and is the actual object desired (see example).</typeparam>
|
|
/// <param name="ID">Unique GUID ID of descendant object</param>
|
|
/// <returns>The related object</returns>
|
|
/// <example>
|
|
/// Example usage - populating an asp.net combo box with saved grid filters
|
|
/// <code>
|
|
/// WorkorderItemScheduledUser wis = Workorder.GetDescendant<WorkorderItemScheduledUser>(MyWoItemSchedUserObjectID);
|
|
///</code>
|
|
/// </example>
|
|
public static T GetDescendant<T>(Guid ID)
|
|
{
|
|
T bizobject = default(T);
|
|
RootObjectTypes objectType = RootObjectTypes.Nothing;
|
|
|
|
#region Type to RootObjectType
|
|
if (typeof(T) == typeof(WorkorderItem))
|
|
{
|
|
objectType = RootObjectTypes.WorkorderItem;
|
|
}
|
|
else if (typeof(T) == typeof(WorkorderItemLabor))
|
|
{
|
|
objectType = RootObjectTypes.WorkorderItemLabor;
|
|
}
|
|
else if (typeof(T) == typeof(WorkorderItemTravel))
|
|
{
|
|
objectType = RootObjectTypes.WorkorderItemTravel;
|
|
}
|
|
else if (typeof(T) == typeof(WorkorderItemScheduledUser))
|
|
{
|
|
objectType = RootObjectTypes.WorkorderItemScheduledUser;
|
|
}
|
|
else if (typeof(T) == typeof(WorkorderItemOutsideService))
|
|
{
|
|
objectType = RootObjectTypes.WorkorderItemOutsideService;
|
|
}
|
|
else if (typeof(T) == typeof(WorkorderItemPartRequest))
|
|
{
|
|
objectType = RootObjectTypes.WorkorderItemPartRequest;
|
|
}
|
|
else if (typeof(T) == typeof(WorkorderItemPart))
|
|
{
|
|
objectType = RootObjectTypes.WorkorderItemPart;
|
|
}
|
|
else if (typeof(T) == typeof(WorkorderPreventiveMaintenance))
|
|
{
|
|
objectType = RootObjectTypes.WorkorderPreventiveMaintenance;
|
|
}
|
|
else if (typeof(T) == typeof(WorkorderQuote))
|
|
{
|
|
objectType = RootObjectTypes.WorkorderQuote;
|
|
}
|
|
else if (typeof(T) == typeof(WorkorderService))
|
|
{
|
|
objectType = RootObjectTypes.WorkorderService;
|
|
}
|
|
else if (typeof(T) == typeof(WorkorderItemLoan))
|
|
{
|
|
objectType = RootObjectTypes.WorkorderItemLoan;
|
|
}
|
|
else if (typeof(T) == typeof(WorkorderItemMiscExpense))
|
|
{
|
|
objectType = RootObjectTypes.WorkorderItemMiscExpense;
|
|
}
|
|
#endregion
|
|
|
|
#region Check if supported
|
|
switch (objectType)
|
|
{
|
|
case RootObjectTypes.WorkorderItem:
|
|
break;
|
|
case RootObjectTypes.WorkorderItemLabor:
|
|
break;
|
|
case RootObjectTypes.WorkorderItemTravel:
|
|
break;
|
|
case RootObjectTypes.WorkorderItemScheduledUser:
|
|
break;
|
|
case RootObjectTypes.WorkorderItemOutsideService:
|
|
break;
|
|
case RootObjectTypes.WorkorderItemPartRequest:
|
|
break;
|
|
case RootObjectTypes.WorkorderItemPart:
|
|
break;
|
|
case RootObjectTypes.WorkorderItemLoan:
|
|
break;
|
|
case RootObjectTypes.WorkorderItemMiscExpense:
|
|
break;
|
|
default:
|
|
throw new System.NotSupportedException("GetDescendant(" + typeof(T).ToString() + ") not supported");
|
|
}
|
|
#endregion
|
|
|
|
#region Fetch and return
|
|
Workorder w = Workorder.GetWorkorderByRelativeNoMRU(objectType, ID);
|
|
|
|
if (objectType == RootObjectTypes.WorkorderItem)
|
|
return (T)(object)w.WorkorderItems[ID];
|
|
|
|
WorkorderItem wi = w.WorkorderItems[w.GetWorkorderItemIDFromDescendant(objectType, ID)];
|
|
|
|
switch (objectType)
|
|
{
|
|
|
|
case RootObjectTypes.WorkorderItemLabor:
|
|
return (T)(object)wi.Labors[ID.ToString()];
|
|
case RootObjectTypes.WorkorderItemTravel:
|
|
return (T)(object)wi.Travels[ID.ToString()];
|
|
case RootObjectTypes.WorkorderItemScheduledUser:
|
|
return (T)(object)wi.ScheduledUsers[ID.ToString()];
|
|
case RootObjectTypes.WorkorderItemOutsideService:
|
|
return (T)(object)wi.OutsideService;
|
|
case RootObjectTypes.WorkorderItemPartRequest:
|
|
return (T)(object)wi.PartRequests[ID.ToString()];
|
|
case RootObjectTypes.WorkorderItemPart:
|
|
return (T)(object)wi.Parts[ID.ToString()];
|
|
case RootObjectTypes.WorkorderItemLoan:
|
|
return (T)(object)wi.Loans[ID.ToString()];
|
|
case RootObjectTypes.WorkorderItemMiscExpense:
|
|
return (T)(object)wi.Expenses[ID.ToString()];
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
return bizobject;
|
|
|
|
}
|
|
#endregion
|
|
|
|
#region Reopen
|
|
/// <summary>
|
|
/// Reopen closed Workorder
|
|
/// has no effect on already open work orders
|
|
/// </summary>
|
|
/// <param name="_ID">Workorder GUID</param>
|
|
public static void Reopen(Guid _ID)
|
|
{
|
|
|
|
if (RightsToWorkorder(_ID) > SecurityLevelTypes.ReadOnly)
|
|
Workorder.WorkorderReopener.Open(_ID);
|
|
else
|
|
throw new System.Security.SecurityException(
|
|
string.Format(
|
|
LocalizedTextTable.GetLocalizedTextDirect("Error.Security.NotAuthorizedToChange"),
|
|
LocalizedTextTable.GetLocalizedTextDirect("O.Workorder")));
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Template copy-inator
|
|
/// <summary>
|
|
/// Generate a work order from a template
|
|
/// </summary>
|
|
/// <param name="t"></param>
|
|
/// <param name="dest"></param>
|
|
/// <returns></returns>
|
|
private static Workorder CopyTemplateToWorkorder(Workorder t, Workorder dest)
|
|
{
|
|
//get the empty workorderitem that is automatically
|
|
//created on a new workorder so we can delete it later
|
|
Guid DummyWorkorderItemID = dest.WorkorderItems[0].ID;
|
|
|
|
RatePickList rates = null;
|
|
if (dest.ContractResolved() == null)
|
|
rates = RatePickList.GetList(false);
|
|
else
|
|
rates = RatePickList.GetListWithContract(dest.ContractIDResolved());
|
|
|
|
|
|
//WORKORDER HEADER
|
|
dest.CustomerContactName = t.CustomerContactName;
|
|
dest.CustomerReferenceNumber = t.CustomerReferenceNumber;
|
|
dest.InternalReferenceNumber = t.InternalReferenceNumber;
|
|
dest.Onsite = t.Onsite;
|
|
dest.ProjectID = t.ProjectID;
|
|
dest.Summary = t.Summary;
|
|
dest.WorkorderCategoryID = t.WorkorderCategoryID;
|
|
|
|
|
|
//case 3160
|
|
RootObjectTypes destExactType = RootObjectTypes.Nothing;
|
|
|
|
//Workorder type header
|
|
switch (t.WorkorderType)
|
|
{
|
|
case WorkorderTypes.TemplateService:
|
|
{
|
|
//Definitely NOT copy these two see case 588
|
|
//dest.WorkorderService.CloseByDate = t.WorkorderService.CloseByDate;
|
|
//dest.WorkorderService.ServiceDate = t.WorkorderService.ServiceDate;
|
|
dest.WorkorderService.WorkorderStatusID = t.WorkorderService.WorkorderStatusID;
|
|
|
|
destExactType = RootObjectTypes.WorkorderService;
|
|
|
|
}
|
|
break;
|
|
case WorkorderTypes.TemplateQuote:
|
|
{
|
|
dest.WorkorderQuote.Introduction = t.WorkorderQuote.Introduction;
|
|
dest.WorkorderQuote.PreparedByID = t.WorkorderQuote.PreparedByID;
|
|
//case 589
|
|
//dest.WorkorderQuote.QuoteRequestDate = t.WorkorderQuote.QuoteRequestDate;
|
|
dest.WorkorderQuote.QuoteStatus = t.WorkorderQuote.QuoteStatus;
|
|
//case 589
|
|
//dest.WorkorderQuote.ValidUntilDate = t.WorkorderQuote.ValidUntilDate;
|
|
|
|
destExactType = RootObjectTypes.WorkorderQuote;
|
|
|
|
}
|
|
break;
|
|
case WorkorderTypes.TemplatePreventiveMaintenance:
|
|
{
|
|
dest.WorkorderPreventiveMaintenance.Active = false;//for protection
|
|
//case 778
|
|
dest.WorkorderPreventiveMaintenance.DayOfTheWeek = t.WorkorderPreventiveMaintenance.DayOfTheWeek;
|
|
dest.WorkorderPreventiveMaintenance.GenerateSpan = t.WorkorderPreventiveMaintenance.GenerateSpan;
|
|
dest.WorkorderPreventiveMaintenance.GenerateSpanUnit = t.WorkorderPreventiveMaintenance.GenerateSpanUnit;
|
|
//Case 590
|
|
//dest.WorkorderPreventiveMaintenance.NextServiceDate = t.WorkorderPreventiveMaintenance.NextServiceDate;
|
|
// dest.WorkorderPreventiveMaintenance.StopGeneratingDate = t.WorkorderPreventiveMaintenance.StopGeneratingDate;
|
|
dest.WorkorderPreventiveMaintenance.ThresholdSpan = t.WorkorderPreventiveMaintenance.ThresholdSpan;
|
|
dest.WorkorderPreventiveMaintenance.ThresholdSpanUnit = t.WorkorderPreventiveMaintenance.ThresholdSpanUnit;
|
|
dest.WorkorderPreventiveMaintenance.WorkorderStatusID = t.WorkorderPreventiveMaintenance.WorkorderStatusID;
|
|
|
|
|
|
destExactType = RootObjectTypes.WorkorderPreventiveMaintenance;
|
|
|
|
}
|
|
break;
|
|
}
|
|
|
|
|
|
//WORKORDERITEMS
|
|
foreach (WorkorderItem wisource in t.WorkorderItems)
|
|
{
|
|
WorkorderItem widest = dest.WorkorderItems.Add(dest);
|
|
widest.Custom0 = wisource.Custom0;
|
|
widest.Custom1 = wisource.Custom1;
|
|
widest.Custom2 = wisource.Custom2;
|
|
widest.Custom3 = wisource.Custom3;
|
|
widest.Custom4 = wisource.Custom4;
|
|
widest.Custom5 = wisource.Custom5;
|
|
widest.Custom6 = wisource.Custom6;
|
|
widest.Custom7 = wisource.Custom7;
|
|
widest.Custom8 = wisource.Custom8;
|
|
widest.Custom9 = wisource.Custom9;
|
|
widest.PriorityID = wisource.PriorityID;
|
|
//Case 588
|
|
//widest.RequestDate = wisource.RequestDate;
|
|
widest.Summary = wisource.Summary;
|
|
widest.TechNotes = wisource.TechNotes;
|
|
widest.TypeID = wisource.TypeID;
|
|
//widest.UnitID = wisource.UnitID;
|
|
//widest.WarrantyService = wisource.WarrantyService;
|
|
widest.WorkorderItemUnitServiceTypeID = wisource.WorkorderItemUnitServiceTypeID;
|
|
widest.WorkorderStatusID = wisource.WorkorderStatusID;
|
|
|
|
//case 3132
|
|
//cache part prices if required
|
|
PartPickList partList = null;
|
|
if (t.mTemplateFreshPrice)
|
|
partList = PartPickList.GetListFromIDList(t.ListOfPartsSelected());
|
|
|
|
//PARTS
|
|
foreach (WorkorderItemPart partsource in wisource.Parts)
|
|
{
|
|
WorkorderItemPart partdest = widest.Parts.Add(widest);
|
|
|
|
|
|
partdest.Description = partsource.Description;
|
|
partdest.Discount = partsource.Discount;
|
|
partdest.DiscountType = partsource.DiscountType;
|
|
partdest.PartID = partsource.PartID;
|
|
partdest.PartWarehouseID = partsource.PartWarehouseID;
|
|
|
|
|
|
//case 3132: update prices here if the template says to do that
|
|
if (t.mTemplateFreshPrice)
|
|
{
|
|
if (partdest.PartID != Guid.Empty)
|
|
{
|
|
partdest.Cost = partList[partdest.PartID].Cost;
|
|
partdest.Price = partList[partdest.PartID].Retail;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
partdest.Cost = partsource.Cost;
|
|
partdest.Price = partsource.Price;
|
|
}
|
|
|
|
|
|
|
|
if (AyaBizUtils.GlobalSettings.UseInventory)
|
|
{
|
|
//case 2076
|
|
if (dest.IsServiceWorkorder)
|
|
{
|
|
partdest.QuantityReserved = partsource.Quantity;
|
|
partdest.Quantity = 0;
|
|
}
|
|
else
|
|
{
|
|
partdest.Quantity = partsource.Quantity;
|
|
}
|
|
|
|
}
|
|
else
|
|
partdest.Quantity = partsource.Quantity;
|
|
|
|
partdest.TaxPartSaleID = partsource.TaxPartSaleID;
|
|
|
|
|
|
}
|
|
|
|
//**********************************************************
|
|
//Part requests would be here if copying a service workorder
|
|
//**********************************************************
|
|
|
|
//SCHEDULED USERS
|
|
foreach (WorkorderItemScheduledUser usersource in wisource.ScheduledUsers)
|
|
{
|
|
WorkorderItemScheduledUser userdest = widest.ScheduledUsers.Add(widest);
|
|
//Case 862 Case 890
|
|
if (usersource.ServiceRateID != Guid.Empty && rates.Contains(usersource.ServiceRateID) && rates[usersource.ServiceRateID].Selectable)
|
|
userdest.ServiceRateID = usersource.ServiceRateID;
|
|
userdest.EstimatedQuantity = usersource.EstimatedQuantity;
|
|
//Case 588
|
|
//userdest.StartDate = usersource.StartDate;
|
|
//userdest.StopDate = usersource.StopDate;
|
|
userdest.UserID = usersource.UserID;
|
|
}
|
|
|
|
//LABOR
|
|
foreach (WorkorderItemLabor laborsource in wisource.Labors)
|
|
{
|
|
WorkorderItemLabor labordest = widest.Labors.Add(widest);
|
|
labordest.NoChargeQuantity = laborsource.NoChargeQuantity;
|
|
labordest.ServiceDetails = laborsource.ServiceDetails;
|
|
|
|
//Case 862 Case 890
|
|
if (laborsource.ServiceRateID != Guid.Empty && rates.Contains(laborsource.ServiceRateID) && rates[laborsource.ServiceRateID].Selectable)
|
|
labordest.ServiceRateID = laborsource.ServiceRateID;
|
|
|
|
labordest.ServiceRateQuantity = laborsource.ServiceRateQuantity;
|
|
|
|
//Case 588
|
|
//labordest.ServiceStartDate = laborsource.ServiceStartDate;
|
|
//labordest.ServiceStopDate = laborsource.ServiceStopDate;
|
|
labordest.TaxRateSaleID = laborsource.TaxRateSaleID;
|
|
labordest.UserID = laborsource.UserID;
|
|
}
|
|
|
|
//**********************************************************
|
|
//Expenses if service workorder
|
|
//**********************************************************
|
|
if (t.IsServiceTemplateWorkorder)
|
|
{
|
|
foreach (WorkorderItemMiscExpense e in wisource.Expenses)
|
|
{
|
|
WorkorderItemMiscExpense exdest = widest.Expenses.Add(widest);
|
|
exdest.ChargeAmount = e.ChargeAmount;
|
|
exdest.ChargeTaxCodeID = e.ChargeTaxCodeID;
|
|
exdest.ChargeToClient = e.ChargeToClient;
|
|
exdest.Description = e.Description;
|
|
exdest.Name = e.Name;
|
|
exdest.ReimburseUser = e.ReimburseUser;
|
|
exdest.TaxPaid = e.TaxPaid;
|
|
exdest.TotalCost = e.TotalCost;
|
|
exdest.UserID = e.UserID;
|
|
//exdest.WorkorderItemID = e.WorkorderItemID;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//**********************************************************
|
|
//Loans for a service workorder (but we've deced they won't be templatizable)
|
|
//**********************************************************
|
|
|
|
//TRAVEL
|
|
foreach (WorkorderItemTravel travelsource in wisource.Travels)
|
|
{
|
|
WorkorderItemTravel traveldest = widest.Travels.Add(widest);
|
|
traveldest.TravelDetails = travelsource.TravelDetails;
|
|
//Case 862 Case 890
|
|
if (travelsource.TravelRateID != Guid.Empty && rates.Contains(travelsource.TravelRateID) && rates[travelsource.TravelRateID].Selectable)
|
|
traveldest.TravelRateID = travelsource.TravelRateID;
|
|
traveldest.TravelRateQuantity = travelsource.TravelRateQuantity;
|
|
//Case 588
|
|
//traveldest.TravelStartDate = travelsource.TravelStartDate;
|
|
//traveldest.TravelStopDate = travelsource.TravelStopDate;
|
|
traveldest.TaxRateSaleID = travelsource.TaxRateSaleID;
|
|
traveldest.UserID = travelsource.UserID;
|
|
traveldest.Distance = travelsource.Distance;
|
|
traveldest.Notes = travelsource.Notes;
|
|
traveldest.NoChargeQuantity = travelsource.NoChargeQuantity;
|
|
}
|
|
|
|
|
|
|
|
//TASKS
|
|
foreach (WorkorderItemTask tasksource in wisource.Tasks)
|
|
{
|
|
WorkorderItemTask taskdest = widest.Tasks.Add(widest);
|
|
taskdest.TaskGroupID = tasksource.TaskGroupID;
|
|
taskdest.TaskID = tasksource.TaskID;
|
|
|
|
}
|
|
|
|
//**********************************************************
|
|
//Outside service would be here if copying a service workorder
|
|
//**********************************************************
|
|
|
|
}//foreach workorderitem loop
|
|
|
|
|
|
|
|
////Delete the auto-created dummy workorder item
|
|
////if there are more than it present
|
|
if (dest.WorkorderItems.Count > 1)
|
|
dest.WorkorderItems.RemoveAt(0);
|
|
|
|
//case 3160
|
|
//copy wikipage from template to created wo
|
|
if (t.HasWiki)
|
|
{
|
|
WikiPage.DuplicateItem(new TypeAndID(RootObjectTypes.Workorder, t.ID), new TypeAndID(destExactType, dest.ID));
|
|
}
|
|
|
|
return dest;
|
|
}
|
|
|
|
#endregion template copyinator
|
|
|
|
#region Generate service workorder from quote
|
|
/// <summary>
|
|
/// Generates a service workorder from a Quote type Workorder
|
|
/// </summary>
|
|
/// <param name="SourceWorkorderID">ID of Quote</param>
|
|
/// <returns>A new service workorder</returns>
|
|
public static Workorder NewServiceWorkorderFromQuote(Guid SourceWorkorderID)
|
|
{
|
|
|
|
//revamped for case 1387 now calls the one single static newitem method
|
|
|
|
//Fetch the source workorder and verify it's a quote
|
|
Workorder source = Workorder.GetItemNoMRU(SourceWorkorderID);
|
|
if (source.WorkorderType != WorkorderTypes.Quote)
|
|
throw new NotSupportedException(LocalizedTextTable.GetLocalizedTextDirect("Workorder.Label.Error.SourceInvalidType"));
|
|
|
|
//Ok, so far so goo, create the new one
|
|
bool bUseInventory = AyaBizUtils.GlobalSettings.UseInventory;
|
|
|
|
|
|
//NOTE: THIS DOES *NOT* CALL THE SHARED NEWITEM METHOD IN WORKORDER
|
|
//Workorder dest = new Workorder();
|
|
//dest.WorkorderType=WorkorderTypes.Service;
|
|
//dest.mService=WorkorderService.NewItem(dest);
|
|
|
|
Workorder dest = Workorder.NewItem(WorkorderTypes.Service);
|
|
|
|
//get the empty workorderitem that is automatically
|
|
//created on a new workorder so we can delete it later
|
|
Guid DummyWorkorderItemID = dest.WorkorderItems[0].ID;
|
|
|
|
//WORKORDER HEADER
|
|
dest.ClientID = source.ClientID;
|
|
// dest.Custom0=source.Custom0;
|
|
// dest.Custom1=source.Custom1;
|
|
// dest.Custom2=source.Custom2;
|
|
// dest.Custom3=source.Custom3;
|
|
// dest.Custom4=source.Custom4;
|
|
// dest.Custom5=source.Custom5;
|
|
// dest.Custom6=source.Custom6;
|
|
// dest.Custom7=source.Custom7;
|
|
// dest.Custom8=source.Custom8;
|
|
// dest.Custom9=source.Custom9;
|
|
dest.CustomerContactName = source.CustomerContactName;
|
|
dest.CustomerReferenceNumber = source.CustomerReferenceNumber;
|
|
dest.mFromQuoteID = source.WorkorderQuote.ID;
|
|
dest.InternalReferenceNumber = source.InternalReferenceNumber;
|
|
dest.Onsite = source.Onsite;
|
|
dest.ProjectID = source.ProjectID;
|
|
//dest.RegionID=source.RegionID;
|
|
dest.Summary = source.Summary;
|
|
dest.WorkorderCategoryID = source.WorkorderCategoryID;
|
|
|
|
//WORKORDERITEMS
|
|
foreach (WorkorderItem wisource in source.WorkorderItems)
|
|
{
|
|
WorkorderItem widest = dest.WorkorderItems.Add(dest);
|
|
widest.Custom0 = wisource.Custom0;
|
|
widest.Custom1 = wisource.Custom1;
|
|
widest.Custom2 = wisource.Custom2;
|
|
widest.Custom3 = wisource.Custom3;
|
|
widest.Custom4 = wisource.Custom4;
|
|
widest.Custom5 = wisource.Custom5;
|
|
widest.Custom6 = wisource.Custom6;
|
|
widest.Custom7 = wisource.Custom7;
|
|
widest.Custom8 = wisource.Custom8;
|
|
widest.Custom9 = wisource.Custom9;
|
|
widest.PriorityID = wisource.PriorityID;
|
|
widest.RequestDate = wisource.RequestDate;
|
|
widest.Summary = wisource.Summary;
|
|
widest.TechNotes = wisource.TechNotes;
|
|
widest.TypeID = wisource.TypeID;
|
|
widest.UnitID = wisource.UnitID;
|
|
widest.WarrantyService = wisource.WarrantyService;
|
|
widest.WorkorderItemUnitServiceTypeID = wisource.WorkorderItemUnitServiceTypeID;
|
|
widest.WorkorderStatusID = wisource.WorkorderStatusID;
|
|
|
|
//PARTS
|
|
foreach (WorkorderItemPart partsource in wisource.Parts)
|
|
{
|
|
WorkorderItemPart partdest = widest.Parts.Add(widest);
|
|
partdest.Cost = partsource.Cost;
|
|
partdest.Description = partsource.Description;
|
|
partdest.Discount = partsource.Discount;
|
|
partdest.DiscountType = partsource.DiscountType;
|
|
partdest.PartID = partsource.PartID;
|
|
partdest.PartWarehouseID = partsource.PartWarehouseID;
|
|
partdest.Price = partsource.Price;
|
|
if (bUseInventory)
|
|
{
|
|
partdest.QuantityReserved = partsource.Quantity;
|
|
partdest.Quantity = 0;
|
|
}
|
|
else
|
|
partdest.Quantity = partsource.Quantity;
|
|
partdest.TaxPartSaleID = partsource.TaxPartSaleID;
|
|
|
|
|
|
}
|
|
|
|
//**********************************************************
|
|
//Part requests would be here if copying a service workorder
|
|
//**********************************************************
|
|
|
|
//SCHEDULED USERS
|
|
foreach (WorkorderItemScheduledUser usersource in wisource.ScheduledUsers)
|
|
{
|
|
WorkorderItemScheduledUser userdest = widest.ScheduledUsers.Add(widest);
|
|
userdest.EstimatedQuantity = usersource.EstimatedQuantity;
|
|
userdest.ServiceRateID = usersource.ServiceRateID;
|
|
userdest.StartDate = usersource.StartDate;
|
|
userdest.StopDate = usersource.StopDate;
|
|
userdest.UserID = usersource.UserID;
|
|
|
|
}
|
|
|
|
//LABOR
|
|
foreach (WorkorderItemLabor laborsource in wisource.Labors)
|
|
{
|
|
WorkorderItemLabor labordest = widest.Labors.Add(widest);
|
|
labordest.NoChargeQuantity = laborsource.NoChargeQuantity;
|
|
labordest.ServiceDetails = laborsource.ServiceDetails;
|
|
labordest.ServiceRateID = laborsource.ServiceRateID;
|
|
labordest.ServiceRateQuantity = laborsource.ServiceRateQuantity;
|
|
labordest.ServiceStartDate = laborsource.ServiceStartDate;
|
|
labordest.ServiceStopDate = laborsource.ServiceStopDate;
|
|
labordest.TaxRateSaleID = laborsource.TaxRateSaleID;
|
|
labordest.UserID = laborsource.UserID;
|
|
|
|
}
|
|
|
|
//**********************************************************
|
|
//Expenses would be here if copying a service workorder
|
|
//**********************************************************
|
|
|
|
|
|
//**********************************************************
|
|
//Loans would be here if copying a service workorder
|
|
//**********************************************************
|
|
|
|
//TRAVEL
|
|
foreach (WorkorderItemTravel travelsource in wisource.Travels)
|
|
{
|
|
WorkorderItemTravel traveldest = widest.Travels.Add(widest);
|
|
traveldest.TravelDetails = travelsource.TravelDetails;
|
|
traveldest.TravelRateID = travelsource.TravelRateID;
|
|
traveldest.TravelRateQuantity = travelsource.TravelRateQuantity;
|
|
traveldest.TravelStartDate = travelsource.TravelStartDate;
|
|
traveldest.TravelStopDate = travelsource.TravelStopDate;
|
|
traveldest.TaxRateSaleID = travelsource.TaxRateSaleID;
|
|
traveldest.UserID = travelsource.UserID;
|
|
traveldest.Distance = travelsource.Distance;
|
|
traveldest.Notes = travelsource.Notes;
|
|
traveldest.NoChargeQuantity = travelsource.NoChargeQuantity;
|
|
}
|
|
|
|
|
|
|
|
//TASKS
|
|
foreach (WorkorderItemTask tasksource in wisource.Tasks)
|
|
{
|
|
WorkorderItemTask taskdest = widest.Tasks.Add(widest);
|
|
taskdest.TaskGroupID = tasksource.TaskGroupID;
|
|
taskdest.TaskID = tasksource.TaskID;
|
|
|
|
}
|
|
|
|
//**********************************************************
|
|
//Outside service would be here if copying a service workorder
|
|
//**********************************************************
|
|
|
|
}//foreach workorderitem loop
|
|
|
|
|
|
//case 1387
|
|
//Delete the auto-created dummy workorder item
|
|
//if there are more than it present
|
|
if (dest.WorkorderItems.Count > 1)
|
|
dest.WorkorderItems.RemoveAt(0);
|
|
|
|
//case 1630
|
|
//copy wikipage from quote to service workorder
|
|
if (dest.CanWiki && source.HasWiki)
|
|
{
|
|
try
|
|
{
|
|
WikiPage wpSource = WikiPage.GetItem(new TypeAndID(RootObjectTypes.WorkorderQuote, source.ID));
|
|
WikiPage wpDest = WikiPage.GetItem(new TypeAndID(RootObjectTypes.WorkorderService, dest.ID));
|
|
wpDest.SetContent(wpSource.GetContent());
|
|
wpDest.Save();
|
|
}
|
|
catch { };
|
|
|
|
}
|
|
|
|
return dest;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
#endregion
|
|
|
|
#region Generate service workorder from PM
|
|
/// <summary>
|
|
/// Generates a service workorder from a PM type Workorder
|
|
/// </summary>
|
|
/// <param name="SourceWorkorderID">ID of PM</param>
|
|
/// <returns>A new service workorder</returns>
|
|
public static Workorder NewServiceWorkorderFromPM(Guid SourceWorkorderID)
|
|
{
|
|
//Fetch the source workorder and verify it's a PM
|
|
Workorder source = Workorder.GetItemNoMRU(SourceWorkorderID);
|
|
if (source.WorkorderType != WorkorderTypes.PreventiveMaintenance)
|
|
throw new NotSupportedException(LocalizedTextTable.GetLocalizedTextDirect("Workorder.Label.Error.SourceInvalidType"));
|
|
|
|
//if it's inactive then there is nothing to Process
|
|
//this is a backstop, the list the pm is being generated off of
|
|
//should have already selected only active items that have not reached their
|
|
//expiry date
|
|
if (source.WorkorderPreventiveMaintenance.Active == false)
|
|
{
|
|
throw new System.ApplicationException("NewServiceWorkorderFromPM: source PM workorder is not active");
|
|
}
|
|
|
|
if (source.WorkorderPreventiveMaintenance.StopGeneratingDate != System.DBNull.Value &&
|
|
source.WorkorderPreventiveMaintenance.dtStopGeneratingDate < DBUtil.CurrentWorkingDateTime)
|
|
{
|
|
throw new System.ApplicationException("NewServiceWorkorderFromPM: source PM workorder is past StopGeneratingDate");
|
|
}
|
|
|
|
//Ok, so far so good, create the new one
|
|
bool bUseInventory = AyaBizUtils.GlobalSettings.UseInventory;
|
|
|
|
//case 1387
|
|
Workorder dest = Workorder.NewItem(WorkorderTypes.Service);
|
|
|
|
////NOTE: THIS DOESN'T CALL THE SHARED NEW ITEM METHOD
|
|
//Workorder dest = new Workorder();
|
|
//dest.WorkorderType=WorkorderTypes.Service;
|
|
//dest.mService=WorkorderService.NewItem(dest);
|
|
|
|
#region copy workorder data
|
|
|
|
//WORKORDER HEADER
|
|
dest.ClientID = source.ClientID;
|
|
dest.CustomerContactName = source.CustomerContactName;
|
|
dest.CustomerReferenceNumber = source.CustomerReferenceNumber;
|
|
dest.mFromPMID = source.WorkorderPreventiveMaintenance.ID;
|
|
dest.InternalReferenceNumber = source.InternalReferenceNumber;
|
|
dest.Onsite = source.Onsite;
|
|
dest.ProjectID = source.ProjectID;
|
|
//dest.RegionID=source.RegionID;
|
|
dest.Summary = source.Summary;
|
|
dest.WorkorderCategoryID = source.WorkorderCategoryID;
|
|
|
|
//PM SPECIFIC
|
|
dest.WorkorderService.WorkorderStatusID = source.WorkorderPreventiveMaintenance.WorkorderStatusID;
|
|
//Date stuff (note that date is assumed to have been advanced the last time a workorder was
|
|
//generated off the pm (see bottom of this method for that))
|
|
dest.WorkorderService.ServiceDate = source.WorkorderPreventiveMaintenance.NextServiceDate;
|
|
|
|
|
|
//WORKORDERITEMS
|
|
foreach (WorkorderItem wisource in source.WorkorderItems)
|
|
{
|
|
WorkorderItem widest = dest.WorkorderItems.Add(dest);
|
|
widest.Custom0 = wisource.Custom0;
|
|
widest.Custom1 = wisource.Custom1;
|
|
widest.Custom2 = wisource.Custom2;
|
|
widest.Custom3 = wisource.Custom3;
|
|
widest.Custom4 = wisource.Custom4;
|
|
widest.Custom5 = wisource.Custom5;
|
|
widest.Custom6 = wisource.Custom6;
|
|
widest.Custom7 = wisource.Custom7;
|
|
widest.Custom8 = wisource.Custom8;
|
|
widest.Custom9 = wisource.Custom9;
|
|
widest.PriorityID = wisource.PriorityID;
|
|
widest.RequestDate = wisource.RequestDate;
|
|
widest.Summary = wisource.Summary;
|
|
widest.TechNotes = wisource.TechNotes;
|
|
widest.TypeID = wisource.TypeID;
|
|
widest.UnitID = wisource.UnitID;
|
|
widest.WarrantyService = wisource.WarrantyService;
|
|
widest.WorkorderItemUnitServiceTypeID = wisource.WorkorderItemUnitServiceTypeID;
|
|
widest.WorkorderStatusID = wisource.WorkorderStatusID;
|
|
|
|
//PARTS
|
|
foreach (WorkorderItemPart partsource in wisource.Parts)
|
|
{
|
|
WorkorderItemPart partdest = widest.Parts.Add(widest);
|
|
partdest.Cost = partsource.Cost;
|
|
partdest.Description = partsource.Description;
|
|
partdest.Discount = partsource.Discount;
|
|
partdest.DiscountType = partsource.DiscountType;
|
|
partdest.PartID = partsource.PartID;
|
|
partdest.PartWarehouseID = partsource.PartWarehouseID;
|
|
partdest.Price = partsource.Price;
|
|
if (bUseInventory)
|
|
{
|
|
partdest.QuantityReserved = partsource.Quantity;
|
|
partdest.Quantity = 0;
|
|
}
|
|
else
|
|
partdest.Quantity = partsource.Quantity;
|
|
partdest.TaxPartSaleID = partsource.TaxPartSaleID;
|
|
|
|
|
|
}
|
|
|
|
//**********************************************************
|
|
//Part requests would be here if copying a service workorder
|
|
//**********************************************************
|
|
|
|
//SCHEDULED USERS
|
|
foreach (WorkorderItemScheduledUser usersource in wisource.ScheduledUsers)
|
|
{
|
|
WorkorderItemScheduledUser userdest = widest.ScheduledUsers.Add(widest);
|
|
userdest.EstimatedQuantity = usersource.EstimatedQuantity;
|
|
userdest.ServiceRateID = usersource.ServiceRateID;
|
|
userdest.StartDate = usersource.StartDate;
|
|
userdest.StopDate = usersource.StopDate;
|
|
userdest.UserID = usersource.UserID;
|
|
|
|
}
|
|
|
|
//LABOR
|
|
foreach (WorkorderItemLabor laborsource in wisource.Labors)
|
|
{
|
|
WorkorderItemLabor labordest = widest.Labors.Add(widest);
|
|
labordest.NoChargeQuantity = laborsource.NoChargeQuantity;
|
|
labordest.ServiceDetails = laborsource.ServiceDetails;
|
|
labordest.ServiceRateID = laborsource.ServiceRateID;
|
|
labordest.ServiceRateQuantity = laborsource.ServiceRateQuantity;
|
|
labordest.ServiceStartDate = laborsource.ServiceStartDate;
|
|
labordest.ServiceStopDate = laborsource.ServiceStopDate;
|
|
labordest.TaxRateSaleID = laborsource.TaxRateSaleID;
|
|
labordest.UserID = laborsource.UserID;
|
|
|
|
}
|
|
|
|
//**********************************************************
|
|
//Expenses would be here if copying a service workorder
|
|
//**********************************************************
|
|
|
|
|
|
//**********************************************************
|
|
//Loans would be here if copying a service workorder
|
|
//**********************************************************
|
|
|
|
//TRAVEL
|
|
foreach (WorkorderItemTravel travelsource in wisource.Travels)
|
|
{
|
|
WorkorderItemTravel traveldest = widest.Travels.Add(widest);
|
|
traveldest.TravelDetails = travelsource.TravelDetails;
|
|
traveldest.TravelRateID = travelsource.TravelRateID;
|
|
traveldest.TravelRateQuantity = travelsource.TravelRateQuantity;
|
|
traveldest.TravelStartDate = travelsource.TravelStartDate;
|
|
traveldest.TravelStopDate = travelsource.TravelStopDate;
|
|
traveldest.TaxRateSaleID = travelsource.TaxRateSaleID;
|
|
traveldest.UserID = travelsource.UserID;
|
|
traveldest.Distance = travelsource.Distance;
|
|
traveldest.Notes = travelsource.Notes;
|
|
traveldest.NoChargeQuantity = travelsource.NoChargeQuantity;
|
|
}
|
|
|
|
|
|
|
|
//TASKS
|
|
foreach (WorkorderItemTask tasksource in wisource.Tasks)
|
|
{
|
|
WorkorderItemTask taskdest = widest.Tasks.Add(widest);
|
|
taskdest.TaskGroupID = tasksource.TaskGroupID;
|
|
taskdest.TaskID = tasksource.TaskID;
|
|
|
|
}
|
|
|
|
//**********************************************************
|
|
//Outside service would be here if copying a service workorder
|
|
//**********************************************************
|
|
|
|
}//foreach workorderitem loop
|
|
|
|
//case 1387
|
|
|
|
//Delete the auto-created dummy workorder item
|
|
//if there are more than it present
|
|
if (dest.WorkorderItems.Count > 1)
|
|
dest.WorkorderItems.RemoveAt(0);
|
|
|
|
#endregion copy workorder data
|
|
|
|
//Now save it to ensure it was created properly so
|
|
//that we know it's now safe to advance the next service date and all others
|
|
|
|
//case 868 previously didn't set dest to result of save causing it to be a copy
|
|
dest = (Workorder)dest.Save();
|
|
|
|
|
|
|
|
|
|
#region Calculate reschedule dates
|
|
//Get the current next service date for calcs
|
|
DateTime dtNext = GetDateFromSpanAndUnit(source.WorkorderPreventiveMaintenance.dtNextServiceDate,
|
|
source.WorkorderPreventiveMaintenance.GenerateSpanUnit,
|
|
source.WorkorderPreventiveMaintenance.GenerateSpan);
|
|
|
|
//Get to the desired day of the week if necessary...
|
|
if (source.mWorkorderPreventiveMaintenance.DayOfTheWeek != AyaDayOfWeek.AnyDayOfWeek)
|
|
{
|
|
DayOfWeek desired = AyaToSystemDayOfWeek(source.mWorkorderPreventiveMaintenance.DayOfTheWeek);
|
|
while (dtNext.DayOfWeek != desired)
|
|
{
|
|
dtNext = dtNext.AddDays(1);
|
|
}
|
|
|
|
}
|
|
|
|
//Get the time span to add to all the other relevant dates on teh workorder to match
|
|
//the amount the next service date has been advanced
|
|
System.TimeSpan tsToNext = dtNext - source.WorkorderPreventiveMaintenance.dtNextServiceDate;
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
//Will the next workorder service date fall after the
|
|
//stop generating date?
|
|
if (source.WorkorderPreventiveMaintenance.StopGeneratingDate != System.DBNull.Value &&
|
|
source.WorkorderPreventiveMaintenance.dtStopGeneratingDate < dtNext)
|
|
{
|
|
//Yes it will, so set it to inactive and bail out
|
|
source.WorkorderPreventiveMaintenance.Active = false;
|
|
source.Save();
|
|
return dest;
|
|
}
|
|
|
|
#region Reschedule PM
|
|
|
|
source.WorkorderPreventiveMaintenance.dtNextServiceDate = dtNext;
|
|
//Calcs the generate date (threshold date)
|
|
source.WorkorderPreventiveMaintenance.SetGenerateDate();
|
|
//WORKORDERITEMS
|
|
foreach (WorkorderItem wisource in source.WorkorderItems)
|
|
{
|
|
|
|
wisource.RequestDate = wisource.RequestDate;
|
|
|
|
|
|
//PARTS
|
|
//no date changes required
|
|
|
|
|
|
//SCHEDULED USERS
|
|
foreach (WorkorderItemScheduledUser usersource in wisource.ScheduledUsers)
|
|
{
|
|
//Changed: 2-Oct-2006
|
|
//check to not add a date if the original date was empty
|
|
if (usersource.StartDate != System.DBNull.Value)
|
|
usersource.dtStartDate = usersource.dtStartDate.Add(tsToNext);
|
|
|
|
if (usersource.StopDate != System.DBNull.Value)
|
|
usersource.dtStopDate = usersource.dtStopDate.Add(tsToNext);
|
|
|
|
|
|
}
|
|
|
|
//LABOR
|
|
foreach (WorkorderItemLabor laborsource in wisource.Labors)
|
|
{
|
|
//Changed: 2-Oct-2006
|
|
//check to not add a date if the original date was empty
|
|
if (laborsource.ServiceStartDate != System.DBNull.Value)
|
|
laborsource.dtServiceStartDate = laborsource.dtServiceStartDate.Add(tsToNext);
|
|
|
|
if (laborsource.ServiceStopDate != System.DBNull.Value)
|
|
laborsource.dtServiceStopDate = laborsource.dtServiceStopDate.Add(tsToNext);
|
|
|
|
}
|
|
|
|
//**********************************************************
|
|
//Expenses would be here if copying a service workorder
|
|
//**********************************************************
|
|
|
|
|
|
//**********************************************************
|
|
//Loans would be here if copying a service workorder
|
|
//**********************************************************
|
|
|
|
//TRAVEL
|
|
foreach (WorkorderItemTravel travelsource in wisource.Travels)
|
|
{
|
|
//Changed: 2-Oct-2006
|
|
//check to not add a date if the original date was empty
|
|
if (travelsource.TravelStartDate != DBNull.Value)
|
|
travelsource.dtTravelStartDate = travelsource.dtTravelStartDate.Add(tsToNext);
|
|
|
|
if (travelsource.TravelStopDate != DBNull.Value)
|
|
travelsource.dtTravelStopDate = travelsource.dtTravelStopDate.Add(tsToNext);
|
|
|
|
}
|
|
|
|
|
|
|
|
//TASKS
|
|
|
|
|
|
//**********************************************************
|
|
//Outside service would be here if copying a service workorder
|
|
//**********************************************************
|
|
|
|
}//foreach workorderitem loop
|
|
#endregion reschedule pm
|
|
|
|
//Ok, Source PM is now rescheduled, save it
|
|
|
|
|
|
|
|
//case 1959 try catch block added to prevent infinite generation issue
|
|
try
|
|
{
|
|
source = (Workorder)source.Save();
|
|
}
|
|
catch (Exception exx)
|
|
{
|
|
dest.Delete();
|
|
dest.Save();
|
|
//crack the exception
|
|
while (exx.InnerException != null)
|
|
exx = exx.InnerException;
|
|
|
|
Memo mwarn = Memo.NewItem();
|
|
mwarn.ToID = User.AdministratorID;
|
|
|
|
//case 3826
|
|
if (User.CurrentUserType == UserTypes.Utility)
|
|
{
|
|
//Utility accounts should not be sending memos, it fucks up downstream
|
|
//trying to view the memo, also it's confusing
|
|
mwarn.FromID = User.AdministratorID;
|
|
}
|
|
else
|
|
{
|
|
mwarn.FromID = User.CurrentThreadUserID;
|
|
}
|
|
|
|
|
|
mwarn.Subject = "SYSTEM WARNING: Preventive Maintenance WO PROBLEM";
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.AppendLine("This is an automated message sent on behalf of the current user from the \"NewServiceWorkorderFromPM\" module.");
|
|
sb.AppendLine("This message concerns Preventive Maintenance workorder number " + source.WorkorderPreventiveMaintenance.PreventiveMaintenanceNumber.ToString());
|
|
sb.AppendLine("The Preventive Maintenance workorder had an error when trying to save it during generation of a service workorder.");
|
|
sb.AppendLine("This kind of problem could result in loop which generates a very large number of identical service workorders.");
|
|
sb.AppendLine("In order to prevent this the operation has been stopped and this message generated so you can fix the problem with the source PM workorder.");
|
|
sb.AppendLine("See below for details and examine the PM workorder for problems or contact support@ayanova.com for help with the information in this message.");
|
|
sb.AppendLine("Here are the details of the error preventing save:");
|
|
sb.AppendLine("=================================");
|
|
sb.AppendLine("Exception saving source PM:");
|
|
sb.AppendLine(exx.Message);
|
|
sb.AppendLine("=================================");
|
|
string sSourceErr = source.GetBrokenRulesString();
|
|
if (!string.IsNullOrWhiteSpace(sSourceErr))
|
|
{
|
|
sb.AppendLine("Broken business rules on PM object:");
|
|
sb.AppendLine(sSourceErr);
|
|
sb.AppendLine("==============================");
|
|
}
|
|
mwarn.Message = sb.ToString();
|
|
mwarn.Save();
|
|
throw new System.ApplicationException("Workorder->NewServiceWorkorderFromPM: Error during service workorder generation. Memo with details sent to Administrator account.");
|
|
|
|
|
|
|
|
}
|
|
|
|
//case 1630
|
|
//copy wikipage from pm to service workorder
|
|
if (dest.CanWiki && source.HasWiki)
|
|
{
|
|
try
|
|
{
|
|
WikiPage wpSource = WikiPage.GetItem(new TypeAndID(RootObjectTypes.WorkorderPreventiveMaintenance, source.ID));
|
|
WikiPage wpDest = WikiPage.GetItem(new TypeAndID(RootObjectTypes.WorkorderService, dest.ID));
|
|
wpDest.SetContent(wpSource.GetContent());
|
|
wpDest.Save();
|
|
}
|
|
catch { };
|
|
|
|
}
|
|
|
|
return dest;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
#endregion gen service wo from pm
|
|
|
|
#region Copy workorder item from one workorder to another
|
|
|
|
/// <summary>
|
|
/// Copy workorder item and all it's children
|
|
/// from current workorder to indicated destination workorder
|
|
///
|
|
/// Destination workorder can not be closed and must be the same client
|
|
///
|
|
/// If inventory is being tracked then all quantities from parts
|
|
/// are copied over as reserved quantities and need to be re-selected on destination
|
|
/// to control inventory / serial numbers etc
|
|
///
|
|
/// Loans, Outside service, part requests and Expenses are NOT copied as they are
|
|
/// situation specific.
|
|
/// </summary>
|
|
/// <param name="ToWorkorderID"></param>
|
|
/// <param name="SourceWorkorderID"></param>
|
|
/// <param name="SourceWorkorderItemID"></param>
|
|
public static void CopyWorkorderItem(Guid ToWorkorderID, Guid SourceWorkorderID, Guid SourceWorkorderItemID)
|
|
{
|
|
|
|
|
|
//Do they have enough rights to do this?
|
|
if (RightsToWorkorder(ToWorkorderID) < SecurityLevelTypes.ReadWrite)
|
|
throw new System.Security.SecurityException(
|
|
string.Format(
|
|
LocalizedTextTable.GetLocalizedTextDirect("Error.Security.NotAuthorizedToCreate"),
|
|
LocalizedTextTable.GetLocalizedTextDirect("O.Workorder")));
|
|
|
|
|
|
//Fetch the source workorder and verify it's got the source workorder item in it
|
|
Workorder source = Workorder.GetItemNoMRU(SourceWorkorderID);
|
|
if (!source.WorkorderItems.Contains(SourceWorkorderItemID))
|
|
DBUtil.ThrowFetchError("WorkorderItemID: " + SourceWorkorderItemID.ToString());
|
|
|
|
//Ok, so far so good, create the new one
|
|
bool bUseInventory = AyaBizUtils.GlobalSettings.UseInventory;
|
|
Workorder dest = Workorder.GetItemNoMRU(ToWorkorderID);
|
|
if (dest.Closed == true || dest.ServiceCompleted == true)
|
|
throw new System.ApplicationException
|
|
(
|
|
string.Format
|
|
(
|
|
LocalizedTextTable.GetLocalizedTextDirect("Error.Security.NotAuthorizedToChange"),
|
|
LocalizedTextTable.GetLocalizedTextDirect("O.Workorder")
|
|
)
|
|
);
|
|
|
|
//WORKORDERITEM
|
|
WorkorderItem wisource = source.WorkorderItems[SourceWorkorderItemID];
|
|
|
|
WorkorderItem widest = dest.WorkorderItems.Add(dest);
|
|
widest.Custom0 = wisource.Custom0;
|
|
widest.Custom1 = wisource.Custom1;
|
|
widest.Custom2 = wisource.Custom2;
|
|
widest.Custom3 = wisource.Custom3;
|
|
widest.Custom4 = wisource.Custom4;
|
|
widest.Custom5 = wisource.Custom5;
|
|
widest.Custom6 = wisource.Custom6;
|
|
widest.Custom7 = wisource.Custom7;
|
|
widest.Custom8 = wisource.Custom8;
|
|
widest.Custom9 = wisource.Custom9;
|
|
widest.PriorityID = wisource.PriorityID;
|
|
widest.RequestDate = wisource.RequestDate;
|
|
widest.Summary = wisource.Summary;
|
|
widest.TechNotes = wisource.TechNotes;
|
|
widest.TypeID = wisource.TypeID;
|
|
widest.UnitID = wisource.UnitID;
|
|
widest.WarrantyService = wisource.WarrantyService;
|
|
widest.WorkorderItemUnitServiceTypeID = wisource.WorkorderItemUnitServiceTypeID;
|
|
widest.WorkorderStatusID = wisource.WorkorderStatusID;
|
|
|
|
//PARTS
|
|
foreach (WorkorderItemPart partsource in wisource.Parts)
|
|
{
|
|
WorkorderItemPart partdest = widest.Parts.Add(widest);
|
|
partdest.Cost = partsource.Cost;
|
|
partdest.Description = partsource.Description;
|
|
partdest.Discount = partsource.Discount;
|
|
partdest.DiscountType = partsource.DiscountType;
|
|
partdest.PartID = partsource.PartID;
|
|
partdest.PartWarehouseID = partsource.PartWarehouseID;
|
|
partdest.Price = partsource.Price;
|
|
if (bUseInventory)
|
|
{
|
|
partdest.QuantityReserved = partsource.Quantity;
|
|
partdest.Quantity = 0;
|
|
}
|
|
else
|
|
partdest.Quantity = partsource.Quantity;
|
|
partdest.TaxPartSaleID = partsource.TaxPartSaleID;
|
|
|
|
|
|
}
|
|
|
|
//**********************************************************
|
|
//Part requests would be here if copying a service workorder
|
|
//**********************************************************
|
|
|
|
//SCHEDULED USERS
|
|
foreach (WorkorderItemScheduledUser usersource in wisource.ScheduledUsers)
|
|
{
|
|
WorkorderItemScheduledUser userdest = widest.ScheduledUsers.Add(widest);
|
|
userdest.EstimatedQuantity = usersource.EstimatedQuantity;
|
|
userdest.ServiceRateID = usersource.ServiceRateID;
|
|
userdest.StartDate = usersource.StartDate;
|
|
userdest.StopDate = usersource.StopDate;
|
|
userdest.UserID = usersource.UserID;
|
|
|
|
}
|
|
|
|
//LABOR
|
|
foreach (WorkorderItemLabor laborsource in wisource.Labors)
|
|
{
|
|
WorkorderItemLabor labordest = widest.Labors.Add(widest);
|
|
labordest.NoChargeQuantity = laborsource.NoChargeQuantity;
|
|
labordest.ServiceDetails = laborsource.ServiceDetails;
|
|
labordest.ServiceRateID = laborsource.ServiceRateID;
|
|
labordest.ServiceRateQuantity = laborsource.ServiceRateQuantity;
|
|
labordest.ServiceStartDate = laborsource.ServiceStartDate;
|
|
labordest.ServiceStopDate = laborsource.ServiceStopDate;
|
|
labordest.TaxRateSaleID = laborsource.TaxRateSaleID;
|
|
labordest.UserID = laborsource.UserID;
|
|
|
|
}
|
|
|
|
//**********************************************************
|
|
//Expenses would be here if copying a service workorder
|
|
//**********************************************************
|
|
|
|
|
|
//**********************************************************
|
|
//Loans would be here if copying a service workorder
|
|
//**********************************************************
|
|
|
|
//TRAVEL
|
|
foreach (WorkorderItemTravel travelsource in wisource.Travels)
|
|
{
|
|
WorkorderItemTravel traveldest = widest.Travels.Add(widest);
|
|
traveldest.TravelDetails = travelsource.TravelDetails;
|
|
traveldest.TravelRateID = travelsource.TravelRateID;
|
|
traveldest.TravelRateQuantity = travelsource.TravelRateQuantity;
|
|
traveldest.TravelStartDate = travelsource.TravelStartDate;
|
|
traveldest.TravelStopDate = travelsource.TravelStopDate;
|
|
traveldest.TaxRateSaleID = travelsource.TaxRateSaleID;
|
|
traveldest.UserID = travelsource.UserID;
|
|
traveldest.Distance = travelsource.Distance;
|
|
traveldest.Notes = travelsource.Notes;
|
|
traveldest.NoChargeQuantity = travelsource.NoChargeQuantity;
|
|
}
|
|
|
|
|
|
|
|
//TASKS
|
|
foreach (WorkorderItemTask tasksource in wisource.Tasks)
|
|
{
|
|
WorkorderItemTask taskdest = widest.Tasks.Add(widest);
|
|
taskdest.TaskGroupID = tasksource.TaskGroupID;
|
|
taskdest.TaskID = tasksource.TaskID;
|
|
|
|
}
|
|
|
|
//**********************************************************
|
|
//Outside service would be here if copying a service workorder
|
|
//**********************************************************
|
|
|
|
dest.Save();
|
|
}
|
|
#endregion
|
|
|
|
#region Date time calcs helpers
|
|
//Takes an AyaNova day of week and returns
|
|
//a System.DayOfWeek
|
|
//Assumes that AyaDayOfWeek is NOT "AnyDay"
|
|
internal static System.DayOfWeek AyaToSystemDayOfWeek(AyaDayOfWeek day)
|
|
{
|
|
switch (day)
|
|
{
|
|
case AyaDayOfWeek.Monday:
|
|
return DayOfWeek.Monday;
|
|
case AyaDayOfWeek.Tuesday:
|
|
return DayOfWeek.Tuesday;
|
|
case AyaDayOfWeek.Wednesday:
|
|
return DayOfWeek.Wednesday;
|
|
case AyaDayOfWeek.Thursday:
|
|
return DayOfWeek.Thursday;
|
|
case AyaDayOfWeek.Friday:
|
|
return DayOfWeek.Friday;
|
|
case AyaDayOfWeek.Saturday:
|
|
return DayOfWeek.Saturday;
|
|
case AyaDayOfWeek.Sunday:
|
|
return DayOfWeek.Sunday;
|
|
|
|
|
|
|
|
}
|
|
|
|
throw new System.ArgumentOutOfRangeException("DayOfWeekConverter: AyaDayOfWeek.AnyDayOfWeek is not supported");
|
|
}
|
|
|
|
|
|
internal static DateTime GetDateFromSpanAndUnit(DateTime StartDate, AyaUnitsOfTime unit, int multiple)
|
|
{
|
|
switch (unit)
|
|
{
|
|
case AyaUnitsOfTime.Seconds:
|
|
return StartDate.AddSeconds(multiple);
|
|
|
|
case AyaUnitsOfTime.Minutes:
|
|
return StartDate.AddMinutes(multiple);
|
|
|
|
case AyaUnitsOfTime.Hours:
|
|
return StartDate.AddHours(multiple);
|
|
|
|
case AyaUnitsOfTime.Days:
|
|
return StartDate.AddDays(multiple);
|
|
|
|
case AyaUnitsOfTime.Weeks:
|
|
throw new System.NotSupportedException("GetDateFromSpanAndUnit: Weeks not supported");
|
|
|
|
case AyaUnitsOfTime.Months:
|
|
return StartDate.AddMonths(multiple);
|
|
|
|
case AyaUnitsOfTime.Years:
|
|
return StartDate.AddYears(multiple);
|
|
|
|
|
|
}
|
|
|
|
//fail safe:
|
|
return StartDate;
|
|
}
|
|
|
|
#endregion date time calcs helpers
|
|
|
|
#region wotype <-> rootobject converters
|
|
/// <summary>
|
|
/// Converts <see cref="RootObjectTypes"/> enum value to corresponding <see cref="WorkorderTypes"/> enum value
|
|
/// </summary>
|
|
/// <param name="rootobject"></param>
|
|
/// <returns></returns>
|
|
public static WorkorderTypes WorkorderTypeFromRootObjectType(RootObjectTypes rootobject)
|
|
{
|
|
switch (rootobject)
|
|
{
|
|
case RootObjectTypes.WorkorderService:
|
|
return WorkorderTypes.Service;
|
|
|
|
case RootObjectTypes.WorkorderQuote:
|
|
return WorkorderTypes.Quote;
|
|
|
|
case RootObjectTypes.WorkorderPreventiveMaintenance:
|
|
return WorkorderTypes.PreventiveMaintenance;
|
|
|
|
case RootObjectTypes.WorkorderServiceTemplate:
|
|
return WorkorderTypes.TemplateService;
|
|
|
|
case RootObjectTypes.WorkorderQuoteTemplate:
|
|
return WorkorderTypes.TemplateQuote;
|
|
|
|
case RootObjectTypes.WorkorderPreventiveMaintenanceTemplate:
|
|
return WorkorderTypes.TemplatePreventiveMaintenance;
|
|
|
|
default:
|
|
return WorkorderTypes.Unknown;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Converts a <see cref="WorkorderTypes"/> enum value to corresponding <see cref="RootObjectTypes"/> enum value
|
|
/// </summary>
|
|
/// <param name="wotype"></param>
|
|
/// <returns></returns>
|
|
public static RootObjectTypes RootObjectTypeFromWorkorderType(WorkorderTypes wotype)
|
|
{
|
|
switch (wotype)
|
|
{
|
|
|
|
case WorkorderTypes.Service:
|
|
return RootObjectTypes.WorkorderService;
|
|
case WorkorderTypes.Quote:
|
|
return RootObjectTypes.WorkorderQuote;
|
|
|
|
case WorkorderTypes.PreventiveMaintenance:
|
|
return RootObjectTypes.WorkorderPreventiveMaintenance;
|
|
|
|
case WorkorderTypes.TemplateService:
|
|
return RootObjectTypes.WorkorderServiceTemplate;
|
|
|
|
case WorkorderTypes.TemplateQuote:
|
|
return RootObjectTypes.WorkorderQuoteTemplate;
|
|
|
|
case WorkorderTypes.TemplatePreventiveMaintenance:
|
|
return RootObjectTypes.WorkorderPreventiveMaintenanceTemplate;
|
|
|
|
|
|
default:
|
|
return RootObjectTypes.Nothing;
|
|
|
|
}
|
|
}
|
|
|
|
#endregion converter
|
|
|
|
#endregion static methods
|
|
|
|
#region Shared Notification Message Processor
|
|
internal static NotifyMessage GetNotificationMessage(NotifyMessageRequestData d)
|
|
{
|
|
|
|
//case 1555
|
|
bool bSourceIsQuote = (d.EventType == (int)WorkorderEvent.QuoteUpdated);
|
|
|
|
if (bSourceIsQuote)//case 1555
|
|
{
|
|
#region Quote workorder
|
|
WorkorderQuoteDescriptionFetcher wdf = WorkorderQuoteDescriptionFetcher.GetItem(d.RootObjectID);
|
|
|
|
string sEventDescription = "";
|
|
string sExtraInfo = "";
|
|
switch (d.EventType)
|
|
{
|
|
|
|
case (int)WorkorderEvent.QuoteUpdated:
|
|
sEventDescription = LocalizedTextTable.GetLocalizedTextDirect("Workorder.Label.Event.QuoteUpdated", d.Language);
|
|
bSourceIsQuote = true;
|
|
break;
|
|
}
|
|
|
|
|
|
string sMessage = sEventDescription;
|
|
string sSubject = sEventDescription;
|
|
NotifyMessage nm = null;
|
|
|
|
if (d.Format == NotifyDeliveryMessageFormats.Brief)
|
|
{
|
|
sMessage += " " + LocalizedTextTable.GetLocalizedTextDirect("WorkorderQuote.Label.QuoteNumber", d.Language) + " " + wdf.WorkorderNumber + " " + wdf.ClientName + " " + sExtraInfo;
|
|
if (d.MaxCharacters > 0 && sMessage.Length > d.MaxCharacters)
|
|
nm = new NotifyMessage("", sMessage.Substring(0, d.MaxCharacters));
|
|
else
|
|
nm = new NotifyMessage("", sMessage);
|
|
}
|
|
else
|
|
{
|
|
sSubject += ": " + LocalizedTextTable.GetLocalizedTextDirect("WorkorderQuote.Label.QuoteNumber", d.Language) + " " + wdf.WorkorderNumber;
|
|
sMessage += ": " + LocalizedTextTable.GetLocalizedTextDirect("WorkorderQuote.Label.QuoteNumber", d.Language) + " " + wdf.WorkorderNumber + "\r\n" +
|
|
LocalizedTextTable.GetLocalizedTextDirect("O.Client", d.Language) + ": " + wdf.ClientName + "\r\n" +
|
|
sExtraInfo;
|
|
nm = new NotifyMessage(sSubject, sMessage);
|
|
}
|
|
return nm;
|
|
#endregion quote workorder
|
|
|
|
}
|
|
else
|
|
{
|
|
#region Service workorder
|
|
WorkorderDescriptionFetcher wdf = WorkorderDescriptionFetcher.GetItem(d.RootObjectID);
|
|
|
|
//case 1415
|
|
SmartDate sTZCloseBy = wdf.CloseByDate;
|
|
if (d.TimeZoneOffset != 0)
|
|
{
|
|
sTZCloseBy.Date = wdf.CloseByDate.Date.ToUniversalTime().AddHours(d.TimeZoneOffset);
|
|
|
|
}
|
|
|
|
|
|
|
|
string sEventDescription = "";
|
|
string sExtraInfo = "";
|
|
switch (d.EventType)
|
|
{
|
|
case (int)WorkorderEvent.Status:
|
|
sEventDescription = LocalizedTextTable.GetLocalizedTextDirect("Workorder.Label.Event.Status", d.Language);
|
|
sExtraInfo = LocalizedTextTable.GetLocalizedTextDirect("O.WorkorderStatus", d.Language) + ": " + NameFetcher.GetItem("aWorkorderStatus", "aName", d.GuidValue).RecordName;
|
|
break;
|
|
case (int)WorkorderEvent.CloseByDatePassed:
|
|
sEventDescription = LocalizedTextTable.GetLocalizedTextDirect("Workorder.Label.Event.CloseByDatePassed", d.Language);
|
|
sExtraInfo = LocalizedTextTable.GetLocalizedTextDirect("WorkorderService.Label.CloseByDate", d.Language) + ": " + sTZCloseBy.ToString();
|
|
break;
|
|
|
|
//case 1555
|
|
case (int)WorkorderEvent.QuoteUpdated:
|
|
sEventDescription = LocalizedTextTable.GetLocalizedTextDirect("Workorder.Label.Event.QuoteUpdated", d.Language);
|
|
//sExtraInfo = LocalizedTextTable.GetLocalizedTextDirect("O.WorkorderStatus", d.Language) + ": " + NameFetcher.GetItem("aWorkorderStatus", "aName", d.GuidValue).RecordName;
|
|
bSourceIsQuote = true;
|
|
break;
|
|
}
|
|
|
|
|
|
string sMessage = sEventDescription;
|
|
string sSubject = sEventDescription;
|
|
NotifyMessage nm = null;
|
|
|
|
if (d.Format == NotifyDeliveryMessageFormats.Brief)
|
|
{
|
|
sMessage += " " + LocalizedTextTable.GetLocalizedTextDirect("WorkorderService.Label.ServiceNumber", d.Language) + " " + wdf.WorkorderNumber + " " + wdf.ClientName + " " + sExtraInfo;
|
|
if (d.MaxCharacters > 0 && sMessage.Length > d.MaxCharacters)
|
|
nm = new NotifyMessage("", sMessage.Substring(0, d.MaxCharacters));
|
|
else
|
|
nm = new NotifyMessage("", sMessage);
|
|
}
|
|
else
|
|
{
|
|
sSubject += ": " + LocalizedTextTable.GetLocalizedTextDirect("WorkorderService.Label.ServiceNumber", d.Language) + " " + wdf.WorkorderNumber;
|
|
sMessage += ": " + LocalizedTextTable.GetLocalizedTextDirect("WorkorderService.Label.ServiceNumber", d.Language) + " " + wdf.WorkorderNumber + "\r\n" +
|
|
LocalizedTextTable.GetLocalizedTextDirect("O.Client", d.Language) + ": " + wdf.ClientName + "\r\n" +
|
|
sExtraInfo;
|
|
nm = new NotifyMessage(sSubject, sMessage);
|
|
}
|
|
return nm;
|
|
#endregion service workorder
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region DAL DATA ACCESS
|
|
|
|
#region Fetch
|
|
|
|
//case 53 - need to know if workorder was new before it was saved
|
|
//for new workorder client notification processing
|
|
private bool bWasNew = false;
|
|
|
|
///
|
|
/// <param name="Criteria"></param>
|
|
protected override void DataPortal_Fetch(object Criteria)
|
|
{
|
|
|
|
//set to false to load items initially
|
|
bReadOnly = false;
|
|
|
|
Criteria crit = (Criteria)Criteria;
|
|
SafeDataReader dr = null;
|
|
Guid WorkorderIDToFetch = crit.ID;
|
|
try
|
|
{
|
|
|
|
switch (crit.RootObjectType)
|
|
{
|
|
case RootObjectTypes.Workorder:
|
|
;//Do nothing, we already have the workorder id in crit.ID
|
|
break;
|
|
case RootObjectTypes.WorkorderItem:
|
|
WorkorderIDToFetch = DBUtil.ToGuid(DBUtil.GetScalarFromSQLString(
|
|
"SELECT TOP 1 aWorkorderItem.aWorkorderID " +
|
|
"FROM aWorkorderItem WHERE (aWorkorderItem.aID = @ID)"
|
|
, crit.ID));
|
|
break;
|
|
case RootObjectTypes.WorkorderItemLabor:
|
|
WorkorderIDToFetch = DBUtil.ToGuid(DBUtil.GetScalarFromSQLString(
|
|
"SELECT TOP 1 aWorkorderItem.aWorkorderID " +
|
|
"FROM aWorkorderItem INNER JOIN aWorkorderItemLabor " +
|
|
"ON aWorkorderItem.aID = aWorkorderItemLabor.aWorkorderItemID " +
|
|
"WHERE (aWorkorderItemLabor.aID " +
|
|
"= @ID)"
|
|
, crit.ID));
|
|
break;
|
|
//Added: 2-Oct-2006
|
|
//to support search results display
|
|
case RootObjectTypes.WorkorderItemMiscExpense:
|
|
WorkorderIDToFetch = DBUtil.ToGuid(DBUtil.GetScalarFromSQLString(
|
|
"SELECT TOP 1 aWorkorderItem.aWorkorderID " +
|
|
"FROM aWorkorderItem INNER JOIN aWorkorderItemMiscExpense " +
|
|
"ON aWorkorderItem.aID = aWorkorderItemMiscExpense.aWorkorderItemID " +
|
|
"WHERE (aWorkorderItemMiscExpense.aID " +
|
|
"= @ID)"
|
|
, crit.ID));
|
|
break;
|
|
case RootObjectTypes.WorkorderItemTravel:
|
|
WorkorderIDToFetch = DBUtil.ToGuid(DBUtil.GetScalarFromSQLString(
|
|
"SELECT TOP 1 aWorkorderItem.aWorkorderID " +
|
|
"FROM aWorkorderItem INNER JOIN aWorkorderItemTravel " +
|
|
"ON aWorkorderItem.aID = aWorkorderItemTravel.aWorkorderItemID " +
|
|
"WHERE (aWorkorderItemTravel.aID " +
|
|
"= @ID)"
|
|
, crit.ID));
|
|
break;
|
|
case RootObjectTypes.WorkorderItemScheduledUser:
|
|
WorkorderIDToFetch = DBUtil.ToGuid(DBUtil.GetScalarFromSQLString(
|
|
"SELECT TOP 1 aWorkorderItem.aWorkorderID " +
|
|
"FROM aWorkorderItem INNER JOIN aWorkorderItemScheduledUser " +
|
|
"ON aWorkorderItem.aID = aWorkorderItemScheduledUser.aWorkorderItemID " +
|
|
"WHERE (aWorkorderItemScheduledUser.aID " +
|
|
"= @ID)"
|
|
, crit.ID));
|
|
break;
|
|
case RootObjectTypes.WorkorderItemOutsideService:
|
|
WorkorderIDToFetch = DBUtil.ToGuid(DBUtil.GetScalarFromSQLString(
|
|
"SELECT TOP 1 aWorkorderItem.aWorkorderID " +
|
|
"FROM aWorkorderItem INNER JOIN aWorkorderItemOutsideService " +
|
|
"ON aWorkorderItem.aID = aWorkorderItemOutsideService.aWorkorderItemID " +
|
|
"WHERE (aWorkorderItemOutsideService.aID " +
|
|
"= @ID)"
|
|
, crit.ID));
|
|
break;
|
|
case RootObjectTypes.WorkorderItemPartRequest:
|
|
WorkorderIDToFetch = DBUtil.ToGuid(DBUtil.GetScalarFromSQLString(
|
|
"SELECT TOP 1 aWorkorderItem.aWorkorderID " +
|
|
"FROM aWorkorderItem INNER JOIN aWorkorderItemPartRequest " +
|
|
"ON aWorkorderItem.aID = aWorkorderItemPartRequest.aWorkorderItemID " +
|
|
"WHERE (aWorkorderItemPartRequest.aID " +
|
|
"= @ID)"
|
|
, crit.ID));
|
|
break;
|
|
case RootObjectTypes.WorkorderItemPart:
|
|
WorkorderIDToFetch = DBUtil.ToGuid(DBUtil.GetScalarFromSQLString(
|
|
"SELECT TOP 1 aWorkorderItem.aWorkorderID " +
|
|
"FROM aWorkorderItem INNER JOIN aWorkorderItemPart " +
|
|
"ON aWorkorderItem.aID = aWorkorderItemPart.aWorkorderItemID " +
|
|
"WHERE (aWorkorderItemPart.aID " +
|
|
"= @ID)"
|
|
, crit.ID));
|
|
break;
|
|
case RootObjectTypes.WorkorderPreventiveMaintenance:
|
|
WorkorderIDToFetch = DBUtil.ToGuid(DBUtil.GetScalarFromSQLString(
|
|
"SELECT aWorkorderPreventiveMaintenance.aWorkorderID " +
|
|
"FROM aWorkorderPreventiveMaintenance " +
|
|
"WHERE (aWorkorderPreventiveMaintenance.aID " +
|
|
"= @ID)"
|
|
, crit.ID));
|
|
break;
|
|
case RootObjectTypes.WorkorderQuote:
|
|
WorkorderIDToFetch = DBUtil.ToGuid(DBUtil.GetScalarFromSQLString(
|
|
"SELECT aWorkorderQuote.aWorkorderID " +
|
|
"FROM aWorkorderQuote " +
|
|
"WHERE (aWorkorderQuote.aID " +
|
|
"= @ID)"
|
|
, crit.ID));
|
|
break;
|
|
case RootObjectTypes.WorkorderService:
|
|
WorkorderIDToFetch = DBUtil.ToGuid(DBUtil.GetScalarFromSQLString(
|
|
"SELECT aWorkorderService.aWorkorderID " +
|
|
"FROM aWorkorderService " +
|
|
"WHERE (aWorkorderService.aID " +
|
|
"= @ID)"
|
|
, crit.ID));
|
|
break;
|
|
case RootObjectTypes.WorkorderItemLoan:
|
|
WorkorderIDToFetch = DBUtil.ToGuid(DBUtil.GetScalarFromSQLString(
|
|
"SELECT TOP 1 aWorkorderItem.aWorkorderID " +
|
|
"FROM aWorkorderItem INNER JOIN aWorkorderItemLoan " +
|
|
"ON aWorkorderItem.aID = aWorkorderItemLoan.aWorkorderItemID " +
|
|
"WHERE (aWorkorderItemLoan.aID " +
|
|
"= @ID)"
|
|
, crit.ID));
|
|
break;
|
|
default:
|
|
throw new System.NotSupportedException("GetWorkorderByDescendant(" + crit.RootObjectType.ToString() + ") not supported");
|
|
}
|
|
|
|
|
|
|
|
crit.ID = WorkorderIDToFetch;
|
|
|
|
//retrieve the workorder:
|
|
dr = DBUtil.GetReaderFromSQLString("SELECT * FROM aWorkorder WHERE aID=@ID;", crit.ID);
|
|
if (!dr.Read())
|
|
DBUtil.ThrowFetchError("Workorder ID: " + crit.ID.ToString());
|
|
|
|
//Workorder fields
|
|
mClientID = dr.GetGuid("aClientID");
|
|
mProjectID = dr.GetGuid("aProjectID");
|
|
mInternalReferenceNumber = dr.GetString("aInternalReferenceNumber");
|
|
mCustomerReferenceNumber = dr.GetString("aCustomerReferenceNumber");
|
|
mOnsite = dr.GetBoolean("aOnsite");
|
|
mCustomerContactName = dr.GetString("aCustomerContactName");
|
|
|
|
//Case 58
|
|
mRegionID = dr.GetGuid("aRegionID");
|
|
|
|
mSummary = dr.GetString("aSummary");
|
|
//mTemplateID=dr.GetGuid("aTemplateID");
|
|
mFormLayoutID = dr.GetGuid("aFormLayoutID");
|
|
mWorkorderType = (WorkorderTypes)dr.GetInt16("aWorkorderType");
|
|
mRights = (SecurityLevelTypes)AyaBizUtils.Right(Workorder.RootObjectTypeFromWorkorderType(mWorkorderType));
|
|
|
|
|
|
//mTemplate=dr.GetBoolean("aTemplate");
|
|
mWorkorderCategoryID = dr.GetGuid("aWorkorderCategoryID");
|
|
mServiceCompleted = dr.GetBoolean("aServiceCompleted");
|
|
mClosed = dr.GetBoolean("aClosed");
|
|
mFromQuoteID = dr.GetGuid("aFromQuoteID");
|
|
mFromPMID = dr.GetGuid("aFromPMID");
|
|
mTemplateDescription = dr.GetString("aTemplateDescription");
|
|
mTemplateFreshPrice = dr.GetBoolean("ATEMPLATEFRESHPRICE");//case 3132
|
|
|
|
|
|
//Standard fields
|
|
mID = dr.GetGuid("aID");
|
|
mCreated = DBUtil.ToLocal(dr.GetSmartDate("aCreated"));
|
|
mModified = DBUtil.ToLocal(dr.GetSmartDate("aModified"));
|
|
mCreator = dr.GetGuid("aCreator");
|
|
mModifier = dr.GetGuid("aModifier");
|
|
|
|
if (dr != null) dr.Close();
|
|
|
|
|
|
//Child objects...
|
|
|
|
//PM
|
|
if (this.mWorkorderType == WorkorderTypes.PreventiveMaintenance ||
|
|
this.mWorkorderType == WorkorderTypes.TemplatePreventiveMaintenance)
|
|
{
|
|
dr = DBUtil.GetReaderFromSQLString("SELECT * FROM aWorkorderPreventiveMaintenance WHERE aWorkorderID=@ID;", crit.ID);
|
|
if (dr.Read())//single child objects need this
|
|
mWorkorderPreventiveMaintenance = WorkorderPreventiveMaintenance.GetItem(dr);
|
|
else
|
|
{
|
|
//double check there isn't a problem
|
|
|
|
//ok, we *should* always have a pm for a
|
|
//pm type workorder obviously something has gone wrong
|
|
//so let's create one now
|
|
mWorkorderPreventiveMaintenance = WorkorderPreventiveMaintenance.NewItem(this);
|
|
|
|
}
|
|
if (dr != null) dr.Close();
|
|
}
|
|
|
|
|
|
//WorkorderService
|
|
if (this.mWorkorderType == WorkorderTypes.Service ||
|
|
this.mWorkorderType == WorkorderTypes.TemplateService)
|
|
{
|
|
dr = DBUtil.GetReaderFromSQLString("SELECT * FROM aWorkorderService WHERE aWorkorderID=@ID;", crit.ID);
|
|
if (dr.Read())//single child objects need this
|
|
mService = WorkorderService.GetItem(dr);
|
|
else
|
|
{
|
|
//double check there isn't a problem
|
|
|
|
//ok, we *should* always have a workorderservice for a
|
|
//service type workorder obviously something has gone wrong
|
|
//so let's create one now
|
|
mService = WorkorderService.NewItem(this);
|
|
|
|
}
|
|
if (dr != null) dr.Close();
|
|
}
|
|
|
|
|
|
//WorkorderQuote
|
|
if (this.mWorkorderType == WorkorderTypes.Quote ||
|
|
this.mWorkorderType == WorkorderTypes.TemplateQuote)
|
|
{
|
|
dr = DBUtil.GetReaderFromSQLString("SELECT * FROM aWorkorderQuote WHERE aWorkorderID=@ID;", crit.ID);
|
|
if (dr.Read())//single child objects need this
|
|
mQuote = WorkorderQuote.GetItem(dr);
|
|
else
|
|
{
|
|
//double check there isn't a problem
|
|
|
|
//ok, we *should* always have a WorkorderQuote for a
|
|
//Quote type workorder obviously something has gone wrong
|
|
//so let's create one now
|
|
mQuote = WorkorderQuote.NewItem(this);
|
|
|
|
}
|
|
if (dr != null) dr.Close();
|
|
}
|
|
|
|
|
|
//WorkorderItems collection
|
|
dr = DBUtil.GetReaderFromSQLString("SELECT * FROM aWorkorderItem WHERE aWorkorderID=@ID;", crit.ID);
|
|
//Child collection objects don't need to read first: they do it themselves
|
|
mWorkorderItems = WorkorderItems.GetItems(dr, this);
|
|
if (dr != null) dr.Close();
|
|
|
|
//Docs
|
|
dr = DBUtil.GetReaderFromSQLString("SELECT * FROM AASSIGNEDDOC WHERE (aRootObjectID=@ID and aRootObjectType=9);", crit.ID);
|
|
mDocs = AssignedDocs.GetItems(dr, RootObjectTypes.Workorder, this.RootObjectType);
|
|
if (dr != null) dr.Close();
|
|
|
|
}
|
|
finally
|
|
{
|
|
if (dr != null) dr.Close();
|
|
}
|
|
|
|
MarkOld();
|
|
|
|
|
|
if (crit.TrackMRU)
|
|
{
|
|
switch (mWorkorderType)
|
|
{
|
|
case WorkorderTypes.Service:
|
|
if (AyaBizUtils.AllowAutomaticMRUOnUpdate) AyaBizUtils.MRU.Add(RootObjectTypes.Workorder, mID);
|
|
break;
|
|
case WorkorderTypes.Quote:
|
|
if (AyaBizUtils.AllowAutomaticMRUOnUpdate) AyaBizUtils.MRU.Add(RootObjectTypes.WorkorderQuote, WorkorderQuote.ID);
|
|
break;
|
|
case WorkorderTypes.PreventiveMaintenance:
|
|
if (AyaBizUtils.AllowAutomaticMRUOnUpdate) AyaBizUtils.MRU.Add(RootObjectTypes.WorkorderPreventiveMaintenance, WorkorderPreventiveMaintenance.ID);
|
|
break;
|
|
|
|
case WorkorderTypes.TemplateService:
|
|
if (AyaBizUtils.AllowAutomaticMRUOnUpdate) AyaBizUtils.MRU.Add(RootObjectTypes.WorkorderServiceTemplate, mID);
|
|
break;
|
|
case WorkorderTypes.TemplateQuote:
|
|
if (AyaBizUtils.AllowAutomaticMRUOnUpdate) AyaBizUtils.MRU.Add(RootObjectTypes.WorkorderQuoteTemplate, WorkorderQuote.ID);
|
|
break;
|
|
case WorkorderTypes.TemplatePreventiveMaintenance:
|
|
if (AyaBizUtils.AllowAutomaticMRUOnUpdate) AyaBizUtils.MRU.Add(RootObjectTypes.WorkorderPreventiveMaintenanceTemplate, WorkorderPreventiveMaintenance.ID);
|
|
break;
|
|
}
|
|
}
|
|
|
|
//Get access rights level
|
|
bReadOnly = mRights < SecurityLevelTypes.ReadWrite;
|
|
|
|
//If not already read only see if workorder is closed because a closed
|
|
//workorder is *always* read only
|
|
if (!bReadOnly)
|
|
{
|
|
if (mWorkorderType == WorkorderTypes.Service)
|
|
{
|
|
if (mClosed)
|
|
{
|
|
//case 986
|
|
//bReadOnly=true;
|
|
//set all workorder items to read only status
|
|
this.mWorkorderItems.SetReadOnly(true);
|
|
return;//no need to continue because the following only
|
|
//does the same thing anyway
|
|
}
|
|
}
|
|
}
|
|
|
|
//Check for service completed
|
|
if (mWorkorderType == WorkorderTypes.Service)
|
|
{
|
|
if (mServiceCompleted)
|
|
{
|
|
//set all workorder items to read only status
|
|
this.mWorkorderItems.SetReadOnly(true);
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
#endregion fetch
|
|
|
|
#region Update
|
|
|
|
/// <summary>
|
|
/// Called by DataPortal to delete/add/update data into the database
|
|
/// </summary>
|
|
protected override void DataPortal_Update()
|
|
{
|
|
|
|
// 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, "aWorkorder");
|
|
|
|
#region Delete
|
|
if (IsDeleted)
|
|
{
|
|
if (this.HasPartRequestsOnOrder)
|
|
throw new System.ApplicationException
|
|
(
|
|
|
|
string.Format
|
|
(
|
|
LocalizedTextTable.GetLocalizedTextDirect("Error.Object.NotDeleteable"),
|
|
LocalizedTextTable.GetLocalizedTextDirect("O.Workorder")
|
|
) + " when it has part requests on order"//case 3599
|
|
);
|
|
if (!IsNew)
|
|
{
|
|
|
|
//Delete pm, service, quote, woitems and workorder itself
|
|
|
|
|
|
//case 3596
|
|
DBCommandWrapper cmDeleteFromLastServiceClient = DBUtil.GetCommandFromSQL("UPDATE ACLIENT SET ALASTWORKORDERID = null, ALASTSERVICEDATE = null WHERE ALASTWORKORDERID = @WORKORDERID");
|
|
cmDeleteFromLastServiceClient.AddInParameter("@WORKORDERID", DbType.Guid, this.mID);
|
|
|
|
//case 3596
|
|
DBCommandWrapper cmDeleteFromLastServiceUnit = DBUtil.GetCommandFromSQL("UPDATE AUNIT SET ALASTWORKORDERID = null, ALASTSERVICEDATE = null WHERE ALASTWORKORDERID = @WORKORDERID");
|
|
cmDeleteFromLastServiceUnit.AddInParameter("@WORKORDERID", DbType.Guid, this.mID);
|
|
|
|
DBCommandWrapper cmDeletePM = DBUtil.GetCommandFromSQL("DELETE FROM aWorkorderPreventiveMaintenance WHERE aWorkorderID = @ID;");
|
|
cmDeletePM.AddInParameter("@ID", DbType.Guid, this.mID);
|
|
|
|
DBCommandWrapper cmDeleteService = DBUtil.GetCommandFromSQL("DELETE FROM aWorkorderService WHERE aWorkorderID = @ID;");
|
|
cmDeleteService.AddInParameter("@ID", DbType.Guid, this.mID);
|
|
|
|
DBCommandWrapper cmDeleteQuote = DBUtil.GetCommandFromSQL("DELETE FROM aWorkorderQuote WHERE aWorkorderID = @ID;");
|
|
cmDeleteQuote.AddInParameter("@ID", DbType.Guid, this.mID);
|
|
|
|
DBCommandWrapper cmDeleteWO = DBUtil.GetCommandFromSQL("DELETE FROM aWorkorder WHERE aID = @ID;");
|
|
cmDeleteWO.AddInParameter("@ID", DbType.Guid, this.mID);
|
|
|
|
|
|
|
|
using (IDbConnection connection = DBUtil.DB.GetConnection())
|
|
{
|
|
connection.Open();
|
|
//IDbTransaction transaction = connection.BeginTransaction();
|
|
//Changed this to a high isolation level transaction because
|
|
//it can affect inventory etc
|
|
IDbTransaction transaction = connection.BeginTransaction(System.Data.IsolationLevel.Serializable);
|
|
|
|
try
|
|
{
|
|
|
|
//case 3596
|
|
DBUtil.DB.ExecuteNonQuery(cmDeleteFromLastServiceClient, transaction);
|
|
DBUtil.DB.ExecuteNonQuery(cmDeleteFromLastServiceUnit, transaction);
|
|
|
|
//This one method takes care of any and all workorder
|
|
//items that are children of this workorder
|
|
//It deletes all workorder item children and then all workorder items
|
|
//attached to this workorder
|
|
WorkorderItems.DeleteItems(this.mID, transaction);
|
|
DBUtil.DB.ExecuteNonQuery(cmDeletePM, transaction);
|
|
DBUtil.DB.ExecuteNonQuery(cmDeleteService, transaction);
|
|
DBUtil.DB.ExecuteNonQuery(cmDeleteQuote, transaction);
|
|
DBUtil.DB.ExecuteNonQuery(cmDeleteWO, transaction);
|
|
|
|
DBUtil.RemoveKeywords(transaction, RootObjectTypes.Workorder, this.mID);
|
|
DBUtil.RemoveDocs(transaction, RootObjectTypes.Workorder, this.mID);
|
|
|
|
// Commit the transaction
|
|
transaction.Commit();
|
|
|
|
}
|
|
catch
|
|
{
|
|
// Rollback transaction
|
|
transaction.Rollback();
|
|
throw;
|
|
}
|
|
finally
|
|
{
|
|
connection.Close();
|
|
}
|
|
}
|
|
|
|
//Remove any events for this object
|
|
if (AyaBizUtils.GlobalSettings.UseNotification)//Case 510
|
|
{
|
|
NotifyEvent.RemoveAllEventsForObject(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 aWorkorder (aID, aClientID, aProjectID, " +
|
|
"aInternalReferenceNumber, aCustomerReferenceNumber, " +
|
|
"aOnsite, aCustomerContactName, aWorkorderType, " +
|
|
"aFormLayoutID, aSummary, aTemplateDescription, " +
|
|
"aWorkorderCategoryID, aCreated,aModified,aCreator,aModifier, " +
|
|
"aClosed, aServiceCompleted, aFromQuoteID, aFromPMID, aRegionID, ATEMPLATEFRESHPRICE) VALUES (@ID,@ClientID, " +
|
|
"@ProjectID,@InternalReferenceNumber,@CustomerReferenceNumber, " +
|
|
"@Onsite,@CustomerContactName, " +
|
|
"@WorkorderType,@FormLayoutID, " +
|
|
"@Summary, @TemplateDescription, @WorkorderCategoryID, " +
|
|
"@Created, @Modified,@CurrentUserID,@CurrentUserID, " +
|
|
"@Closed,@ServiceCompleted, @FromQuoteID, @FromPMID, @RegionID, @TEMPLATEFRESHPRICE)"
|
|
);
|
|
else
|
|
cm = DBUtil.GetCommandFromSQL(
|
|
"UPDATE aWorkorder SET aID=@ID, aClientID=@ClientID, " +
|
|
"aProjectID=@ProjectID, aInternalReferenceNumber=@InternalReferenceNumber, " +
|
|
"aCustomerReferenceNumber=@CustomerReferenceNumber, " +
|
|
"aOnsite=@Onsite, aCustomerContactName=@CustomerContactName, " +
|
|
"aWorkOrderType=@WorkOrderType, aFormLayoutID=@FormLayoutID, " +
|
|
"aSummary=@Summary, aTemplateDescription=@TemplateDescription, aWorkorderCategoryID=@WorkorderCategoryID, " +
|
|
" aModifier=@CurrentUserID, " +
|
|
" aModified=@Modified, aClosed=@Closed, " +
|
|
"aServiceCompleted=@ServiceCompleted, aFromQuoteID=@FromQuoteID, aFromPMID=@FromPMID, aRegionID=@RegionID, " +
|
|
"ATEMPLATEFRESHPRICE=@TEMPLATEFRESHPRICE " + //case 3132
|
|
"WHERE aID=@ID"
|
|
);
|
|
|
|
|
|
|
|
//Workorder fields
|
|
cm.AddInParameter("@ID", DbType.Guid, mID);
|
|
cm.AddInParameter("@ClientID", DbType.Guid, mClientID);
|
|
cm.AddInParameter("@ProjectID", DbType.Guid, mProjectID);
|
|
cm.AddInParameter("@InternalReferenceNumber", DbType.String, mInternalReferenceNumber);
|
|
cm.AddInParameter("@CustomerReferenceNumber", DbType.String, mCustomerReferenceNumber);
|
|
cm.AddInParameter("@Onsite", DbType.Boolean, mOnsite);
|
|
cm.AddInParameter("@CustomerContactName", DbType.String, mCustomerContactName);
|
|
//case 58
|
|
cm.AddInParameter("@RegionID", DbType.Guid, mRegionID);
|
|
cm.AddInParameter("@Summary", DbType.String, mSummary);
|
|
cm.AddInParameter("@TemplateDescription", DbType.String, mTemplateDescription);
|
|
cm.AddInParameter("@FormLayoutID", DbType.Guid, mFormLayoutID);
|
|
cm.AddInParameter("@WorkorderType", DbType.Int16, (int)mWorkorderType);
|
|
cm.AddInParameter("@WorkorderCategoryID", DbType.Guid, mWorkorderCategoryID);
|
|
cm.AddInParameter("@ServiceCompleted", DbType.Boolean, mServiceCompleted);
|
|
cm.AddInParameter("@Closed", DbType.Boolean, mClosed);
|
|
cm.AddInParameter("@FromQuoteID", DbType.Guid, mFromQuoteID);
|
|
cm.AddInParameter("@FromPMID", DbType.Guid, mFromPMID);
|
|
|
|
|
|
//case 3132
|
|
cm.AddInParameter("@TEMPLATEFRESHPRICE", DbType.Boolean, mTemplateFreshPrice);
|
|
|
|
|
|
//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));
|
|
|
|
//Custom fields
|
|
// cm.AddLargeStringInParameter("@Custom1", mCustom1);
|
|
// cm.AddLargeStringInParameter("@Custom2", mCustom2);
|
|
// cm.AddLargeStringInParameter("@Custom3", mCustom3);
|
|
// cm.AddLargeStringInParameter("@Custom4", mCustom4);
|
|
// cm.AddLargeStringInParameter("@Custom5", mCustom5);
|
|
// cm.AddLargeStringInParameter("@Custom6", mCustom6);
|
|
// cm.AddLargeStringInParameter("@Custom7", mCustom7);
|
|
// cm.AddLargeStringInParameter("@Custom8", mCustom8);
|
|
// cm.AddLargeStringInParameter("@Custom9", mCustom9);
|
|
// cm.AddLargeStringInParameter("@Custom0", mCustom0);
|
|
|
|
|
|
|
|
|
|
using (IDbConnection connection = DBUtil.DB.GetConnection())
|
|
{
|
|
connection.Open();
|
|
//IDbTransaction transaction = connection.BeginTransaction();
|
|
//Changed to high isolation transaction because an update affects potentially inventory and
|
|
//service bank objects
|
|
IDbTransaction transaction = connection.BeginTransaction(System.Data.IsolationLevel.Serializable);
|
|
|
|
try
|
|
{
|
|
|
|
DBUtil.DB.ExecuteNonQuery(cm, transaction);
|
|
|
|
/*
|
|
* Update child objects
|
|
*/
|
|
|
|
switch (this.WorkorderType)
|
|
{
|
|
case WorkorderTypes.PreventiveMaintenance:
|
|
case WorkorderTypes.TemplatePreventiveMaintenance:
|
|
mWorkorderPreventiveMaintenance.Update(this, transaction);
|
|
break;
|
|
case WorkorderTypes.Quote:
|
|
case WorkorderTypes.TemplateQuote:
|
|
mQuote.Update(this, transaction);
|
|
|
|
break;
|
|
case WorkorderTypes.Service:
|
|
case WorkorderTypes.TemplateService:
|
|
mService.Update(this, transaction);
|
|
|
|
//Last service date / wo
|
|
//only set this if closed
|
|
//this prevents a situation where the workorder can not be deleted
|
|
//because of the foreign key link to the client lastworkorderid field
|
|
//because a closed workorder can not be deleted
|
|
if (this.mClosed)
|
|
{//unclose
|
|
DBCommandWrapper cmLastServiceClient = DBUtil.GetCommandFromSQL(
|
|
"UPDATE aClient SET aLastWorkorderID=@WorkorderID, " +
|
|
"aLastServiceDate=@LastServiceDate " +
|
|
"WHERE aID=@ClientID"
|
|
);
|
|
cmLastServiceClient.AddInParameter("@ClientID", DbType.Guid, mClientID);
|
|
cmLastServiceClient.AddInParameter("@WorkorderID", DbType.Guid, this.mID);
|
|
cmLastServiceClient.AddInParameter("@LastServiceDate", DbType.DateTime, DBUtil.ToUTC(mService.sdServiceDate).DBValue);
|
|
DBUtil.DB.ExecuteNonQuery(cmLastServiceClient, transaction);
|
|
|
|
foreach (WorkorderItem wi in this.mWorkorderItems)
|
|
{
|
|
if (wi.UnitID != Guid.Empty)
|
|
{//unclose
|
|
DBCommandWrapper cmLastServiceUnit = DBUtil.GetCommandFromSQL(
|
|
"UPDATE aUnit SET aLastWorkorderID=@WorkorderID, " +
|
|
"aLastServiceDate=@LastServiceDate " +
|
|
"WHERE aID=@UnitID"
|
|
);
|
|
cmLastServiceUnit.AddInParameter("@UnitID", DbType.Guid, wi.UnitID);
|
|
cmLastServiceUnit.AddInParameter("@WorkorderID", DbType.Guid, this.mID);
|
|
cmLastServiceUnit.AddInParameter("@LastServiceDate", DbType.DateTime, DBUtil.ToUTC(mService.sdServiceDate).DBValue);
|
|
DBUtil.DB.ExecuteNonQuery(cmLastServiceUnit, transaction);
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
//WorkorderItems collection
|
|
mWorkorderItems.Update(this, transaction);
|
|
|
|
//Docs
|
|
mDocs.Update(transaction);
|
|
|
|
//Process keywords
|
|
DBUtil.ProcessKeywords(transaction, this.mID, RootObjectTypes.Workorder, IsNew, AyaBizUtils.Break(false,
|
|
mInternalReferenceNumber, mCustomerReferenceNumber, mCustomerContactName, mSummary, mTemplateDescription));
|
|
|
|
//case 53
|
|
bWasNew = IsNew;
|
|
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;
|
|
|
|
switch (mWorkorderType)
|
|
{
|
|
case WorkorderTypes.Service:
|
|
if (AyaBizUtils.AllowAutomaticMRUOnUpdate) AyaBizUtils.MRU.Add(RootObjectTypes.Workorder, mID);
|
|
break;
|
|
case WorkorderTypes.Quote:
|
|
if (AyaBizUtils.AllowAutomaticMRUOnUpdate) AyaBizUtils.MRU.Add(RootObjectTypes.WorkorderQuote, WorkorderQuote.ID);
|
|
break;
|
|
case WorkorderTypes.PreventiveMaintenance:
|
|
if (AyaBizUtils.AllowAutomaticMRUOnUpdate) AyaBizUtils.MRU.Add(RootObjectTypes.WorkorderPreventiveMaintenance, WorkorderPreventiveMaintenance.ID);
|
|
break;
|
|
|
|
case WorkorderTypes.TemplateService:
|
|
if (AyaBizUtils.AllowAutomaticMRUOnUpdate) AyaBizUtils.MRU.Add(RootObjectTypes.WorkorderServiceTemplate, ID);
|
|
break;
|
|
case WorkorderTypes.TemplateQuote:
|
|
if (AyaBizUtils.AllowAutomaticMRUOnUpdate) AyaBizUtils.MRU.Add(RootObjectTypes.WorkorderQuoteTemplate, WorkorderQuote.ID);
|
|
break;
|
|
case WorkorderTypes.TemplatePreventiveMaintenance:
|
|
if (AyaBizUtils.AllowAutomaticMRUOnUpdate) AyaBizUtils.MRU.Add(RootObjectTypes.WorkorderPreventiveMaintenanceTemplate, WorkorderPreventiveMaintenance.ID);
|
|
break;
|
|
}
|
|
|
|
if (this.Closed)
|
|
ClientServiceRequest.CloseFlag(this.mID);
|
|
|
|
#region Process events
|
|
//Process events as necessary
|
|
if (AyaBizUtils.GlobalSettings.UseNotification)//Case 510
|
|
{
|
|
#region Service type workorder notification events
|
|
if (mWorkorderType == WorkorderTypes.Service && this.mService != null)
|
|
{
|
|
//there are three types of events that might be of interest
|
|
|
|
//Case 53 new event of interest - workorder created
|
|
if (bWasNew)
|
|
{
|
|
ClientNotifyEvent.ProcessEvent(ClientNotifyEventType.NewWorkorder, mClientID, mService.WorkorderStatusID,
|
|
mService.ServiceNumber.ToString(),
|
|
mCustomerContactName, mCustomerReferenceNumber, "", mID, mSummary, "");
|
|
}
|
|
|
|
//Has the status changed?
|
|
if (mService.mStatusSignificant)
|
|
{
|
|
NotifyEvent.AddOrUpdateEvent(RootObjectTypes.Workorder, this.mID, (int)WorkorderEvent.Status, Guid.Empty, new SmartDate(), mService.WorkorderStatusID);
|
|
|
|
ClientNotifyEvent.ProcessEvent(ClientNotifyEventType.WorkorderStatusSet, mClientID, mService.WorkorderStatusID,
|
|
mService.ServiceNumber.ToString(),
|
|
mCustomerContactName, mCustomerReferenceNumber, "", mID, mSummary, "");
|
|
|
|
//case 1879 - multiple events showing up on repeated save of same workorder edit session
|
|
mService.mStatusSignificant = false;
|
|
}
|
|
|
|
//Has it been closed?
|
|
if (Closed)
|
|
{
|
|
//Yes, so
|
|
//remove close by events if present
|
|
//This is ok even if it's passed and closed later
|
|
//because they would have got the notice about it being passed
|
|
//so in any case we want the event gone
|
|
NotifyEvent.RemoveSpecificEventForObject(mID, (int)WorkorderEvent.CloseByDatePassed);
|
|
|
|
//Workorder is closed adn we're in the upate method so clearly it was open and has now just been closed and saved
|
|
//since a closed workorder can not be updated
|
|
//case 53
|
|
|
|
//unclose
|
|
ClientNotifyEvent.ProcessEvent(ClientNotifyEventType.WorkorderClosed, mClientID, mService.WorkorderStatusID,
|
|
mService.ServiceNumber.ToString(),
|
|
mCustomerContactName, mCustomerReferenceNumber, "", mID, mSummary, "");
|
|
ClientNotifyEvent.ProcessEvent(ClientNotifyEventType.WorkorderFollowUp, mClientID, mService.WorkorderStatusID,
|
|
mService.ServiceNumber.ToString(),
|
|
mCustomerContactName, mCustomerReferenceNumber, "", mID, mSummary, "");
|
|
|
|
}
|
|
else
|
|
{
|
|
//Nope,so set the close by date event if significant (changed)
|
|
if (mService.mCloseByDateSignificant)
|
|
{
|
|
//Check if user set it to empty,
|
|
//in which case we don't want any event for this
|
|
if (mService.sdCloseByDate.IsEmpty)
|
|
NotifyEvent.RemoveSpecificEventForObject(mID, (int)WorkorderEvent.CloseByDatePassed);
|
|
else
|
|
NotifyEvent.AddOrUpdateEvent(RootObjectTypes.Workorder, this.mID, (int)WorkorderEvent.CloseByDatePassed, Guid.Empty, mService.sdCloseByDate, Guid.Empty);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
#endregion service workorder notification processor
|
|
|
|
#region Quote type workorder notification events
|
|
if (mWorkorderType == WorkorderTypes.Quote && this.mQuote != null)
|
|
{
|
|
//Has the status changed?
|
|
if (mQuote.mStatusSignificant)
|
|
{
|
|
|
|
ClientNotifyEvent.ProcessEvent(ClientNotifyEventType.QuoteStatusSet, mClientID, Guid.Empty, mQuote.QuoteNumber.ToString(),
|
|
mCustomerContactName, mCustomerReferenceNumber, "", mID, mSummary, "", mQuote.QuoteStatus);
|
|
}
|
|
|
|
|
|
//case 1555
|
|
//User quote updated notification
|
|
NotifyEvent.AddOrUpdateEvent(RootObjectTypes.Workorder, this.mID, (int)WorkorderEvent.QuoteUpdated);
|
|
|
|
//case 2090 to be added here:?
|
|
//notification when quote is approved X days after
|
|
|
|
}
|
|
#endregion Quote workorder notification processor
|
|
|
|
}
|
|
#endregion
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
#endregion update
|
|
|
|
#endregion
|
|
|
|
#region Override IsValid / IsDirty
|
|
//Override base class version if there are child objects
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public override bool IsValid
|
|
{
|
|
get
|
|
{
|
|
|
|
switch (this.WorkorderType)
|
|
{
|
|
case WorkorderTypes.PreventiveMaintenance:
|
|
case WorkorderTypes.TemplatePreventiveMaintenance:
|
|
return base.IsValid && mWorkorderPreventiveMaintenance.IsValid &&
|
|
mWorkorderItems.IsValid && mDocs.IsValid;
|
|
case WorkorderTypes.Quote:
|
|
case WorkorderTypes.TemplateQuote:
|
|
return base.IsValid && mQuote.IsValid &&
|
|
mWorkorderItems.IsValid && mDocs.IsValid;
|
|
case WorkorderTypes.Service:
|
|
case WorkorderTypes.TemplateService:
|
|
return base.IsValid && mService.IsValid &&
|
|
mWorkorderItems.IsValid && mDocs.IsValid;
|
|
|
|
}
|
|
return false;
|
|
|
|
}
|
|
}
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public override bool IsDirty
|
|
{
|
|
get
|
|
{
|
|
switch (this.WorkorderType)
|
|
{
|
|
case WorkorderTypes.PreventiveMaintenance:
|
|
case WorkorderTypes.TemplatePreventiveMaintenance:
|
|
return base.IsDirty ||
|
|
mWorkorderPreventiveMaintenance.IsDirty ||
|
|
mWorkorderItems.IsDirty || mDocs.IsDirty;
|
|
case WorkorderTypes.Quote:
|
|
case WorkorderTypes.TemplateQuote:
|
|
return base.IsDirty || mQuote.IsDirty ||
|
|
mWorkorderItems.IsDirty || mDocs.IsDirty;
|
|
case WorkorderTypes.Service:
|
|
case WorkorderTypes.TemplateService:
|
|
return base.IsDirty || mService.IsDirty ||
|
|
mWorkorderItems.IsDirty || mDocs.IsDirty;
|
|
|
|
}
|
|
return false;
|
|
|
|
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region criteria
|
|
/// <summary>
|
|
/// Criteria for identifying existing object
|
|
/// </summary>
|
|
[Serializable]
|
|
private class Criteria
|
|
{
|
|
public bool TrackMRU;
|
|
public Guid ID;
|
|
public RootObjectTypes RootObjectType;
|
|
public Criteria(RootObjectTypes _RootObjectType, Guid _ID, bool _TrackMRU)
|
|
{
|
|
ID = _ID;
|
|
RootObjectType = _RootObjectType;
|
|
TrackMRU = _TrackMRU;
|
|
}
|
|
|
|
}
|
|
#endregion
|
|
|
|
#region Move WorkorderItem
|
|
#pragma warning disable 1591
|
|
|
|
/// <summary>
|
|
/// Move a workorder item to a new workorder
|
|
/// </summary>
|
|
[Serializable, System.ComponentModel.Browsable(false)]
|
|
public class WorkorderItemMover//DO_NOT_OBFUSCATE
|
|
{
|
|
Guid _ToWorkorderID;
|
|
Guid _FromWorkorderID;
|
|
Guid _WorkorderItemID;
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="FromWorkorderID"></param>
|
|
/// <param name="ToWorkorderID"></param>
|
|
/// <param name="WorkorderItemID"></param>
|
|
public WorkorderItemMover(Guid FromWorkorderID, Guid ToWorkorderID, Guid WorkorderItemID)
|
|
{
|
|
_FromWorkorderID = FromWorkorderID;
|
|
_ToWorkorderID = ToWorkorderID;
|
|
_WorkorderItemID = WorkorderItemID;
|
|
}
|
|
|
|
public static void Move(Guid FromWorkorderID, Guid ToWorkorderID, Guid WorkorderItemID)
|
|
{
|
|
DataPortal.Update(new WorkorderItemMover(FromWorkorderID, ToWorkorderID, WorkorderItemID));
|
|
}
|
|
|
|
public void DataPortal_Update()
|
|
{
|
|
DBCommandWrapper cm = null;
|
|
|
|
cm = DBUtil.GetCommandFromSQL(
|
|
"UPDATE aWorkorderItem SET aWorkorderID=@ToWorkorderID " +
|
|
"WHERE aWorkorderID=@FromWorkorderID AND aID=@WorkorderItemID"
|
|
);
|
|
|
|
cm.AddInParameter("@FromWorkorderID", DbType.Guid, _FromWorkorderID);
|
|
cm.AddInParameter("@ToWorkorderID", DbType.Guid, _ToWorkorderID);
|
|
cm.AddInParameter("@WorkorderItemID", DbType.Guid, _WorkorderItemID);
|
|
|
|
DBUtil.DB.ExecuteNonQuery(cm);
|
|
|
|
|
|
}
|
|
|
|
}
|
|
#endregion move workorder item
|
|
|
|
#region Re-open workorder
|
|
/// <summary>
|
|
/// Re-open a closed work order
|
|
///
|
|
/// Removes all User notification events for the workorder
|
|
///
|
|
/// Will not remove client notifications if pending because
|
|
/// they do not store the workorder ID, only an email message so
|
|
/// there is a possibility they will get sent out about a closed workorder
|
|
/// *after* the work order was reopened.
|
|
/// </summary>
|
|
[Serializable, System.ComponentModel.Browsable(false)]
|
|
public class WorkorderReopener//DO_NOT_OBFUSCATE
|
|
{
|
|
Guid _WorkorderID;
|
|
|
|
public WorkorderReopener(Guid WorkorderID)
|
|
{
|
|
_WorkorderID = WorkorderID;
|
|
}
|
|
|
|
public static void Open(Guid WorkorderID)
|
|
{
|
|
DataPortal.Update(new WorkorderReopener(WorkorderID));
|
|
}
|
|
|
|
public void DataPortal_Update()
|
|
{
|
|
|
|
DBCommandWrapper cm = null;
|
|
|
|
//reopen workorder
|
|
cm = DBUtil.GetCommandFromSQL(
|
|
"UPDATE aWorkorder SET aClosed=@FALSE " +
|
|
"WHERE aWorkorder.AID=@WorkorderID "
|
|
);
|
|
|
|
cm.AddInParameter("@WorkorderID", DbType.Guid, _WorkorderID);
|
|
cm.AddInParameter("@FALSE", DbType.Boolean, false);
|
|
|
|
DBUtil.DB.ExecuteNonQuery(cm);
|
|
|
|
//change client last workorder and service date if
|
|
//it was set to this workorder
|
|
cm = DBUtil.GetCommandFromSQL(
|
|
"UPDATE aClient SET aLastWorkorderID=NULL, " +
|
|
"aLastServiceDate=NULL " +
|
|
"WHERE aLastWorkorderID=@WorkorderID"
|
|
);
|
|
cm.AddInParameter("@WorkorderID", DbType.Guid, _WorkorderID);
|
|
DBUtil.DB.ExecuteNonQuery(cm);
|
|
|
|
//change unit last workorder and service date if it was set to this workorder
|
|
cm = DBUtil.GetCommandFromSQL(
|
|
"UPDATE aUnit SET aLastWorkorderID=NULL, " +
|
|
"aLastServiceDate=NULL " +
|
|
"WHERE aLastWorkorderID=@WorkorderID"
|
|
);
|
|
cm.AddInParameter("@WorkorderID", DbType.Guid, _WorkorderID);
|
|
DBUtil.DB.ExecuteNonQuery(cm);
|
|
|
|
NotifyEvent.RemoveAllEventsForObject(_WorkorderID);
|
|
|
|
}
|
|
|
|
}
|
|
#endregion reopen workorder
|
|
#pragma warning restore 1591
|
|
|
|
}//end Workorder
|
|
|
|
#region Notification events
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public enum WorkorderEvent : int
|
|
{
|
|
/// <summary>
|
|
/// Status changed on service workorder
|
|
/// </summary>
|
|
[Description("LT:Workorder.Label.Event.Status")]
|
|
Status = 1,
|
|
//CloseByDatePassed *is* a dated event, but it's not user selectable
|
|
//so that's why the enumeration value is 2 instead of 256.
|
|
/// <summary>
|
|
/// Close by date passed on service workorder
|
|
/// </summary>
|
|
[Description("LT:Workorder.Label.Event.CloseByDatePassed")]
|
|
CloseByDatePassed = 2,
|
|
/// <summary>
|
|
/// Quote updated event
|
|
/// </summary>
|
|
[Description("LT:Workorder.Label.Event.QuoteUpdated")]
|
|
QuoteUpdated = 3
|
|
|
|
|
|
}
|
|
|
|
#endregion
|
|
}//end namespace GZTW.AyaNova.BLL |