/// <summary> Constructor for a new instance of the Tracking_ItemViewer class, used display
        /// the full workflow history information for a digital resource </summary>
        /// <param name="BriefItem"> Digital resource object </param>
        /// <param name="CurrentUser"> Current user, who may or may not be logged on </param>
        /// <param name="CurrentRequest"> Information about the current request </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering </param>
        public Tracking_ItemViewer(BriefItemInfo BriefItem, User_Object CurrentUser, Navigation_Object CurrentRequest, Custom_Tracer Tracer )
        {
            // Save the arguments for use later
            this.BriefItem = BriefItem;
            this.CurrentUser = CurrentUser;
            this.CurrentRequest = CurrentRequest;

            // Set the behavior properties to the empy behaviors ( in the base class )
            Behaviors = EmptyBehaviors;

            // Get the tracking information
            Tracer.Add_Trace("Tracking_ItemViewer.Constructor", "Try to pull the tracking details for this item");
            trackingDetails = SobekEngineClient.Items.Get_Item_Tracking_Work_History(BriefItem.BibID, BriefItem.VID, Tracer);
            if (trackingDetails == null)
            {
                Tracer.Add_Trace("Tracking_ItemViewer.Constructor", "Unable to pull tracking details");
                CurrentRequest.Mode = Display_Mode_Enum.Error;
                CurrentRequest.Error_Message = "Internal Error : Unable to pull tracking information for " + BriefItem.BibID + ":" + BriefItem.VID;
            }
        }
        /// <summary> Store the tracking/workflow information related to a digital resource   </summary>
        /// <param name="BibID"> Bibliographic Identifier for the digital resource to store </param>
        /// <param name="VID"> Volume Identifier for the digital resource to store </param>
        /// <param name="StoreObject"> Tracking/workflow information for a digital Resource object to store for later retrieval </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering</param>
        public void Store_Item_Tracking(string BibID, string VID, Item_Tracking_Details StoreObject, Custom_Tracer Tracer)
        {
            // If the cache is disabled, just return before even tracing
            if (settings.Disabled)
                return;

            // Determine the key
            string key = "ITEM_" + BibID + "_" + VID + "_Tracking";
            const int LENGTH_OF_TIME = 1;

            if (Tracer != null)
            {
                Tracer.Add_Trace("CachedDataManager_ItemServices.Store_Item_Tracking", "Adding object '" + key + "' to the local cache with expiration of " + LENGTH_OF_TIME + " minute");
            }

            HttpContext.Current.Cache.Insert(key, StoreObject, null, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(LENGTH_OF_TIME));
        }
        /// <summary> Returns list of individual work history events and milestones for a single item </summary>
        /// <param name="BibID"> Bibliographic identifier for the item group of interest </param>
        /// <param name="VID"> Volume identifier for the item of interest </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering</param>
        /// <returns> Month-by-month usage statistics for item and item-group </returns>
        /// <remarks> This calls the 'Tracking_Get_Work_History' stored procedure  </remarks>
        public static Item_Tracking_Details Get_Item_Tracking_Work_History(string BibID, string VID, Custom_Tracer Tracer)
        {
            if (Tracer != null)
            {
                Tracer.Add_Trace("Engine_Database.Get_Item_Tracking_Work_History", "Pulling work history for '" + BibID + "_" + VID + "' from database");
            }

            try
            {
                // Execute this query stored procedure
                EalDbParameter[] paramList = new EalDbParameter[2];
                paramList[0] = new EalDbParameter("@BibID", BibID);
                paramList[1] = new EalDbParameter("@VID", VID);

                // Open the data reader to step through the data as it comes back
                EalDbReaderWrapper readerWrapper = EalDbAccess.ExecuteDataReader(DatabaseType, Connection_String, CommandType.StoredProcedure, "Tracking_Get_Work_History", paramList);

                // Start the return value
                Item_Tracking_Details returnValue = new Item_Tracking_Details();

                // Step through each work event
                while (readerWrapper.Reader.Read())
                {
                    // Build this item information
                    Item_Tracking_Event thisItem = new Item_Tracking_Event
                    {
                        WorkflowName = readerWrapper.Reader.GetString(1),
                        CompletedDate = readerWrapper.Reader.GetString(2),
                        WorkPerformedBy = readerWrapper.Reader.GetString(3)
                    };

                    // If there are notes include them
                    if (!readerWrapper.Reader.IsDBNull(4))
                        thisItem.Notes = readerWrapper.Reader.GetString(4);

                    // Add this item to the list to return
                    returnValue.WorkEvents.Add(thisItem);
                }

                // Go to the milestone table and pull those numbers
                if ((readerWrapper.Reader.NextResult()) && (readerWrapper.Reader.Read()))
                {
                    returnValue.CreateDate = readerWrapper.Reader.GetDateTime(0);

                    if (!readerWrapper.Reader.IsDBNull(1)) returnValue.Milestone_DigitalAcquisition = readerWrapper.Reader.GetDateTime(1);
                    if (!readerWrapper.Reader.IsDBNull(2)) returnValue.Milestone_ImageProcessing = readerWrapper.Reader.GetDateTime(2);
                    if (!readerWrapper.Reader.IsDBNull(3)) returnValue.Milestone_QualityControl = readerWrapper.Reader.GetDateTime(3);
                    if (!readerWrapper.Reader.IsDBNull(4)) returnValue.Milestone_OnlineComplete = readerWrapper.Reader.GetDateTime(4);
                    if (!readerWrapper.Reader.IsDBNull(5)) returnValue.Material_ReceivedDate = readerWrapper.Reader.GetDateTime(5);
                    if (!readerWrapper.Reader.IsDBNull(6)) returnValue.Disposition_Date = readerWrapper.Reader.GetDateTime(6);
                }

                // Close the reader (which also closes the connection)
                readerWrapper.Close();

                // Return the fully built object
                return returnValue;
            }
            catch (Exception ee)
            {
                Last_Exception = ee;
                if (Tracer != null)
                {
                    Tracer.Add_Trace("Engine_Database.Get_Item_Tracking_Work_History", "Exception caught during database work", Custom_Trace_Type_Enum.Error);
                    Tracer.Add_Trace("Engine_Database.Get_Item_Tracking_Work_History", ee.Message, Custom_Trace_Type_Enum.Error);
                    Tracer.Add_Trace("Engine_Database.Get_Item_Tracking_Work_History", ee.StackTrace, Custom_Trace_Type_Enum.Error);
                }
                return null;
            }
        }