Files
ayanova7/source/bizobjects/AyaLib/GZTW.AyaNova.BLL/PartInventoryList.cs
2018-06-29 19:47:36 +00:00

633 lines
24 KiB
C#

///////////////////////////////////////////////////////////
// PartInventoryList.cs
// Implementation of Class PartInventoryList
// CSLA type: Read only collection
// Created on: 28-Nov-2007
// Object design: John
// Coded: 28-Nov-2007
///////////////////////////////////////////////////////////
using System;
using System.Data;
using GZTW.Data;
using CSLA.Data;
using CSLA;
using System.ComponentModel;
using System.Collections.Generic;
namespace GZTW.AyaNova.BLL
{
#pragma warning disable 1591
/// <summary>
/// Similar to <see cref="PartWarehouseInventoryList"/> but
/// for retrieving inventory and serials of a single part
/// specified by part id.
///
/// Used by AyaNova WBI Only in PartInventoryView page
///
/// </summary>
[Serializable]
public class PartInventoryList : ReadOnlyCollectionBase, ITypedList
{
#region ITypedList
//Implementation of ITypedList to allow a grid to display a read only child collection
//within a read only collection
PropertyDescriptorCollection ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors)
{
if (listAccessors == null)//then return properties of this (the parent) collection
{
//This class this code is in is the implementation of the
//PartInventoryList read only collection business object
return TypeDescriptor.GetProperties(typeof(PartInventoryListInfo));
}
else if (listAccessors.Length == 1)//then return the properties of a child object
{
//Return the properties of the struct inside the
//PartInventoryList read only collection
if (listAccessors[0].Name == "LT_PartSerial_Label_List")
return TypeDescriptor.GetProperties(typeof(PartSerialPickList.PartSerialPickListInfo));
//add more here if there are more children or grandchildren
}
return null;
}
///
/// Not required for grid but must be implemented
///
///
///
string ITypedList.GetListName(PropertyDescriptor[] listAccessors)
{
return "";
}
#endregion
#region Data structure
/// <summary>
/// Properties
/// </summary>
[Serializable]
public struct PartInventoryListInfo
{
internal Guid mID;
internal GridNameValueCellItem mPartWarehouseID;
internal GridNameValueCellItem mPartID;
internal decimal mQuantityOnHand;
internal decimal mQuantityOnOrder;
internal decimal mReorderQuantity;
internal decimal mMinStockLevel;
internal GridNameValueCellItem mPartCategory;
internal GridNameValueCellItem mPartAssembly;
//case 265
internal bool mPartActive;
//case 1975
internal decimal mQtyOnOrderCommitted;
[SqlColumnNameAttribute("aPartAssembly.aName",
"aPartAssembly.aID"),
Display(DisplayType.Button, RootObjectType = RootObjectTypes.PartAssembly)]
public GridNameValueCellItem LT_O_PartAssembly { get { return mPartAssembly; } }
[SqlColumnNameAttribute("aPartCategory.aName",
"aPartCategory.aID"),
Display(DisplayType.Button, RootObjectType = RootObjectTypes.PartCategory)]
public GridNameValueCellItem LT_O_PartCategory { get { return mPartCategory; } }
internal PartSerialPickList mSerials;
[SqlColumnNameAttribute("grid"), Display(DisplayType.Text)]
public PartSerialPickList LT_PartSerial_Label_List { get { return mSerials; } }
[Display(DisplayType.Hidden)]
public Guid ID { get { return mID; } }
[SqlColumnNameAttribute("aPartWarehouse.aName",
"aPartByWarehouseInventory.aPartWarehouseID"),
Display(DisplayType.Button, RootObjectType = RootObjectTypes.PartWarehouse)]
public GridNameValueCellItem LT_O_PartWarehouse { get { return mPartWarehouseID; } }
[SqlColumnNameAttribute("aPart.aPartNumber",
"aPartByWarehouseInventory.aPartID"),
Display(DisplayType.Button, RootObjectType = RootObjectTypes.Part)]
public GridNameValueCellItem LT_O_Part { get { return mPartID; } }
[Display(DisplayType.DecimalNumber)]
public decimal LT_PartByWarehouseInventory_Label_QuantityOnHand { get { return mQuantityOnHand; } }
[Display(DisplayType.DecimalNumber)]
public decimal LT_PartByWarehouseInventory_Label_QuantityOnOrder { get { return mQuantityOnOrder; } }
[Display(DisplayType.DecimalNumber)]
public decimal LT_PartByWarehouseInventory_Label_MinStockLevel { get { return mMinStockLevel; } }
[SqlColumnNameAttribute("AREORDERQUANTITY"), Display(DisplayType.DecimalNumber)]
public decimal LT_PartByWarehouseInventory_Label_ReorderQuantity { get { return mReorderQuantity; } }
//Case 265
[Display(DisplayType.TrueFalse)]
public bool LT_Part_Label_Active { get { return mPartActive; } }
//Case 58
internal GridNameValueCellItem mRegion;
[SqlColumnNameAttribute("aRegion.aName", "aRegion.aID"),
Display(DisplayType.Button, RootObjectType = RootObjectTypes.Region)]
public GridNameValueCellItem LT_O_Region
{
get
{
return mRegion;
}
}
//case 1975
[Display(DisplayType.DecimalNumber)]
public decimal LT_PartByWarehouseInventory_Label_QtyOnOrderCommitted { get { return mQtyOnOrderCommitted; } }
//case 1975
internal decimal mTotal;
public decimal Total
{ get { return mTotal; } }
/// <summary>
///
/// </summary>
/// <param name="obj"></param>
public bool Equals(PartInventoryListInfo obj)
{
return this.mID.Equals(obj.mID);
}
}//end PartInventoryListInfo
#endregion
#region Constructor
protected PartInventoryList()
{
// AllowSort=false;
// AllowFind=true;
// AllowEdit=false;
// AllowNew=false;
// AllowRemove=false;
}
#endregion
#region Business properties and methods
/// <summary>
/// Get item by index
/// </summary>
/// <param name="Item"></param>
public PartInventoryListInfo this[int Item]
{
get
{
return (PartInventoryListInfo)List[Item];
}
}
/// <summary>
/// Returns display text that matches passed in itemid value
/// </summary>
/// <param name="ItemID"></param>
public string this[Guid ItemID]
{
get
{
foreach (PartInventoryListInfo child in List)
{
if (child.mID == ItemID) return child.ToString();
}
return "Missing: " + ItemID.ToString();
}
}
#endregion
#region contains
/// <summary>
/// Check if item in collection
/// </summary>
/// <param name="obj"></param>
public bool Contains(PartInventoryListInfo obj)
{
foreach (PartInventoryListInfo child in List)
{
if (child.Equals(obj)) return true;
}
return false;
}
#endregion
#region Reporting and shared UI editor helpers
/// <summary>
/// Returns the report key which is a property of
/// reports used to link all reports that can be used
/// with a particular data source.
/// </summary>
public static string ReportKey
{
get
{
return "PartInventoryList";
}
}
/// <summary>
/// Returns the Detailed report key
/// which is used to determine which reports and objects
/// will be used for detailed reports
///
/// If empty string then indicates there is no detailed report object or reports
/// </summary>
public static string DetailedReportKey
{
get
{
return "";
}
}
/// <summary>
/// Base object that this list is reporting on
/// used by shared UI editor to instantiate new objects
/// when user selects new in UI elements that display this list
///
/// (I.E. when user clicks on new in a read only list grid, this is the object type created)
/// </summary>
public static RootObjectTypes BaseObjectType
{
get
{
return RootObjectTypes.Nothing;
}
}
/// <summary>
/// Locale key so that generic list editor
/// UI code knows what title to give the list in a
/// grid
/// </summary>
public string LocaleKey
{
get
{
return "PartByWarehouseInventory.Label.List";
}
}
/// <summary>
/// The Type of the struct used to store list records
/// Used to fetch the custom display attributes of the fields
/// contained within the record to modify the grid display accordingly
/// <see cref="DisplayAttribute"/>
/// </summary>
public static Type ListRecordType
{
get
{
return typeof(PartInventoryListInfo);
}
}
/// <summary>
/// Field that contains the ID of the objects
/// that are the basis of this list.
///
/// Used for compiling an ID list for reporting from user
/// selections in a grid.
/// </summary>
public static string IDField
{
get
{
return "ID";
}
}
/// <summary>
/// Same as IDField but for detailed reports
/// </summary>
public static string IDFieldDetailed
{
get
{
return IDField;
}
}
#endregion
#region Static methods
/// <summary>
/// Internal method used by list factory
/// </summary>
internal static PartInventoryList Get(string Filter, int MaxRecords, List<Guid> IDList)
{
return (PartInventoryList)DataPortal.Fetch(new Criteria(Filter, IDList, MaxRecords));
}
/// <summary>
/// Get all PartByWarehouseInventory (filtered by crit)
/// </summary>
/// <param name="xmlCriteria">Use AyaNova UI to easily build xmlCriteria and Ctrl-Alt-g keyboard command to display it for use in your code</param>
/// <returns></returns>
public static PartInventoryList GetList(string xmlCriteria)
{
return (PartInventoryList)DataPortal.Fetch(new Criteria(xmlCriteria, null, -1));
}
/// <summary>
/// Takes a single PART ID and returns a "list" of one object
/// </summary>
/// <param name="PartID">ID of PART</param>
public static PartInventoryList GetListForSingleItem(Guid PartID)
{
//Case 556
List<Guid> l = new List<Guid>();
l.Add(PartID);
return GetListFromIDList(l);
}
/// <summary>
/// Get list by part id's indicated in IDList
/// </summary>
/// <param name="IDList">Generic list of Part Guid's</param>
/// <returns></returns>
public static PartInventoryList GetListFromIDList(List<Guid> IDList)
{
//case 556
//Handle empty list
if (IDList.Count == 0)
return new PartInventoryList();
return (PartInventoryList)DataPortal.Fetch(new Criteria("", IDList, -1));
}
/// <summary>
/// Return an empty list
/// used for initializing grid
/// </summary>
/// <returns></returns>
public static PartInventoryList GetEmptyList()
{
return new PartInventoryList();
}
//case 1975
/// <summary>
/// Takes a single PART ID and returns a "list" of one object
/// </summary>
/// <param name="PartID">ID of PART</param>
/// <param name="MaxRecords">Maximum records to return</param>
/// <returns></returns>
public static PartInventoryList GetListForSingleItem(Guid PartID, int MaxRecords)
{
//Case 556
List<Guid> l = new List<Guid>();
l.Add(PartID);
return (PartInventoryList)DataPortal.Fetch(new Criteria("", l, MaxRecords));
}
#endregion
#region DAL DATA ACCESS
///
/// <param name="Criteria"></param>
protected override void DataPortal_Fetch(object Criteria)
{
Criteria crit = (Criteria)Criteria;
SafeDataReader dr = null;
try
{
//case 1975
decimal dTotal = 0;
//Workaround for sorting on the calculated column
string sSort = AyaBizUtils.GetGridSortOrderColumns(crit.CriteriaXML);
sSort = sSort.Replace("AREORDERQUANTITY", "(aPartByWarehouseInventory.aMinStockLevel-(aPartByWarehouseInventory.aQuantityOnHand + aPartByWarehouseInventory.aQuantityOnOrder))");
//This is a funky workaround because AREORDERQUANTITY is based on a calculated value
//you can't filter on an alias even though you can sort on one wierd in MS SQL (In firebird you can't
// do either. AREORDERQUANTITY
//so when it's filtered, it's distinctive name is easy to replace with the filter calculation
//whereas when it's sorted it simply uses the alias so we replace here in case of filter"
//Also we display zero when a reorderqty is less than zero so there needs to be a
//hack to change a filter of =0 (as the user sees it) to <1
string sFilter = AyaBizUtils.GetGridColumnCriteria(crit.CriteriaXML, true);
if (sFilter.IndexOf("AREORDERQUANTITY =0") != -1)
sFilter = sFilter.Replace("AREORDERQUANTITY =0", "(aPartByWarehouseInventory.aMinStockLevel-(aPartByWarehouseInventory.aQuantityOnHand + aPartByWarehouseInventory.aQuantityOnOrder)) <1");
else if (sFilter.IndexOf("AREORDERQUANTITY <0") != -1)
sFilter = sFilter.Replace("AREORDERQUANTITY <0", "(aPartByWarehouseInventory.aMinStockLevel-(aPartByWarehouseInventory.aQuantityOnHand + aPartByWarehouseInventory.aQuantityOnOrder)) <1");
else
sFilter = sFilter.Replace("AREORDERQUANTITY", "(aPartByWarehouseInventory.aMinStockLevel-(aPartByWarehouseInventory.aQuantityOnHand + aPartByWarehouseInventory.aQuantityOnOrder)) ");
string q =//************************************************************
"SELECT ~MAXRECS~ aPart.aPartNumber AS aPARTNUMBER, aPart.aName, aPart.aActive, " +//case 265 added apartactive
" aPartByWarehouseInventory.aPartWarehouseID, " +
" aPartWarehouse.aName AS aPartWarehouseName, " +
" aPartWarehouse.aRegionID, aRegion.aName AS aRegionName, " + //case 58
" aPartByWarehouseInventory.aQuantityOnHand, " +
" aPartByWarehouseInventory.aQtyOnOrderCommitted, " +
" aPartByWarehouseInventory.aQuantityOnOrder, " +
" aPartByWarehouseInventory.aMinStockLevel, " +
"aPartByWarehouseInventory.aID, aPartByWarehouseInventory.aMinStockLevel " +
"- (aPartByWarehouseInventory.aQuantityOnHand " +
"+ aPartByWarehouseInventory.aQuantityOnOrder) " +
"AS AREORDERQUANTITY, " +
"aPartByWarehouseInventory.aPartID, aPart.aUPC, " +
" aVendor.aName AS aMANUFACTURERNAME, aPartCategory.aName " +
"AS aPARTCATEGORYNAME, aPartCategory.aID " +
"AS aPartCategoryID, aPartAssembly.aName " +
"AS aPARTASSEMBLYNAME, aPartAssembly.aID " +
"AS aPartAssemblyID " +
"FROM " +
" APARTBYWAREHOUSEINVENTORY " +
" LEFT OUTER JOIN APART ON (APARTBYWAREHOUSEINVENTORY.APARTID=APART.AID) " +
" LEFT OUTER JOIN AVENDOR ON (APART.AWHOLESALERID=AVENDOR.AID) " +
" LEFT OUTER JOIN APARTWAREHOUSE ON (APARTBYWAREHOUSEINVENTORY.APARTWAREHOUSEID=APARTWAREHOUSE.AID) " +
"LEFT OUTER JOIN aRegion ON APARTWAREHOUSE.aRegionID = aRegion.aID " + //Case 58
" LEFT OUTER JOIN APARTCATEGORY ON (APART.APARTCATEGORYID=APARTCATEGORY.AID) " +
" LEFT OUTER JOIN APARTASSEMBLY ON (APART.APARTASSEMBLYID=APARTASSEMBLY.AID) ";
//************************************************************
if (crit.IDList != null)
{
//case 1975
dTotal = DBUtil.ScalarToDecimal(DBUtil.GetScalarFromSQLString(
"SELECT COUNT(AID) FROM APARTBYWAREHOUSEINVENTORY WHERE APARTBYWAREHOUSEINVENTORY.APARTID=@ID", crit.IDList[0]));
//Case 556
System.Text.StringBuilder sbIN = new System.Text.StringBuilder();
sbIN.Append(" WHERE (aPartByWarehouseInventory.aPartID in (");
foreach (Guid gItem in crit.IDList)
{
sbIN.Append("'");
sbIN.Append("{");
sbIN.Append(gItem.ToString().ToUpperInvariant());
sbIN.Append("}");
sbIN.Append("',");
}
sbIN.Length = sbIN.Length - 1;
sbIN.Append(")) ");
if (crit.MaxRecords > 0)
q = q.Replace("~MAXRECS~", "TOP " + crit.MaxRecords.ToString());
else
q = q.Replace("~MAXRECS~", "");
if (string.IsNullOrEmpty(sSort))
sSort = " ORDER BY APARTWAREHOUSE.ANAME";
q = q + sbIN.ToString() + sSort;
}
else
{
//Case 566
if (string.IsNullOrEmpty(sFilter))
sFilter = " WHERE (AQUANTITYONHAND <> 0 OR AQUANTITYONORDER <> 0 OR AMINSTOCKLEVEL <> 0) ";
else
sFilter += " AND (AQUANTITYONHAND <> 0 OR AQUANTITYONORDER <> 0 OR AMINSTOCKLEVEL <> 0) ";
q = q + sFilter + sSort;
if (crit.MaxRecords > 0)
q = q.Replace("~MAXRECS~", "TOP " + crit.MaxRecords.ToString());
else
q = q.Replace("~MAXRECS~", "");
q = DBUtil.AddRegionFilter(q, "aPartWarehouse", "");//case 58
}
dr = DBUtil.GetReaderFromSQLString(q);
//case 1975
bool bFirst = true;
while (dr.Read())
{
//*******************************************
PartInventoryListInfo info = new PartInventoryListInfo();
info.mPartWarehouseID = new GridNameValueCellItem(
dr.GetGuid("aPartWarehouseID"),
dr.GetString("aPartWarehouseName"),
RootObjectTypes.PartWarehouse);
//Case 58
info.mRegion = new GridNameValueCellItem(
dr.GetGuid("aRegionID"),
dr.GetString("aRegionName"),
RootObjectTypes.Region);
info.mPartID = new GridNameValueCellItem(
dr.GetGuid("aPartID"),
Part.PartDisplayFormatter(dr.GetString("aName"), dr.GetString("aPARTNUMBER"), dr.GetString("aUPC"),
dr.GetString("aMANUFACTURERNAME"), dr.GetString("aPARTCATEGORYNAME"), dr.GetString("aPARTASSEMBLYNAME"),
AyaBizUtils.GlobalSettings.DefaultPartDisplayFormat),
RootObjectTypes.Part);
info.mPartCategory = new GridNameValueCellItem(
dr.GetGuid("aPartCategoryID"),
dr.GetString("aPartCategoryName"),
RootObjectTypes.PartCategory);
info.mPartAssembly = new GridNameValueCellItem(
dr.GetGuid("aPartAssemblyID"),
dr.GetString("aPartAssemblyName"),
RootObjectTypes.PartAssembly);
info.mQuantityOnHand = dr.GetDecimal("aQuantityOnHand");
info.mQuantityOnOrder = dr.GetDecimal("aQuantityOnOrder");
info.mMinStockLevel = dr.GetDecimal("aMinStockLevel");
//case 1975
info.mQtyOnOrderCommitted = dr.GetDecimal("aQtyOnOrderCommitted");
//TODO: Why is this necessary, if I pull in the value from the query
//under firebird it's over by a factor of 10000
//haven't tested with mssql yet
//info.mReorderQuantity=dr.GetDecimal("AREORDERQUANTITY");
info.mReorderQuantity = info.mMinStockLevel - (info.mQuantityOnHand + info.mQuantityOnOrder);
if (info.mReorderQuantity < 0) info.mReorderQuantity = 0;
info.mID = dr.GetGuid("aID");
info.mSerials = PartSerialPickList.GetList(info.mPartID.Value, info.mPartWarehouseID.Value);
//case 265
info.mPartActive = dr.GetBoolean("AACTIVE");
if (bFirst)
{
info.mTotal = dTotal;
bFirst = false;
}
InnerList.Add(info);
//*******************************************
}
}
finally
{
if (dr != null) dr.Close();
}
}
#endregion
#region criteria
/// <summary>
/// Criteria for identifying existing object
/// </summary>
[Serializable]
private class Criteria
{
public List<Guid> IDList;
public string CriteriaXML;
public int MaxRecords;
public Criteria(string _CriteriaXML, List<Guid> _IDList, int _MaxRecords)
{
CriteriaXML = _CriteriaXML;
IDList = _IDList;
MaxRecords = _MaxRecords;
}
}
#endregion
}//end PartInventoryList
#pragma warning restore 1591
}//end namespace GZTW.AyaNova.BLL