1794 lines
54 KiB
C#
1794 lines
54 KiB
C#
///////////////////////////////////////////////////////////
|
|
// PurchaseOrder.cs
|
|
// Implementation of Class PurchaseOrder
|
|
// CSLA type: Editable Root
|
|
// Created on: 07-Jun-2004 8:41:31 AM
|
|
// Object design: Joyce
|
|
// Coded: John 28-July-2004
|
|
///////////////////////////////////////////////////////////
|
|
|
|
using System;
|
|
using System.Data;
|
|
using CSLA.Data;
|
|
using GZTW.Data;
|
|
using CSLA;
|
|
using System.Threading;
|
|
using CSLA.Security;
|
|
|
|
namespace GZTW.AyaNova.BLL
|
|
{
|
|
/// <summary>
|
|
/// Purchase order object representing an order for parts
|
|
/// </summary>
|
|
[Serializable]
|
|
public class PurchaseOrder : BusinessBase {
|
|
|
|
#region Attributes
|
|
|
|
private bool bReadOnly;
|
|
private Guid mID;
|
|
private SmartDate mCreated;
|
|
private SmartDate mModified;
|
|
private Guid mCreator;
|
|
private Guid mModifier;
|
|
|
|
private string mNotes="";
|
|
private int mPONumber=0;
|
|
private string mReferenceNumber="";
|
|
private SmartDate mOrderedDate;
|
|
private SmartDate mExpectedReceiveDate;
|
|
private string mVendorMemo="";
|
|
//private decimal mFreight;
|
|
//private decimal mAdditionalCharges;
|
|
private Guid mDropShipToClientID;
|
|
private Guid mVendorID;
|
|
private PurchaseOrderItems mOrderItems;
|
|
//private bool mClosed;
|
|
private PurchaseOrderStatus mStatus;
|
|
|
|
//Custom fields
|
|
private string mCustom1="";
|
|
private string mCustom2="";
|
|
private string mCustom3="";
|
|
private string mCustom4="";
|
|
private string mCustom5="";
|
|
private string mCustom6="";
|
|
private string mCustom7="";
|
|
private string mCustom8="";
|
|
private string mCustom9="";
|
|
private string mCustom0="";
|
|
|
|
//Keep track of status when first created or opened this time around
|
|
//so that we know when the status has changed from not ordered to ordered
|
|
//and can therefore update the inventory etc
|
|
private PurchaseOrderStatus mPreviousStatus;
|
|
|
|
//case 49
|
|
private Guid mProjectID;
|
|
#endregion
|
|
|
|
#region Constructor
|
|
|
|
/// <summary>
|
|
/// Private constructor to prevent direct instantiation
|
|
/// </summary>
|
|
private PurchaseOrder()
|
|
{
|
|
|
|
|
|
|
|
//Set to read / write initially so that properties
|
|
//can be set
|
|
bReadOnly=false;
|
|
|
|
//New ID
|
|
mID = Guid.NewGuid();
|
|
|
|
mStatus=PurchaseOrderStatus.OpenNotYetOrdered;
|
|
mPreviousStatus=PurchaseOrderStatus.OpenNotYetOrdered;
|
|
|
|
mOrderItems=PurchaseOrderItems.NewItems();
|
|
mOrderedDate = new SmartDate(DBUtil.CurrentWorkingDateTime);
|
|
mExpectedReceiveDate=new SmartDate();
|
|
//mActualReceiveDate=new SmartDate();
|
|
|
|
//Set record history to defaults
|
|
mCreated = new SmartDate(DBUtil.CurrentWorkingDateTime);
|
|
mModified=new SmartDate();
|
|
mCreator=Guid.Empty;
|
|
mModifier=Guid.Empty;
|
|
|
|
//Pre-break the vendorID rule
|
|
VendorID=Guid.NewGuid();
|
|
VendorID=Guid.Empty;
|
|
|
|
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Business properties
|
|
|
|
|
|
/// <summary>
|
|
/// Purchase order items child collection
|
|
/// </summary>
|
|
public PurchaseOrderItems OrderItems
|
|
{
|
|
get
|
|
{
|
|
return mOrderItems;
|
|
}
|
|
}
|
|
|
|
/// <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>
|
|
/// Notes about PurchaseOrder
|
|
/// </summary>
|
|
public string Notes
|
|
{
|
|
get
|
|
{
|
|
return mNotes;
|
|
}
|
|
set
|
|
{
|
|
if(bReadOnly)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if(mNotes!=value)
|
|
{
|
|
mNotes = value;
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Status of purchase order
|
|
/// Any status change is valid
|
|
/// with the following exceptions:
|
|
/// If a P.O. status is currently:
|
|
/// ClosedFullReceived - can not be changed to anything
|
|
/// Any status beyond OpenNotYetOrdered can not be
|
|
/// changed back to OpenNotYetOrdered. I.E. once a P.O. is
|
|
/// OnOrder of some kind it can not be taken back to OpenNotYetOrdered
|
|
/// This ensures Purchase orders follow standard business practices for inventory control.
|
|
/// </summary>
|
|
public PurchaseOrderStatus Status
|
|
{
|
|
get
|
|
{
|
|
return mStatus;
|
|
}
|
|
set
|
|
{
|
|
if(bReadOnly ||
|
|
this.mStatus==PurchaseOrderStatus.ClosedFullReceived ||
|
|
(mStatus>PurchaseOrderStatus.OpenNotYetOrdered && value==PurchaseOrderStatus.OpenNotYetOrdered))
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
|
|
if(mStatus!=value)
|
|
{
|
|
|
|
mStatus = value;
|
|
MarkDirty();
|
|
//Lock down the items collection if the p.o.
|
|
//has progressed beyond opennotyetordered
|
|
if(mStatus>PurchaseOrderStatus.OpenNotYetOrdered)
|
|
this.mOrderItems.SetAllItemsReadOnly();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Notes that may be displayed or printied on po when sent to vendor
|
|
/// </summary>
|
|
public string VendorMemo
|
|
{
|
|
get
|
|
{
|
|
return mVendorMemo;
|
|
}
|
|
set
|
|
{
|
|
if(bReadOnly || this.mStatus > PurchaseOrderStatus.OpenOrdered)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if(mVendorMemo!=value)
|
|
{
|
|
mVendorMemo = value;
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Expected date of receiving
|
|
/// </summary>
|
|
public object ExpectedReceiveDate
|
|
{
|
|
get
|
|
{
|
|
return mExpectedReceiveDate.DBValue;
|
|
}
|
|
set
|
|
{
|
|
if(bReadOnly || this.mStatus > PurchaseOrderStatus.OpenOrdered)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if (!AyaBizUtils.SmartDateEquals(mExpectedReceiveDate, value)) //Case 298
|
|
{
|
|
mExpectedReceiveDate.DBValue = value;
|
|
BrokenRules.Assert("ExpectedReceiveDateRequired",
|
|
"Error.Object.RequiredFieldEmpty,PurchaseOrder.Label.ExpectedReceiveDate",
|
|
"ExpectedReceiveDate",mExpectedReceiveDate.IsEmpty);
|
|
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Internal version giving access to smartdate object
|
|
/// </summary>
|
|
internal SmartDate sdExpectedReceiveDate {get{return mExpectedReceiveDate;}}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Date PO was ordered. Defaults to date created, but may be edited
|
|
/// </summary>
|
|
public object OrderedDate
|
|
{
|
|
get
|
|
{
|
|
return mOrderedDate.DBValue;
|
|
}
|
|
set
|
|
{
|
|
if(bReadOnly || this.mStatus > PurchaseOrderStatus.OpenNotYetOrdered)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
|
|
if (!AyaBizUtils.SmartDateEquals(mOrderedDate, value)) //Case 298
|
|
{
|
|
mOrderedDate.DBValue = value;
|
|
BrokenRules.Assert("OrderedDateRequired",
|
|
"Error.Object.RequiredFieldEmpty,PurchaseOrder.Label.OrderedDate",
|
|
"OrderedDate",mOrderedDate.IsEmpty);
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Internal version giving access to smartdate object
|
|
/// </summary>
|
|
internal SmartDate sdOrderedDate {get{return mOrderedDate;}}
|
|
|
|
|
|
/// <summary>
|
|
/// Readonly as generated by AyaNova itself
|
|
///
|
|
/// </summary>
|
|
public int PONumber
|
|
{
|
|
get
|
|
{
|
|
return mPONumber;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Additional reference number for the PO to cooinside with PONumber
|
|
/// </summary>
|
|
public string ReferenceNumber
|
|
{
|
|
get
|
|
{
|
|
return mReferenceNumber;
|
|
}
|
|
set
|
|
{
|
|
if(bReadOnly || this.mStatus > PurchaseOrderStatus.OpenOrdered)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if(mReferenceNumber!=value)
|
|
{
|
|
mReferenceNumber = value;
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// If a drop shipment to a client this is the client
|
|
/// If Guid.Empty then it's a regular order
|
|
/// </summary>
|
|
public Guid DropShipToClientID
|
|
{
|
|
get
|
|
{
|
|
return mDropShipToClientID;
|
|
}
|
|
set
|
|
{
|
|
if(bReadOnly || this.mStatus > PurchaseOrderStatus.OpenOrdered )
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if(mDropShipToClientID!=value)
|
|
{
|
|
mDropShipToClientID = value;
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// True if a client was selected to drop ship to
|
|
/// (read only convenience flag)
|
|
/// </summary>
|
|
public bool IsDropShip//Case 447
|
|
{
|
|
get
|
|
{
|
|
return !mDropShipToClientID.Equals(Guid.Empty);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// ID of the <see cref="Vendor"/> for this PO
|
|
/// </summary>
|
|
public Guid VendorID
|
|
{
|
|
get
|
|
{
|
|
return mVendorID;
|
|
}
|
|
set
|
|
{
|
|
if(bReadOnly || this.mOrderItems.Count>0)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if(mVendorID!=value)
|
|
{
|
|
mVendorID = value;
|
|
BrokenRules.Assert("VendorIDRequired",
|
|
"Error.Object.RequiredFieldEmpty,PurchaseOrder.Label.VendorID",
|
|
"VendorID",mVendorID==Guid.Empty);
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
#region CUSTOM FIELDS
|
|
|
|
/// <summary>
|
|
/// Custom1
|
|
/// </summary>
|
|
public string Custom1
|
|
{
|
|
get
|
|
{
|
|
return mCustom1;
|
|
}
|
|
set
|
|
{
|
|
if(bReadOnly)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if(mCustom1!=value)
|
|
{
|
|
mCustom1 = value;
|
|
BrokenRules.Assert("Custom1Length",
|
|
"Error.Object.FieldLengthExceeded500,PurchaseOrder.Label.Custom1","Custom1",value.Length>500);
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Custom2
|
|
/// </summary>
|
|
public string Custom2
|
|
{
|
|
get
|
|
{
|
|
return mCustom2;
|
|
}
|
|
set
|
|
{
|
|
if(bReadOnly)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if(mCustom2!=value)
|
|
{
|
|
mCustom2 = value;
|
|
BrokenRules.Assert("Custom2Length",
|
|
"Error.Object.FieldLengthExceeded500,PurchaseOrder.Label.Custom2","Custom2",value.Length>500);
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Custom3
|
|
/// </summary>
|
|
public string Custom3
|
|
{
|
|
get
|
|
{
|
|
return mCustom3;
|
|
}
|
|
set
|
|
{
|
|
if(bReadOnly)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if(mCustom3!=value)
|
|
{
|
|
mCustom3 = value;
|
|
BrokenRules.Assert("Custom3Length",
|
|
"Error.Object.FieldLengthExceeded500,PurchaseOrder.Label.Custom3","Custom3",value.Length>500);
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Custom4
|
|
/// </summary>
|
|
public string Custom4
|
|
{
|
|
get
|
|
{
|
|
return mCustom4;
|
|
}
|
|
set
|
|
{
|
|
if(bReadOnly)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if(mCustom4!=value)
|
|
{
|
|
mCustom4 = value;
|
|
BrokenRules.Assert("Custom4Length",
|
|
"Error.Object.FieldLengthExceeded500,PurchaseOrder.Label.Custom4","Custom4",value.Length>500);
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Custom5
|
|
/// </summary>
|
|
public string Custom5
|
|
{
|
|
get
|
|
{
|
|
return mCustom5;
|
|
}
|
|
set
|
|
{
|
|
if(bReadOnly)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if(mCustom5!=value)
|
|
{
|
|
mCustom5 = value;
|
|
BrokenRules.Assert("Custom5Length",
|
|
"Error.Object.FieldLengthExceeded500,PurchaseOrder.Label.Custom5","Custom5",value.Length>500);
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Custom6
|
|
/// </summary>
|
|
public string Custom6
|
|
{
|
|
get
|
|
{
|
|
return mCustom6;
|
|
}
|
|
set
|
|
{
|
|
if(bReadOnly)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if(mCustom6!=value)
|
|
{
|
|
mCustom6 = value;
|
|
BrokenRules.Assert("Custom6Length",
|
|
"Error.Object.FieldLengthExceeded500,PurchaseOrder.Label.Custom6","Custom6",value.Length>500);
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Custom7
|
|
/// </summary>
|
|
public string Custom7
|
|
{
|
|
get
|
|
{
|
|
return mCustom7;
|
|
}
|
|
set
|
|
{
|
|
if(bReadOnly)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if(mCustom7!=value)
|
|
{
|
|
mCustom7 = value;
|
|
BrokenRules.Assert("Custom7Length",
|
|
"Error.Object.FieldLengthExceeded500,PurchaseOrder.Label.Custom7","Custom7",value.Length>500);
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Custom8
|
|
/// </summary>
|
|
public string Custom8
|
|
{
|
|
get
|
|
{
|
|
return mCustom8;
|
|
}
|
|
set
|
|
{
|
|
if(bReadOnly)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if(mCustom8!=value)
|
|
{
|
|
mCustom8 = value;
|
|
BrokenRules.Assert("Custom8Length",
|
|
"Error.Object.FieldLengthExceeded500,PurchaseOrder.Label.Custom8","Custom8",value.Length>500);
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Custom9
|
|
/// </summary>
|
|
public string Custom9
|
|
{
|
|
get
|
|
{
|
|
return mCustom9;
|
|
}
|
|
set
|
|
{
|
|
if(bReadOnly)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if(mCustom9!=value)
|
|
{
|
|
mCustom9 = value;
|
|
BrokenRules.Assert("Custom9Length",
|
|
"Error.Object.FieldLengthExceeded500,PurchaseOrder.Label.Custom9","Custom9",value.Length>500);
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Custom0
|
|
/// </summary>
|
|
public string Custom0
|
|
{
|
|
get
|
|
{
|
|
return mCustom0;
|
|
}
|
|
set
|
|
{
|
|
if(bReadOnly)
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if(mCustom0!=value)
|
|
{
|
|
mCustom0 = value;
|
|
BrokenRules.Assert("Custom0Length",
|
|
"Error.Object.FieldLengthExceeded500,PurchaseOrder.Label.Custom0","Custom0",value.Length>500);
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
//case 29
|
|
/// <summary>
|
|
/// A List of Guid's of parts selected
|
|
/// anywhere in this purchase order.
|
|
///
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public System.Collections.Generic.List<Guid> ListOfPartsSelected()
|
|
{
|
|
System.Collections.Generic.List<Guid> l = new System.Collections.Generic.List<Guid>();
|
|
|
|
foreach (PurchaseOrderItem i in this.OrderItems)
|
|
{
|
|
if (!l.Contains(i.PartID))
|
|
l.Add(i.PartID);
|
|
}
|
|
return l;
|
|
}
|
|
|
|
|
|
//case 49
|
|
/// <summary>
|
|
/// Project to attribute to this purchase order
|
|
/// </summary>
|
|
public Guid ProjectID
|
|
{
|
|
get
|
|
{
|
|
return mProjectID;
|
|
}
|
|
set
|
|
{
|
|
if (bReadOnly )
|
|
ThrowSetError();
|
|
else
|
|
{
|
|
if (mProjectID != value)
|
|
{
|
|
mProjectID = value;
|
|
MarkDirty();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// True if user has edit rights
|
|
/// </summary>
|
|
public bool HasEditRights//Case 412
|
|
{
|
|
get
|
|
{
|
|
return AyaBizUtils.Right("Object.PurchaseOrder") > (int)SecurityLevelTypes.ReadOnly;
|
|
|
|
}
|
|
}
|
|
|
|
/// <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.PurchaseOrder")
|
|
)
|
|
);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region System.object overrides
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public override string ToString()
|
|
{
|
|
return "PurchaseOrder" + mID.ToString();
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="obj"></param>
|
|
/// <returns></returns>
|
|
public override bool Equals(Object obj)
|
|
{
|
|
if ( obj == null || GetType ( ) != obj.GetType ( ) ) return false;
|
|
PurchaseOrder c=(PurchaseOrder)obj;
|
|
return mID==c.mID;
|
|
}
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public override int GetHashCode()
|
|
{
|
|
return ("PurchaseOrder"+mID).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)
|
|
{
|
|
|
|
|
|
|
|
if(AyaBizUtils.Right("Object.PurchaseOrder")<(int)SecurityLevelTypes.ReadOnly)
|
|
return new SearchResult();
|
|
|
|
|
|
SearchResult sr=new SearchResult();
|
|
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
|
SafeDataReader dr = null;
|
|
try
|
|
{
|
|
dr=DBUtil.GetReaderFromSQLString(
|
|
|
|
"SELECT aPurchaseOrder.aCreated, aPurchaseOrder.aModified, " +
|
|
"aPurchaseOrder.aCreator, " +
|
|
" aPurchaseOrder.aModifier, aVendor.aName, " +
|
|
" aPurchaseOrder.aReferenceNumber, aPurchaseOrder.aNotes, " +
|
|
" aPurchaseOrder.aCustom1, aPurchaseOrder.aCustom2, " +
|
|
" aPurchaseOrder.aCustom3, aPurchaseOrder.aCustom4, " +
|
|
" aPurchaseOrder.aCustom5, " +
|
|
" aPurchaseOrder.aCustom6, aPurchaseOrder.aCustom7, " +
|
|
" aPurchaseOrder.aCustom8, aPurchaseOrder.aCustom9, " +
|
|
" aPurchaseOrder.aCustom0 FROM aPurchaseOrder " +
|
|
"LEFT OUTER JOIN aVendor ON aPurchaseOrder.aVendorID " +
|
|
"= aVendor.aID WHERE (aPurchaseOrder.aID " +
|
|
"= @ID)"
|
|
,ID);
|
|
|
|
if(!dr.Read())
|
|
return new SearchResult();//DBUtil.ThrowFetchError("SearchResult for PurchaseOrderID: " + ID.ToString());
|
|
|
|
|
|
//slightly re-arranged following 10/3/2014 to include the ref number in the description
|
|
sb.Append(dr.GetString("aName"));
|
|
sb.Append(" ");
|
|
sb.Append(dr.GetString("aReferenceNumber"));
|
|
sr.Description = sb.ToString();
|
|
|
|
sb.Append(" ");
|
|
|
|
sb.Append(dr.GetString("aNotes"));
|
|
sb.Append(" ");
|
|
|
|
|
|
sb.Append(dr.GetString("aCustom0"));
|
|
sb.Append(" ");
|
|
sb.Append(dr.GetString("aCustom1"));
|
|
sb.Append(" ");
|
|
sb.Append(dr.GetString("aCustom2"));
|
|
sb.Append(" ");
|
|
sb.Append(dr.GetString("aCustom3"));
|
|
sb.Append(" ");
|
|
sb.Append(dr.GetString("aCustom4"));
|
|
sb.Append(" ");
|
|
sb.Append(dr.GetString("aCustom5"));
|
|
sb.Append(" ");
|
|
sb.Append(dr.GetString("aCustom6"));
|
|
sb.Append(" ");
|
|
sb.Append(dr.GetString("aCustom7"));
|
|
sb.Append(" ");
|
|
sb.Append(dr.GetString("aCustom8"));
|
|
sb.Append(" ");
|
|
sb.Append(dr.GetString("aCustom9"));
|
|
|
|
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.PurchaseOrder;
|
|
|
|
return sr;
|
|
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Static methods
|
|
|
|
|
|
/// <summary>
|
|
/// Create new PurchaseOrder
|
|
/// </summary>
|
|
/// <returns>PurchaseOrder</returns>
|
|
public static PurchaseOrder NewItem()
|
|
{
|
|
PurchaseOrder c;
|
|
|
|
if(AyaBizUtils.Right("Object.PurchaseOrder")>(int)SecurityLevelTypes.ReadOnly)
|
|
{
|
|
c = new PurchaseOrder();
|
|
|
|
return c;
|
|
}
|
|
else
|
|
throw new System.Security.SecurityException(
|
|
string.Format(
|
|
LocalizedTextTable.GetLocalizedTextDirect("Error.Security.NotAuthorizedToCreate"),
|
|
LocalizedTextTable.GetLocalizedTextDirect("O.PurchaseOrder")));
|
|
|
|
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Fetch existing PurchaseOrder
|
|
/// </summary>
|
|
/// <returns>PurchaseOrder</returns>
|
|
/// <param name="_ID">PurchaseOrder Guid</param>
|
|
public static PurchaseOrder GetItem(Guid _ID)
|
|
{
|
|
if (_ID == AyaBizUtils.NewObjectGuid)
|
|
return NewItem();
|
|
|
|
if(AyaBizUtils.Right("Object.PurchaseOrder")>(int)SecurityLevelTypes.NoAccess)
|
|
return (PurchaseOrder)DataPortal.Fetch(new Criteria(_ID));
|
|
else
|
|
throw new System.Security.SecurityException(
|
|
string.Format(
|
|
LocalizedTextTable.GetLocalizedTextDirect("Error.Security.NotAuthorizedToRetrieve"),
|
|
LocalizedTextTable.GetLocalizedTextDirect("O.PurchaseOrder")));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Delete PurchaseOrder
|
|
/// </summary>
|
|
/// <param name="_ID">PurchaseOrder GUID</param>
|
|
public static void DeleteItem(Guid _ID)
|
|
{
|
|
|
|
if(AyaBizUtils.Right("Object.PurchaseOrder")>(int)SecurityLevelTypes.ReadWrite)
|
|
DataPortal.Delete(new Criteria(_ID));
|
|
else
|
|
throw new System.Security.SecurityException(
|
|
string.Format(
|
|
LocalizedTextTable.GetLocalizedTextDirect("Error.Security.NotAuthorizedToDelete"),
|
|
LocalizedTextTable.GetLocalizedTextDirect("O.PurchaseOrder")));
|
|
}
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="newID"></param>
|
|
public static void SetVisibleIDNumber(int newID)
|
|
{
|
|
VisibleIDNumber.SetVisibleIDNumber(newID);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region DAL DATA ACCESS
|
|
|
|
#region Fetch
|
|
///
|
|
/// <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;
|
|
|
|
try
|
|
{
|
|
dr=DBUtil.GetReaderFromSQLString("SELECT * FROM aPurchaseOrder WHERE aID=@ID;",crit.ID);
|
|
if(!dr.Read())
|
|
DBUtil.ThrowFetchError("PurchaseOrder ID: " + crit.ID.ToString());
|
|
|
|
//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");
|
|
|
|
|
|
//Custom fields
|
|
mCustom1=dr.GetString("aCustom1");
|
|
mCustom2=dr.GetString("aCustom2");
|
|
mCustom3=dr.GetString("aCustom3");
|
|
mCustom4=dr.GetString("aCustom4");
|
|
mCustom5=dr.GetString("aCustom5");
|
|
mCustom6=dr.GetString("aCustom6");
|
|
mCustom7=dr.GetString("aCustom7");
|
|
mCustom8=dr.GetString("aCustom8");
|
|
mCustom9=dr.GetString("aCustom9");
|
|
mCustom0=dr.GetString("aCustom0");
|
|
|
|
//PurchaseOrder fields
|
|
mNotes=dr.GetString("aNotes");
|
|
mPONumber=dr.GetInt32("aPONumber");
|
|
mReferenceNumber=dr.GetString("aReferenceNumber");
|
|
mOrderedDate=DBUtil.ToLocal(dr.GetSmartDate("aOrderedDate"));
|
|
mExpectedReceiveDate=DBUtil.ToLocal(dr.GetSmartDate("aExpectedReceiveDate"));
|
|
mVendorMemo=dr.GetString("aVendorMemo");
|
|
mDropShipToClientID=dr.GetGuid("aDropShipToClientID");
|
|
|
|
//Unbreak vendorID rule:
|
|
VendorID=dr.GetGuid("aVendorID");
|
|
|
|
mProjectID = dr.GetGuid("aProjectID");//case 49
|
|
|
|
mStatus=(PurchaseOrderStatus)dr.GetInt16("aStatus");
|
|
//used when saving to Process inventory changes if applicable status
|
|
//change
|
|
mPreviousStatus=mStatus;
|
|
if(dr!=null) dr.Close();
|
|
|
|
//Fetch child collection
|
|
dr=DBUtil.GetReaderFromSQLString(
|
|
"SELECT aPurchaseOrderItem.*, aPart.aPartNumber, " +
|
|
" aPart.aManufacturerNumber, aPart.aWholesalerNumber, " +
|
|
" aPart.AALTERNATIVEWHOLESALERNUMBER, " +
|
|
" aPart.aCost AS aPARTCOST, aVendor.aName " +
|
|
"AS aMANUFACTURERNAME, aWorkorderService.aServiceNumber " +
|
|
|
|
"FROM " +
|
|
"APURCHASEORDERITEM " +
|
|
" LEFT OUTER JOIN APART ON (APURCHASEORDERITEM.APARTID=APART.AID) " +
|
|
" LEFT OUTER JOIN AVENDOR ON (APART.AMANUFACTURERID=AVENDOR.AID) " +
|
|
" LEFT OUTER JOIN AWORKORDERITEMPARTREQUEST ON (AWORKORDERITEMPARTREQUEST.AID=APURCHASEORDERITEM.AWORKORDERITEMPARTREQUESTID) " +
|
|
" LEFT OUTER JOIN AWORKORDERITEM ON (AWORKORDERITEMPARTREQUEST.AWORKORDERITEMID=AWORKORDERITEM.AID) " +
|
|
" LEFT OUTER JOIN AWORKORDERSERVICE ON (AWORKORDERITEM.AWORKORDERID=AWORKORDERSERVICE.AWORKORDERID) " +
|
|
|
|
"WHERE (aPurchaseOrderItem.aPurchaseOrderID " +
|
|
"= @ID)"
|
|
,crit.ID);
|
|
|
|
|
|
mOrderItems=PurchaseOrderItems.GetItems(dr);
|
|
if(dr!=null) dr.Close();
|
|
|
|
|
|
|
|
}
|
|
finally
|
|
{
|
|
if(dr!=null) dr.Close();
|
|
}
|
|
MarkOld();
|
|
|
|
|
|
//Get access rights level
|
|
bReadOnly=AyaBizUtils.Right("Object.PurchaseOrder")<(int)SecurityLevelTypes.ReadWrite;
|
|
|
|
//Lock down the children?
|
|
if(bReadOnly || this.mStatus>PurchaseOrderStatus.OpenNotYetOrdered)
|
|
mOrderItems.SetAllItemsReadOnly();
|
|
}
|
|
#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,"aPurchaseOrder");
|
|
|
|
#region Delete (but only if not ordered yet)
|
|
if(IsDeleted)
|
|
{
|
|
if(mStatus>PurchaseOrderStatus.OpenNotYetOrdered)
|
|
throw new System.ApplicationException
|
|
(
|
|
LocalizedTextTable.GetLocalizedTextDirect("PurchaseOrder.Label.Error.Locked")
|
|
);
|
|
if(!IsNew)
|
|
{
|
|
|
|
|
|
//Delete object and child objects
|
|
DBCommandWrapper cmDelete = DBUtil.GetCommandFromSQL("DELETE FROM aPurchaseOrder WHERE aID = @ID;");
|
|
cmDelete.AddInParameter("@ID",DbType.Guid,this.mID);
|
|
|
|
//Delete all child items
|
|
DBCommandWrapper cmDeleteItems = DBUtil.GetCommandFromSQL("DELETE FROM aPurchaseOrderItem WHERE aPurchaseOrderID=@ID;");
|
|
cmDeleteItems.AddInParameter("@ID",DbType.Guid,this.mID);
|
|
|
|
using (IDbConnection connection = DBUtil.DB.GetConnection())
|
|
{
|
|
connection.Open();
|
|
IDbTransaction transaction = connection.BeginTransaction();
|
|
|
|
try
|
|
{
|
|
DBUtil.DB.ExecuteNonQuery(cmDeleteItems, transaction);
|
|
DBUtil.DB.ExecuteNonQuery(cmDelete, transaction);
|
|
|
|
DBUtil.RemoveKeywords(transaction,RootObjectTypes.PurchaseOrder,this.mID);
|
|
//case 480
|
|
DBUtil.RemoveDocs(transaction, RootObjectTypes.PurchaseOrder, this.mID);
|
|
// Commit the transaction
|
|
transaction.Commit();
|
|
}
|
|
catch
|
|
{
|
|
// Rollback transaction
|
|
transaction.Rollback();
|
|
throw;
|
|
}
|
|
finally
|
|
{
|
|
connection.Close();
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------
|
|
}
|
|
MarkNew();
|
|
return;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Add / Update (But only partially if already ordered)
|
|
|
|
//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 aPurchaseOrder (aVendorMemo, aDropShipToClientID, " +
|
|
"aID, aReferenceNumber, aVendorID, aOrderedDate, " +
|
|
"aExpectedReceiveDate, aStatus, aNotes, aCreated,aModified,aCreator, " +
|
|
"aModifier, aCustom1, aCustom2, aCustom3, " +
|
|
"aCustom4, aCustom5, aCustom6, aCustom7, aCustom8, " +
|
|
"aCustom9, aCustom0, aProjectID) VALUES (@VendorMemo,@DropShipToClientID, " +
|
|
"@ID,@ReferenceNumber,@VendorID,@OrderedDate, " +
|
|
"@ExpectedReceiveDate,@Status,@Notes,@Created, @Modified, @CurrentUserID, " +
|
|
"@CurrentUserID, @Custom1,@Custom2,@Custom3, " +
|
|
"@Custom4,@Custom5,@Custom6,@Custom7,@Custom8,@Custom9, " +
|
|
"@Custom0, @ProjectID)"//case 49
|
|
);
|
|
else
|
|
cm=DBUtil.GetCommandFromSQL(
|
|
"UPDATE aPurchaseOrder SET aVendorMemo=@VendorMemo, " +
|
|
"aDropShipToClientID=@DropShipToClientID, aID=@ID, " +
|
|
"aReferenceNumber=@ReferenceNumber, aVendorID=@VendorID, " +
|
|
"aOrderedDate=@OrderedDate, aExpectedReceiveDate=@ExpectedReceiveDate, " +
|
|
"aStatus=@Status, " +
|
|
"aNotes=@Notes, aModifier=@CurrentUserID, aModified=@Modified, " +
|
|
"aCustom1=@Custom1, aCustom2=@Custom2, " +
|
|
"aCustom3=@Custom3, aCustom4=@Custom4, aCustom5=@Custom5, " +
|
|
"aCustom6=@Custom6, aCustom7=@Custom7, " +
|
|
"aCustom8=@Custom8, aCustom9=@Custom9, aCustom0=@Custom0, aProjectID=@ProjectID " +//case 49
|
|
"WHERE aID=@ID"
|
|
);
|
|
|
|
|
|
|
|
cm.AddInParameter("@ID",DbType.Guid,mID);
|
|
cm.AddLargeStringInParameter("@Notes", mNotes);
|
|
cm.AddInParameter("@ReferenceNumber",DbType.String,mReferenceNumber);
|
|
cm.AddInParameter("@OrderedDate",DbType.DateTime,DBUtil.ToUTC(mOrderedDate).DBValue);
|
|
cm.AddInParameter("@ExpectedReceiveDate",DbType.DateTime,DBUtil.ToUTC(mExpectedReceiveDate).DBValue);
|
|
cm.AddInParameter("@VendorMemo",DbType.String,mVendorMemo);
|
|
cm.AddInParameter("@DropShipToClientID",DbType.Guid,mDropShipToClientID);
|
|
cm.AddInParameter("@VendorID",DbType.Guid,mVendorID);
|
|
cm.AddInParameter("@Status",DbType.Int16,(int)mStatus);
|
|
cm.AddInParameter("@ProjectID", DbType.Guid, mProjectID);//case 49
|
|
|
|
//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();
|
|
//Affects inventory so a serializable isolation level required for
|
|
//the transaction
|
|
IDbTransaction transaction = connection.BeginTransaction(System.Data.IsolationLevel.Serializable);
|
|
bool bGetIdentity=IsNew;
|
|
try
|
|
{
|
|
DBUtil.DB.ExecuteNonQuery(cm, transaction);
|
|
//Update items if they are updateable
|
|
mOrderItems.Update(this, transaction);
|
|
|
|
//Status changed update affected external objects special handling
|
|
|
|
#region Status change from not ordered to ordered Inventory and other object updates
|
|
if (this.mStatus>PurchaseOrderStatus.OpenNotYetOrdered && mPreviousStatus == PurchaseOrderStatus.OpenNotYetOrdered)
|
|
{
|
|
//Update inventory affected items
|
|
foreach(PurchaseOrderItem poi in mOrderItems)
|
|
{
|
|
|
|
//get the current inventory values for later updating
|
|
PartByWarehouseInventoryValuesFetcher invent=
|
|
PartByWarehouseInventoryValuesFetcher.GetItem(
|
|
poi.PartID,poi.PartWarehouseID,transaction
|
|
);
|
|
|
|
//is it a workorder item part request
|
|
//initiated po item?
|
|
if(poi.WorkorderItemPartRequestID!=Guid.Empty) //Yes
|
|
{
|
|
#region Update part request
|
|
DBCommandWrapper cmUpdateRequest =DBUtil.GetCommandFromSQL(
|
|
"UPDATE aWorkorderItemPartRequest SET aPurchaseOrderItemID=@PurchaseOrderItemID, " +
|
|
"aModifier=@CurrentUserID, aModified=@Modified WHERE aID=@ID"
|
|
);
|
|
|
|
//WorkorderItemPartRequest specific
|
|
cmUpdateRequest.AddInParameter("@ID",DbType.Guid,poi.WorkorderItemPartRequestID);
|
|
cmUpdateRequest.AddInParameter("@PurchaseOrderItemID",DbType.Guid,poi.ID);
|
|
|
|
//standard parameters
|
|
cmUpdateRequest.AddInParameter("@CurrentUserID",DbType.Guid, CurrentUserID);
|
|
cmUpdateRequest.AddInParameter("@Modified",DbType.DateTime, DBUtil.ToUTC(dtModified));
|
|
DBUtil.DB.ExecuteNonQuery(cmUpdateRequest, transaction);
|
|
#endregion
|
|
|
|
#region Update inventory quantity on order committed (because it's committed to a workorderitempartrequest)
|
|
|
|
//Update...
|
|
DBCommandWrapper cmUpdateInventoryCommitted = null;
|
|
cmUpdateInventoryCommitted = DBUtil.GetCommandFromSQL(
|
|
"UPDATE aPartByWarehouseInventory SET aQtyOnOrderCommitted=@NewQuantity, " +
|
|
"aModifier=@CurrentUserID, aModified=@Modified " +
|
|
"WHERE (aPartID = @PartID) AND (aPartWarehouseID " +
|
|
"= @PartWarehouseID)"
|
|
);
|
|
cmUpdateInventoryCommitted.AddInParameter("@PartID",DbType.Guid,poi.PartID);
|
|
cmUpdateInventoryCommitted.AddInParameter("@PartWarehouseID",DbType.Guid,poi.PartWarehouseID);
|
|
cmUpdateInventoryCommitted.AddInParameter("@CurrentUserID",DbType.Guid, CurrentUserID);
|
|
cmUpdateInventoryCommitted.AddInParameter("@Modified",DbType.DateTime, DBUtil.ToUTC(dtModified));
|
|
cmUpdateInventoryCommitted.AddInParameter("@NewQuantity",DbType.Decimal,invent.QtyOnOrderCommitted+poi.QuantityOrdered);
|
|
DBUtil.DB.ExecuteNonQuery(cmUpdateInventoryCommitted, transaction);
|
|
|
|
#endregion
|
|
|
|
}
|
|
else
|
|
{//No, just a regular order for more stock
|
|
#region Update inventory quantity on order
|
|
|
|
//Update...
|
|
DBCommandWrapper cmUpdateInventoryOnOrder = null;
|
|
cmUpdateInventoryOnOrder = DBUtil.GetCommandFromSQL(
|
|
"UPDATE aPartByWarehouseInventory SET aQuantityOnOrder=@NewQuantity, " +
|
|
"aModifier=@CurrentUserID, aModified=@Modified " +
|
|
"WHERE (aPartID = @PartID) AND (aPartWarehouseID " +
|
|
"= @PartWarehouseID)"
|
|
);
|
|
cmUpdateInventoryOnOrder.AddInParameter("@PartID",DbType.Guid,poi.PartID);
|
|
cmUpdateInventoryOnOrder.AddInParameter("@PartWarehouseID",DbType.Guid,poi.PartWarehouseID);
|
|
cmUpdateInventoryOnOrder.AddInParameter("@CurrentUserID",DbType.Guid, CurrentUserID);
|
|
cmUpdateInventoryOnOrder.AddInParameter("@Modified",DbType.DateTime, DBUtil.ToUTC(dtModified));
|
|
cmUpdateInventoryOnOrder.AddInParameter("@NewQuantity",DbType.Decimal,invent.QuantityOnOrder+poi.QuantityOrdered);
|
|
DBUtil.DB.ExecuteNonQuery(cmUpdateInventoryOnOrder, transaction);
|
|
|
|
#endregion
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion status change from not ordered to ordered
|
|
|
|
#region case 564 - Status change to closed but not fully received handle incomplete orders
|
|
|
|
System.Collections.Generic.List<Guid> poItemsToDeleteList = new System.Collections.Generic.List<Guid>();
|
|
|
|
//case 3588 more foot-shooting prevention code required
|
|
if (this.IsNew && this.mStatus > PurchaseOrderStatus.OpenPartialReceived && mPreviousStatus == PurchaseOrderStatus.OpenNotYetOrdered)
|
|
{
|
|
//Ok, so the block of code immediately below prior to this case is only running when the po was saved otherwise the
|
|
//mPreviousStatus is openNotYetOrdered which causes the code block to not execute but we want it to execute
|
|
//so the solution is to change the mPreviousStatus to OpenOrdered in order to trigger the code block
|
|
//It won't update the db that way as it's mpreviousstatus doesn't get saved anwyhere it's only for control through this DataPortal_update anyway
|
|
mPreviousStatus = PurchaseOrderStatus.OpenOrdered;
|
|
|
|
}
|
|
|
|
|
|
//case 3738 if user doesn't reload this object previousstatus is out of whack and following block won't run so set on successful commit below
|
|
//case 564
|
|
if (this.mStatus > PurchaseOrderStatus.OpenPartialReceived
|
|
&& mPreviousStatus > PurchaseOrderStatus.OpenNotYetOrdered && mPreviousStatus < PurchaseOrderStatus.ClosedPartialReceived)
|
|
//i.e. was on order b4 and not closed in any way and now closed in some way
|
|
{
|
|
//case 3739
|
|
bool bOrderItemsNeedToBeSavedAgain = false;
|
|
//normally items are read only at this point because of status so need to change
|
|
//temporarily
|
|
bool bOrderItemsWasReadOnly = mOrderItems.IsLocked;
|
|
if(bOrderItemsWasReadOnly)
|
|
mOrderItems.SetAllItemsWrite();
|
|
|
|
//Update inventory affected items
|
|
foreach (PurchaseOrderItem poi in mOrderItems)
|
|
{
|
|
//is this poitem incomplete?
|
|
if (poi.QuantityOrdered > 0 && poi.QuantityReceived < poi.QuantityOrdered)
|
|
{
|
|
|
|
//case 1918
|
|
poi.OverrideIsLockedForInternalUpdate = true;
|
|
|
|
//get the current inventory values for later updating
|
|
PartByWarehouseInventoryValuesFetcher invent =
|
|
PartByWarehouseInventoryValuesFetcher.GetItem(
|
|
poi.PartID, poi.PartWarehouseID, transaction
|
|
);
|
|
|
|
|
|
//was nothing at all received?
|
|
if (poi.QuantityReceived == 0)
|
|
{
|
|
#region Nothing received at all
|
|
//If it's a woitempartrequest make it like it was never ordered at all
|
|
if (poi.WorkorderItemPartRequestID != Guid.Empty) //Yes
|
|
{
|
|
#region Update part request
|
|
|
|
//nope to make it like it never happened
|
|
|
|
DBCommandWrapper cmUpdateRequest = DBUtil.GetCommandFromSQL(
|
|
"UPDATE aWorkorderItemPartRequest SET aPurchaseOrderItemID=@PurchaseOrderItemID, " +
|
|
"aModifier=@CurrentUserID, aModified=@Modified WHERE aID=@ID"
|
|
);
|
|
|
|
//WorkorderItemPartRequest specific
|
|
cmUpdateRequest.AddInParameter("@ID", DbType.Guid, poi.WorkorderItemPartRequestID);
|
|
cmUpdateRequest.AddInParameter("@PurchaseOrderItemID", DbType.Guid, Guid.Empty);//set to no po so it's not on order any more
|
|
|
|
//standard parameters
|
|
cmUpdateRequest.AddInParameter("@CurrentUserID", DbType.Guid, CurrentUserID);
|
|
cmUpdateRequest.AddInParameter("@Modified", DbType.DateTime, DBUtil.ToUTC(dtModified));
|
|
DBUtil.DB.ExecuteNonQuery(cmUpdateRequest, transaction);
|
|
|
|
|
|
#endregion
|
|
}
|
|
|
|
//case 1828 moved out of if block above as it would only work if it was a request
|
|
|
|
#region Remove empty poreceiptitem
|
|
//so that we can delete this poitem
|
|
//without invoking a sql index error because poreceiptitem references this
|
|
//poitem
|
|
|
|
DBCommandWrapper cmUpdatePORI = DBUtil.GetCommandFromSQL(
|
|
"DELETE FROM APURCHASEORDERRECEIPTITEM WHERE APURCHASEORDERITEMID=@ID"
|
|
);
|
|
cmUpdatePORI.AddInParameter("@ID", DbType.Guid, poi.ID);
|
|
DBUtil.DB.ExecuteNonQuery(cmUpdatePORI, transaction);
|
|
#endregion
|
|
|
|
#region Update inventory quantity on order committed and qty on order
|
|
|
|
//Update...
|
|
DBCommandWrapper cmUpdateInventoryCommitted = null;
|
|
cmUpdateInventoryCommitted = DBUtil.GetCommandFromSQL(
|
|
"UPDATE aPartByWarehouseInventory SET aQtyOnOrderCommitted=@CMTQuantity, " +
|
|
"aQuantityOnOrder=@OOQuantity, aModifier=@CurrentUserID, aModified=@Modified " +
|
|
"WHERE (aPartID = @PartID) AND (aPartWarehouseID " +
|
|
"= @PartWarehouseID)"
|
|
);
|
|
cmUpdateInventoryCommitted.AddInParameter("@PartID", DbType.Guid, poi.PartID);
|
|
cmUpdateInventoryCommitted.AddInParameter("@PartWarehouseID", DbType.Guid, poi.PartWarehouseID);
|
|
cmUpdateInventoryCommitted.AddInParameter("@CurrentUserID", DbType.Guid, CurrentUserID);
|
|
cmUpdateInventoryCommitted.AddInParameter("@Modified", DbType.DateTime, DBUtil.ToUTC(dtModified));
|
|
cmUpdateInventoryCommitted.AddInParameter("@CMTQuantity", DbType.Decimal, invent.QtyOnOrderCommitted - poi.QuantityOrdered);
|
|
cmUpdateInventoryCommitted.AddInParameter("@OOQuantity", DbType.Decimal, invent.QuantityOnOrder - poi.QuantityOrdered);
|
|
|
|
DBUtil.DB.ExecuteNonQuery(cmUpdateInventoryCommitted, transaction);
|
|
|
|
#endregion
|
|
|
|
//Add the id of the poitem to the list of items to delete in update later
|
|
//can't call remove directly because
|
|
//we're in the midst of iterating through the collection
|
|
poItemsToDeleteList.Add(poi.ID);
|
|
poi.WorkorderItemPartRequestID = Guid.Empty;
|
|
#endregion
|
|
}
|
|
else if (poi.QuantityReceived > 0)
|
|
{// was partially received
|
|
#region Partially received
|
|
|
|
decimal dBalanceUnreceived = poi.QuantityOrdered - poi.QuantityReceived;
|
|
|
|
//change qty ordered to received
|
|
poi.QuantityOrdered = poi.QuantityReceived;
|
|
//case 3739
|
|
bOrderItemsNeedToBeSavedAgain = true;
|
|
|
|
#region Update inventory quantity on order
|
|
|
|
//Update...
|
|
DBCommandWrapper cmUpdateInventoryCommitted = null;
|
|
cmUpdateInventoryCommitted = DBUtil.GetCommandFromSQL(
|
|
"UPDATE aPartByWarehouseInventory SET " +
|
|
"aQuantityOnOrder=@OOQuantity, aModifier=@CurrentUserID, aModified=@Modified " +
|
|
"WHERE (aPartID = @PartID) AND (aPartWarehouseID " +
|
|
"= @PartWarehouseID)"
|
|
);
|
|
cmUpdateInventoryCommitted.AddInParameter("@PartID", DbType.Guid, poi.PartID);
|
|
cmUpdateInventoryCommitted.AddInParameter("@PartWarehouseID", DbType.Guid, poi.PartWarehouseID);
|
|
cmUpdateInventoryCommitted.AddInParameter("@CurrentUserID", DbType.Guid, CurrentUserID);
|
|
cmUpdateInventoryCommitted.AddInParameter("@Modified", DbType.DateTime, DBUtil.ToUTC(dtModified));
|
|
cmUpdateInventoryCommitted.AddInParameter("@OOQuantity", DbType.Decimal, invent.QuantityOnOrder - dBalanceUnreceived);
|
|
|
|
DBUtil.DB.ExecuteNonQuery(cmUpdateInventoryCommitted, transaction);
|
|
|
|
#endregion
|
|
|
|
//Partially received so update workorder item part request record
|
|
//so that the On order quantity matches the received quantity
|
|
//so that the workorder can be closed etc.
|
|
//case 1920
|
|
if (poi.WorkorderItemPartRequestID != Guid.Empty) //Yes
|
|
{
|
|
#region Update part request
|
|
|
|
//Set quantity to the actual recieved amount
|
|
|
|
DBCommandWrapper cmUpdateRequest = DBUtil.GetCommandFromSQL(
|
|
"UPDATE AWORKORDERITEMPARTREQUEST SET AQUANTITY=ARECEIVED, " +
|
|
"AMODIFIER=@CURRENTUSERID, AMODIFIED=@MODIFIED WHERE AID=@ID"
|
|
);
|
|
|
|
//WorkorderItemPartRequest specific
|
|
cmUpdateRequest.AddInParameter("@ID", DbType.Guid, poi.WorkorderItemPartRequestID);
|
|
|
|
//standard parameters
|
|
cmUpdateRequest.AddInParameter("@CurrentUserID", DbType.Guid, CurrentUserID);
|
|
cmUpdateRequest.AddInParameter("@Modified", DbType.DateTime, DBUtil.ToUTC(dtModified));
|
|
DBUtil.DB.ExecuteNonQuery(cmUpdateRequest, transaction);
|
|
|
|
|
|
#endregion
|
|
}
|
|
#endregion
|
|
}
|
|
//case 1918
|
|
poi.OverrideIsLockedForInternalUpdate = false;
|
|
}
|
|
}//foreach poitem
|
|
|
|
//remove any poitems in delete list
|
|
if (poItemsToDeleteList.Count > 0)
|
|
{
|
|
|
|
foreach (Guid g in poItemsToDeleteList)
|
|
mOrderItems.Remove(g);
|
|
//save these changes
|
|
|
|
//case 3739 only save once below
|
|
//mOrderItems.Update(this, transaction);
|
|
bOrderItemsNeedToBeSavedAgain = true;
|
|
}
|
|
|
|
//case 3739
|
|
if (bOrderItemsNeedToBeSavedAgain)
|
|
{
|
|
mOrderItems.Update(this, transaction);
|
|
}
|
|
|
|
if (bOrderItemsWasReadOnly)
|
|
mOrderItems.SetAllItemsReadOnly();
|
|
}//case 564 changed to closed not all received
|
|
|
|
#endregion status change to closed but not fully received handle incomplete orders
|
|
|
|
|
|
|
|
|
|
//Process keywords
|
|
DBUtil.ProcessKeywords(transaction,this.mID,RootObjectTypes.PurchaseOrder,IsNew,AyaBizUtils.Break(false,
|
|
mNotes,mReferenceNumber,mVendorMemo,
|
|
/*Custom fields*/
|
|
mCustom1,mCustom2,mCustom3,mCustom4,mCustom5,mCustom6,mCustom7,mCustom8,mCustom9,mCustom0));
|
|
|
|
MarkOld();//db is now synched with object
|
|
|
|
// Commit the transaction
|
|
transaction.Commit();
|
|
|
|
//case 3738 it has just been saved successfully so we need to now upate previous status to reflect in db value
|
|
mPreviousStatus = mStatus;
|
|
|
|
}
|
|
catch
|
|
{
|
|
// Rollback transaction
|
|
transaction.Rollback();
|
|
throw;
|
|
}
|
|
finally
|
|
{
|
|
connection.Close();
|
|
}
|
|
|
|
//Get new DB generated identity value
|
|
if(bGetIdentity)
|
|
this.mPONumber=DBUtil.GetIdentity("aPONumber","aPurchaseOrder",this.mID,null);
|
|
|
|
//Successful update so
|
|
//change modification time to match
|
|
this.mModified.Date=dtModified;
|
|
}
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
}
|
|
#endregion update
|
|
|
|
#region Delete
|
|
|
|
/// <summary>
|
|
/// Remove a PurchaseOrder record .
|
|
/// </summary>
|
|
/// <param name="Criteria"></param>
|
|
protected override void DataPortal_Delete(object Criteria)
|
|
{
|
|
|
|
Criteria crit = (Criteria)Criteria;
|
|
//get the status and see if it's deleteable
|
|
object o=DBUtil.GetScalarFromSQLString(
|
|
"SELECT aStatus FROM aPurchaseOrder WHERE (aID = @ID)",crit.ID
|
|
);
|
|
if(o==null || o==System.DBNull.Value) return;
|
|
int nValue=System.Convert.ToInt32(o);
|
|
if(nValue > (int)PurchaseOrderStatus.OpenNotYetOrdered)
|
|
throw new System.ApplicationException
|
|
(
|
|
LocalizedTextTable.GetLocalizedTextDirect("PurchaseOrder.Label.Error.Locked")
|
|
);
|
|
|
|
//Delete object and child objects
|
|
DBCommandWrapper cmDelete = DBUtil.GetCommandFromSQL("DELETE FROM aPurchaseOrder WHERE aID = @ID;");
|
|
cmDelete.AddInParameter("@ID",DbType.Guid,crit.ID);
|
|
|
|
//Delete all child items
|
|
DBCommandWrapper cmDeleteItems = DBUtil.GetCommandFromSQL("DELETE FROM aPurchaseOrderItem WHERE aPurchaseOrderID=@ID;");
|
|
cmDeleteItems.AddInParameter("@ID",DbType.Guid,crit.ID);
|
|
|
|
using (IDbConnection connection = DBUtil.DB.GetConnection())
|
|
{
|
|
connection.Open();
|
|
IDbTransaction transaction = connection.BeginTransaction();
|
|
|
|
try
|
|
{
|
|
DBUtil.DB.ExecuteNonQuery(cmDeleteItems, transaction);
|
|
DBUtil.DB.ExecuteNonQuery(cmDelete, transaction);
|
|
|
|
DBUtil.RemoveKeywords(transaction,RootObjectTypes.PurchaseOrder,crit.ID);
|
|
DBUtil.RemoveDocs(transaction, RootObjectTypes.PurchaseOrder, crit.ID);
|
|
|
|
// Commit the transaction
|
|
transaction.Commit();
|
|
}
|
|
catch
|
|
{
|
|
// Rollback transaction
|
|
transaction.Rollback();
|
|
throw;
|
|
}
|
|
finally
|
|
{
|
|
connection.Close();
|
|
}
|
|
}
|
|
}
|
|
#endregion delete
|
|
|
|
#endregion
|
|
|
|
#region Override IsValid / IsDirty
|
|
//Override base class version if there are child objects
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public override bool IsValid
|
|
{
|
|
get
|
|
{
|
|
return base.IsValid && mOrderItems.IsValid ;
|
|
}
|
|
}
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public override bool IsDirty
|
|
{
|
|
get
|
|
{
|
|
return base.IsDirty || mOrderItems.IsDirty ;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region criteria
|
|
/// <summary>
|
|
/// Criteria for identifying existing object
|
|
/// </summary>
|
|
[Serializable]
|
|
private class Criteria
|
|
{
|
|
public Guid ID;
|
|
public Criteria(Guid _ID)
|
|
{
|
|
ID=_ID;
|
|
}
|
|
|
|
}
|
|
#endregion
|
|
|
|
#region Set VisibleIDNumber
|
|
/// <summary>
|
|
/// Set the DB generated visible ID number
|
|
/// to a new user chosen starting point
|
|
/// </summary>
|
|
[Serializable(), System.ComponentModel.Browsable(false)]
|
|
public class VisibleIDNumber//DO_NOT_OBFUSCATE
|
|
{
|
|
int _newStartID = -1;
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="newStartID"></param>
|
|
public VisibleIDNumber(int newStartID)
|
|
{
|
|
_newStartID = newStartID;
|
|
}
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="newStartID"></param>
|
|
public static void SetVisibleIDNumber(int newStartID)
|
|
{
|
|
DataPortal.Update(new VisibleIDNumber(newStartID));
|
|
}
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public void DataPortal_Update()
|
|
{
|
|
//Find the highest existing number
|
|
object o=DBUtil.GetScalarFromSQLString(
|
|
"SELECT MAX(aPONumber) FROM aPurchaseOrder"
|
|
);
|
|
if(o==null || o==System.DBNull.Value) o=0;
|
|
int nHighestExisting=(int)o;
|
|
|
|
|
|
|
|
//ensure new number is larger than highest existing one
|
|
if(_newStartID<nHighestExisting)
|
|
throw new ApplicationException(
|
|
string.Format(
|
|
LocalizedTextTable.GetLocalizedTextDirect("Error.AutoIncrement.NumberTooLow"),
|
|
(nHighestExisting+1).ToString()));
|
|
|
|
|
|
|
|
|
|
switch(DBUtil.DB.DBType)
|
|
{
|
|
case DataBaseType.FireBird:
|
|
{
|
|
string sql="SET Generator GEN_APONUMBER TO " + _newStartID.ToString();
|
|
DBUtil.DB.ExecuteNonQuery(CommandType.Text,sql);
|
|
}
|
|
break;
|
|
|
|
case DataBaseType.MSSQL:
|
|
{
|
|
string sql="DBCC CHECKIDENT (aPurchaseOrder, RESEED, " + _newStartID.ToString()+")";
|
|
DBUtil.DB.ExecuteNonQuery(CommandType.Text,sql);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
throw new ApplicationException("UNKNOWN DB TYPE IN START SEED UPDATE");
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
}
|
|
#endregion set visibleIDnumber
|
|
|
|
|
|
|
|
}//end PurchaseOrder
|
|
|
|
}//end namespace GZTW.AyaNova.BLL |