/// <summary>
    /// clear grid of all data, filters and groups
    /// clear session wrappers so previus search params are not retained
    /// </summary>
    protected void Session_Reset_All()
    {

        //remove all filtering/grouping from grid
        ASPxGridView _grid = (ASPxGridView)this.ContentPlaceHolderM1.FindControl("gridOrder");
        if (_grid != null)
        {
            _grid.FilterExpression = null;
            wwi_func.remove_dxgrid_grouping(_grid);
        }

        //Session["user"] = null;
        Session.Remove("user");

        Session.Clear();
        SessionParameterPasser _sessionWrapper = new SessionParameterPasser();
        _sessionWrapper["query"] = "(OrderNumber==-1)";
        _sessionWrapper["name"] = null;
        _sessionWrapper["mode"] = null;

        this.lblResult.Text = "You are not signed in";
        this.btnLogout.ClientVisible = false;
        this.btnLogin.ClientVisible = true;


        //kill cookie
        if (Request.Browser.Cookies)
        {
            if (Request.Cookies["UserInfo"] != null)
            {
                HttpCookie _acookie = new HttpCookie("UserInfo");
                _acookie.Expires = DateTime.Now.AddDays(-1d);
                Response.Cookies.Add(_acookie);
            }
        }
        //end kill cookie
    }
    /// <summary>
    /// this version of redirect just forces the login to close
    /// </summary>
    protected void Redirect(bool loggedIn)
    {
        try
        {
            if (loggedIn)
            {
                UserClass _thisuser = (UserClass)Session["user"];
                
                //this.txtUserName.Text = _thisuser.UserName;

                //save login history
                append_to_user_log(_thisuser);
                
                //290311 REQUIRED FOR FORMS AUTHENTICATION
                //30/03/2011 for forms authentication
                //System.Web.Security.FormsAuthentication.SetAuthCookie(txtUserName.Text, false); 
         
                //show logout
                //ClientScript.RegisterStartupScript(GetType(), "LOG_KEY", "window.parent.loginSwitch();", true);
                //
                //09/03/2011 reset submit_query -1 which should cause default filter to fire therefore not auto-loading data

                //27/06/2011 don't fire this script for ubmit_query(-1) as it means we can only use this login form with search forms e.g. ord_view_tracking.aspx
                //set session wrapper instead
                SessionParameterPasser _sessionWrapper = new SessionParameterPasser();
                _sessionWrapper["mode"] = "-1";
                //ClientScript.RegisterStartupScript(GetType(), "CLR_KEY", "window.parent.submit_query(-1);", true);
                //pass user name back to parent
                ClientScript.RegisterStartupScript(GetType(), "LBL_KEY", "window.parent.lblResult.SetText(txtResult.GetText());", true);
                //09/08/2011 re-initialise menu
                ClientScript.RegisterStartupScript(GetType(), "LBL_MNU", "window.parent.setMenu();", true);
                //close login  
                ClientScript.RegisterStartupScript(GetType(), "INN_KEY", "window.parent.closeloginWindow(1);", true); 
           
            }
            else
            {
                //close this window and redirect to default non-secure page
                //29/06/2011 don't use script as we are going to redirect anyway
                ClientScript.RegisterStartupScript(GetType(), "OUT_KEY", "window.parent.cancelloginWindow();", true);
                //force popup to close
                }
            
        }
        catch (Exception ex)
        {
            this.lblmsg.Text = ex.Message.ToString(); 
        }
    }
    protected void clear_search()
    {
        this.txtQuickSearch.Text = "";
        this.cboName.Value = null;

        SessionParameterPasser _sessionWrapper = new SessionParameterPasser();
        _sessionWrapper["mode"] = null;
        _sessionWrapper["query"] = null;
        _sessionWrapper["name"] = null;
        //Session["filter"] = null; //so we don't save it again
        reset_hidden(); //sets mode back to default 0
        this.gridContainer.DataBind();
    }
    protected void Page_Load(object sender, EventArgs e)
    {
        //on 1st load if the last query in session was on a different tracking page clear the session
        if (!Page.IsPostBack && !Page.IsCallback)
        {
            SessionParameterPasser _sessionWrapper = new SessionParameterPasser();
            if (_sessionWrapper["source"] != null)
            {
                string _source = _sessionWrapper["source"].ToString();
                string _page = wwi_func.get_current_page_name();
                if (!_page.Contains(_source))
                {
                    _sessionWrapper["query"] = null;
                    _sessionWrapper["name"] = null;
                    Session["querytable"] = null;
                }
            }
        }

        if (!Page.ClientScript.IsClientScriptBlockRegistered("lg_key"))
        {
            register_client_scripts();
        }


        if (Page.Session["user"] != null)
        {
            //does not apply to delivery page
            //be careful wrapping set_visible_data() in postback. If Grid.EnableViewState=false we will lose column settings
            //we might have to change this !Page.IsPostBack so it only applies to internal users who need the upload control
            //if (!Page.IsPostBack)
            //{
            //Int32 _cid = (Int32)((UserClass)Page.Session["user"]).CompanyId;
            //string _usr = ((UserClass)Page.Session["user"]).UserId.ToString();
            //string _uid = _usr + "_" + _cid.ToString();
            //170112 hide company name filter unless publiship user

            //this.gridOrder.Columns["Upload"].Visible = false; } else { this.gridOrder.Columns["Upload"].Visible = true;
            //this.dxcbocompany.Enabled = true;

            //21.10.2014 Paul Edwards we don't need to set visible data for delivery tracking as yet but if we are do not use the same xml files as
            //for shipment tracking which uses different columns
            //if (has_preferences(_cid.ToString()))
            //{
            //    set_visible_data(_cid.ToString());
            //}
            //else
            //{
            //    if (!get_cookie("ord_tracking"))
            //    {
            //        set_visible_data("default");
            //    }
            //}
            //}
        }
        else
        {
            //030212 no longer necessary we force to anonymous tracking if not logged in
            //set_visible_data(false);
            //this.gridOrder.Columns["Upload"].Visible = false;
            if (!Page.IsCallback) { Response.Redirect("~/tracking/shipment_tracking_unsigned.aspx", true); }

        }
    }
    /// <summary>
    /// this code is used with LinqServerModeDataSource_Selecting so we can run in server mode
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void LinqServerModeContainers_Selecting(object sender, DevExpress.Data.Linq.LinqServerModeDataSourceSelectEventArgs e)
    {
        ParameterCollection _params = new ParameterCollection();
        SessionParameterPasser _sessionWrapper = new SessionParameterPasser();
        int _companyid = -1; //after testing default to empty string 
        int _contactid = -1;
        string _countries = "";
        //check if session created from advanced search, in which case we can use the parameters passed back
        string _query = "";
        string _name = "";
        string _mode = "";

        //22.10.14 Paul Edwards Session["loaded"] allows us to init the grid with no data
        //Session["containersloaded"] is null on 1st page init when we call selecting event for grid
        //When Javascript Grid.Init is called Grid.CustomCallback event is fired which sets Session["containersloaded"] = true and allows filter query to build
        //This gives a slight delay allowing the page to load BEFORE the grid is populated for a better user experience
        if (Page.Session["containersloaded"] != null)
        {
            if (_sessionWrapper["mode"] != null) //this is only usually set when we pass it back from history search or logout
            {
                _mode = (string)_sessionWrapper["mode"];
                _sessionWrapper["mode"] = null;
            }
            else
            {
                _mode = this.dxhfMethod.Contains("mode") ? this.dxhfMethod["mode"].ToString() : "0"; //this.dxhfQuery["method"].ToString();
            }

            //mode 0=history, 1=basic search so rebuild filter, 2=advanced search, 3=user status report
            if (_mode == "0")
            {
                if (_sessionWrapper["query"] != null && _sessionWrapper["name"] != null)
                {
                    _query = _sessionWrapper["query"].ToString();
                    _name = _sessionWrapper["name"].ToString();
                }
            }
            else if (_mode == "1")
            {
                _query = get_filter();
                _name = get_name();
            }
            else if (_mode == "2")
            {
                if (_sessionWrapper["query"] != null && _sessionWrapper["name"] != null)
                {
                    _query = _sessionWrapper["query"].ToString();
                    _name = _sessionWrapper["name"].ToString();
                }
            }

            //company id: always add as a search param if user is logged in
            //if (Page.Session["user"] != null)
            //company id: always add as a search param if user is logged in UNLESS _mode = -1 which we can use to bypass params
            if (Page.Session["user"] != null)
            {
                bool _usedefaultid = false;

                //***************
                _contactid = ((UserClass)Page.Session["user"]).UserId;
                //deprecated as we need to filter the aggregate function by contact when processed on server
                //so added client ids to table filter_companies and included in function
                //09.04.2015 Paul Edwards check which clients are are visible for this company
                //IList<string> _clientids = null;
                //_clientids = wwi_func.array_from_xml("xml\\contact_iso.xml", "contactlist/contact[id='" + _contactid + "']/clientids/clientid/value");
                //if (_clientids.Count > 0)
                //{
                //    //don't use sql IN(n) as linq won't parse the statement
                //    string _clients = "(MaxCompanyID ==" + string.Join(" OR MaxCompanyID ==", _clientids.Select(i => i.ToString()).ToArray()) + ")";
                //    _params.Add("NULL", _clients);
                //    
                //}
                //21.10.2014 Paul Edwards for delivery tracking check which DeliveryID's are visible for this company
                //check individual contact ID iso 
                IList<string> _deliveryids = null;
                _deliveryids = wwi_func.array_from_xml("xml\\contact_iso.xml", "contactlist/contact[id='" + _contactid.ToString() + "']/deliveryids/deliveryid/value");
                if (_deliveryids.Count > 0)
                {
                    //don't use sql IN(n) as linq won't parse the statement
                    string _deliveries = "(DeliveryAddress==" + string.Join(" OR DeliveryAddress==", _deliveryids.Select(i => i.ToString()).ToArray()) + ")";
                    _params.Add("NULL", _deliveries); //select for this company off list

                }
                else
                {
                    if (_mode != "-1" && _mode != "0")
                    {
                        _companyid = (Int32)((UserClass)Page.Session["user"]).CompanyId;


                        //if internal user check for a selected company
                        //if external user but they have access to company drop down check for selected company and if restricted to particular countries for selected companyID
                        //else return default
                        if (_companyid == -1)
                        {
                            if (!string.IsNullOrEmpty((string)this.dxcbocompany.Value))
                            {
                                _params.Add("CompanyID", this.dxcbocompany.Value.ToString());
                                _name += this.dxcbocompany.Text.ToString() != "" ? ", company name equals " + this.dxcbocompany.Text.ToString() : "";
                            }
                        }
                        else if (_companyid > 0 && this.dxcbocompany.Enabled)
                        {
                            if (!string.IsNullOrEmpty((string)this.dxcbocompany.Value))
                            {
                                IList<string> _args = null;

                                //check for additional country restrictions e.g. EDC can see usborne shipments but ONLY to the US
                                _args = wwi_func.array_from_xml("xml\\company_iso.xml", "companylist/company[id='" + _companyid + "']/visibleitems/item[itemid='" + this.dxcbocompany.Value.ToString() + "']/destinationid");
                                if (_args.Count > 0)
                                {
                                    //don't use sql IN(n) as linq won't parse the statement
                                    _countries = "(CountryID==" + string.Join(" OR CountryID==", _args.Select(i => i.ToString()).ToArray()) + ")";
                                    _params.Add("CompanyID", this.dxcbocompany.Value.ToString() + " AND " + _countries); //select for this company off list
                                }
                                else
                                {
                                    _params.Add("CompanyID", this.dxcbocompany.Value.ToString());
                                }

                                //050613 only check as consignee if xml item does not contain 'companyonly' = -1 tag
                                _args = wwi_func.array_from_xml("xml\\company_iso.xml", "companylist/company[id='" + _companyid + "']/visibleitems/item[itemid='" + this.dxcbocompany.Value.ToString() + "']/companyonly");
                                if (_args.Count == 0)
                                {
                                    //if company id and selected company are the same do an OR operand e.g. companyid =1 OR consignee = 1
                                    //otherwise use AND e.g. consignee = 1 AND companyid = 234 
                                    if (_companyid.ToString() == (string)this.dxcbocompany.Value)
                                    {
                                        _params.Add("ConsigneeID_OR", _companyid.ToString()); //select for this user's company
                                    }
                                    else
                                    {
                                        _params.Add("ConsigneeID_AND", _companyid.ToString()); //select for this user's company
                                    }
                                }


                            }
                            else
                            {
                                _usedefaultid = true;

                            }
                        }
                        else
                        {
                            _usedefaultid = true;
                        }
                    }
                    else
                    {
                        _usedefaultid = true;
                    }
                }//end if deliveryaddress > 0

                //default company filter 
                if (_usedefaultid)
                {
                    Parameter _p = return_default_view(-1);
                    if (_p != null) { _params.Add(_p); }
                }
            }
            //check for additional parameters if query is not from history (mode=0)
            //but you can only apply these filters when a) user is logged in or b) a query parameter has been entered
            //otherwise you could create a default query of e.g. (Jobclosed==false) which would return ALL closed jobs in database
            //if ((_mode != "0") && (_query !="" | _companyid !=-1))
            //
            if ((_mode != "0" & _mode != "1") && (_query != "" || _params.Count > 0))
            {
                //28/08/2010 users can filter by individual contacts within the company
                //if its an employee we need to check
                //((OrderControllerID=={cboname.Value}) or (OperationsControllerID=={cboname.Value})) or
                //(OriginPortControllerID=={cboname.Value}) or (DestinationPortControllerID=={cboname.Value})) !!!
                //19/10/2010 only use contact id is user is not doing their own status report
                //if (_mode != "3" && this.cboName.Value != null)
                if (this.cboName.Value != null)
                {
                    //11/03/2011 (All users) option added value = -1 use companyid to pull out all records for company instead of individual user
                    //so we don't need to do anyhing as companyid has been parametised above
                    if (!String.IsNullOrEmpty(this.cboName.Value.ToString()) && this.cboName.Value.ToString() != "-1")
                    {
                        _params.Add("ContactID", this.cboName.Value.ToString());
                        _name += ", user name equals " + this.cboName.Text.ToString();
                    }

                }

                //15/09/2010 include closed jobs y/n when combo = Active jobs (jobclosed = 1) or combo = closed jobs (jobclosed = 0)
                //when combo = All jobs we can ignore this filter
                if (this.dxcboclosedyn.Value != null)
                {
                    _params.Add("JobClosed", Convert.ToBoolean(this.dxcboclosedyn.Value).ToString());
                    _name += ", job status equals " + this.dxcboclosedyn.Text.ToString().Replace("Search", "");

                }

            }

            
            //now rebuild query with additional parameters AFTER page is loaded
            string _f = "";
            if (_params.Count > 0)
            {
                foreach (Parameter p in _params)
                {
                    string _pname = p.Name.ToString();
                    string _op = "AND";
                    string[] _check = _pname.Split("_".ToCharArray());
                    _pname = _check[0].ToString();
                    _op = _check.Length > 1 ? _check[1].ToString() : _op;

                    string _a = _f != "" ? " " + _op + " " : "";
                    _f += _pname != "NULL" ? _a + "(" + _pname + "==" + p.DefaultValue.ToString() + ")" : _a + "(" + p.DefaultValue.ToString() + ")";

                }

                if (_query != "") { _query = _f + " AND " + _query; } else { _query = _f; }
            }
        }

        //deprecated 100113 added during company check
        //add country restrictions
        //if (_countries != "") { _query += " AND (" + _countries + ")"; }

        //19/04/2013 re-designed query means we can use subdeliveryid as key NO IT DOESN'T back to OrderIx
        //dynamic queries using system.Linq.dynamic + Dynamic.cs library
        //20/10/2010 we have build a unqiue index (OrderIx) from OrderId, TitleId, ContainerSubId as usual primary keys are not going to 
        //be unique in the view. aspxgrid only works properly when it has a unique key 

        //****************
        //get starting ETS date for deliveries from xml file (which maqes it easy to change if necessary)
        //convert(datetime,'28/03/2013 10:32',103)
        DateTime? _ets = wwi_func.vdatetime(wwi_func.lookup_xml_string("xml\\parameters.xml", "name", "startETS", "value"));
        //****************
            
        //important! need a key id or error=key expression is undefined
        e.KeyExpression = "ContainerIdx";

        if (!string.IsNullOrEmpty(_query))
        {
            //var _query = new linq_classesDataContext().view_orders.Where(_filter);
            //290413 using new userdefined inline table function so we can parametise with month range from current date
            //var _nquery = new linq_view_orders_udfDataContext().view_orders_by_age(1, 12).Where(_query); //c => c.CompanyID == 7
            var _nquery = new linq.linq_view_aggregate_containersDataContext().aggregate_containers_by_ets_and_filters(_ets, _contactid).Where(_query); //c => c.CompanyID == 7
            e.QueryableSource = _nquery;

            //Int32 _count = _nquery.Count();

            if (!String.IsNullOrEmpty(_name))
            {
                append_to_query_log(_query, _name);
                this.gridContainer.SettingsText.Title = "Search results: " + _name;
            }
        }
        else //default to display nothing until page is loaded 
        {
            //var _nquery = new linq_classesDataContext().view_order_2s.Where(c => c.OrderNumber == -1);
            var _nquery = new linq.linq_view_aggregate_containersDataContext().aggregate_containers_by_ets_and_filters(_ets, _contactid).Where(c => c.ContainerIdx == -1); //c => c.CompanyID == 7
            //_count = _nquery.Count();

            e.QueryableSource = _nquery;
        }


    }
    /// <summary>
    /// data repeater responding to linkbutton click event
    /// </summary>
    /// <param name="source"></param>
    /// <param name="e"></param>
    protected void rptQuery_ItemCommand(object source, RepeaterCommandEventArgs e)
    {
        try
        {
            //string _filter = ((LinkButton)e.CommandSource).Text.ToString();
            string _query = ((LinkButton)e.CommandSource).CommandArgument.ToString();
            string _named = ((LinkButton)e.CommandSource).Text.ToString();

            if (!string.IsNullOrEmpty(_query))
            {
                //System.Collections.Hashtable _htfilter = new System.Collections.Hashtable();
                //_htfilter.Add("query", _query);
                //_htfilter.Add("named", _named);
                //_htfilter.Add("state", "0"); //so we don't save again

                //rebuild session and flag hidden field
                //Session["filter"] = _htfilter;
                SessionParameterPasser _sessionWrapper = new SessionParameterPasser();
                _sessionWrapper["query"] = _query;
                _sessionWrapper["name"] = _named;

                this.dxhfMethod.Set("mode", "0");
                this.gridContainer.DataBind();
            }
        }
        catch (Exception ex)
        {
            //Response.Write(ex.Message.ToString());
            this.lblmsgboxdiv.Text += "<div class='alert'>Error description" + ": " + ex.Message.ToString() + "</div>";
        }
    }
    protected void Page_Load(object sender, EventArgs e)
    {

        //on 1st load if the last query in session was on a different tracking page clear the session
        if (!Page.IsPostBack && !Page.IsCallback)
        {
            SessionParameterPasser _sessionWrapper = new SessionParameterPasser();
            if (_sessionWrapper["source"] != null)
            {
                string _source = _sessionWrapper["source"].ToString();  
                string _page = wwi_func.get_current_page_name();
                if (!_page.Contains(_source))
                {
                    _sessionWrapper["query"] = null;
                    _sessionWrapper["name"] = null;
                    Session["querytable"] = null;
                }
            }
        }

        if (!Page.ClientScript.IsClientScriptBlockRegistered("lg_key"))
        {
            register_client_scripts();
        }

        
        if (Page.Session["user"] != null)
        {
            //be careful wrapping set_visible_data() in postback. If Grid.EnableViewState=false we will lose column settings
            //we might have to change this !Page.IsPostBack so it only applies to internal users who need the upload control
            if (!Page.IsPostBack)
            {
                Int32 _cid = (Int32)((UserClass)Page.Session["user"]).CompanyId;
                string _usr = ((UserClass)Page.Session["user"]).UserId.ToString();
                string _uid = _usr + "_" + _cid.ToString();
                //170112 hide company name filter unless publiship user

                //this.gridOrder.Columns["Upload"].Visible = false; } else { this.gridOrder.Columns["Upload"].Visible = true;
                this.dxcbocompany.Enabled = true;

                if (has_preferences(_cid.ToString()))
                {
                    set_visible_data(_cid.ToString());
                }
                else
                {
                    if (!get_cookie("ord_tracking"))
                    {
                        set_visible_data("default");
                    }
                }
            }
        }
        else
        {
            //030212 no longer necessary we force to anonymous tracking if not logged in
            //set_visible_data(false);
            //this.gridOrder.Columns["Upload"].Visible = false;
            if (!Page.IsCallback) { Response.Redirect("~/tracking/shipment_tracking_unsigned.aspx", true); } 
              
        }

        //new linq databinding 
        //this method of using linq does not run in server mode, you MUST use a LinqServerModeDataSource
        //bind_linq_datasource(); 
        //running in server mode
        this.LinqServerModeOrders.Selecting += new EventHandler<DevExpress.Data.Linq.LinqServerModeDataSourceSelectEventArgs>(LinqServerModeOrders_Selecting);

    }
    }//end linq server mode

    /// <summary>
    /// derive filter from selected row and apply to orders view
    /// rebuild session with selected filter
    /// redirect to orders search page
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void dxgrdquerylog_RowCommand(object sender, ASPxGridViewRowCommandEventArgs e)
    {
        try
        {
            Int32 _idx = e.VisibleIndex;
            //string[] _fields = {"qry_text","qry_desc"};

            string _fex = this.dxgrdquerylog.GetRowValues(_idx, "qry_text").ToString();
            string _fname = this.dxgrdquerylog.GetRowValues(_idx, "qry_desc").ToString();
            string _fsource = this.dxgrdquerylog.GetRowValues(_idx, "qry_source").ToString();
            string _default = "shipment";//default to shipment tracking
            string _url = "../tracking/{0}_tracking.aspx";

            _url = _fsource != "" ? string.Format(_url, _fsource): string.Format(_url, _default);    
            //old code we are using form names instead of codes in qry_source as of 20/03/15 
            //if (_fsource == "CNTR") { 
            //    _url = "../tracking/container_tracking.aspx";
            //}
            //else if(_fsource == "DLVRY"){
            //     _url = "../tracking/delivery_tracking.aspx";
            //}
            //else if(_fsource == "NSHIP"){
            //     _url =  "../tracking/not_shipped_tracking.aspx";
            //}
           
            if (!string.IsNullOrEmpty(_fex))
            {
                SessionParameterPasser _sessionWrapper = new SessionParameterPasser(_url);
                _sessionWrapper["query"] = _fex;
                _sessionWrapper["name"] = _fname;
                _sessionWrapper["mode"] = "0";
                _sessionWrapper["source"] = _fsource;
                _sessionWrapper.PassParameters();
                //force submit of query and set mode to 0 (history)
                //this does not work!
                //Page.ClientScript.RegisterStartupScript(GetType(), "QRY_MOD", "window.submit_query(0);", true);
                //Response.Redirect("~/Default.aspx",false); 
            }
        }
        catch(Exception ex)
        {
            Response.Write(ex.Message.ToString());  
        }
    }
    }//end linq server mode

    /// <summary>
    /// derive filter from selected row and apply to cargo update editor - find by selected order id
    /// rebuild session with selected filter
    /// redirect to orders search page
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void dxgrdquerylog_RowCommand(object sender, ASPxGridViewRowCommandEventArgs e)
    {
        try
        {
            Int32 _idx = e.VisibleIndex;
            //string[] _fields = {"qry_text","qry_desc"};

            string _orderid = this.dxgrdquerylog.GetRowValues(_idx, "orderid").ToString();

            if (!string.IsNullOrEmpty(_orderid))
            {
                SessionParameterPasser _sessionWrapper = new SessionParameterPasser("~/Ord_Edit_Cargo.aspx");
                _sessionWrapper["query"] = "orderid==" + _orderid;
                _sessionWrapper["name"] = "query_order_id";
                _sessionWrapper["mode"] = "0";
                _sessionWrapper.PassParameters();
                //force submit of query and set mode to 0 (history)
                //this does not work!
                //Page.ClientScript.RegisterStartupScript(GetType(), "QRY_MOD", "window.submit_query(0);", true);
                //Response.Redirect("~/Default.aspx",false); 
            }
        }
        catch(Exception ex)
        {
            Response.Write(ex.Message.ToString());  
        }
    }
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnApply_Click(object sender, EventArgs e)
    {
        //01122011 PME if user has created a query string but datatable is empty i.e. they did not click the + button to add to datatable
        //populate datatable with query row
        DataTable _dt = (DataTable)Session["querytable"];
        if (_dt.Rows.Count == 0 ) //force check to see whats in input boxes
        {
            datatable_add_row(); 
        }

        //string _magic = "\""; //set up quotes correctly in string 
        //this.txtQueryResult.Text = this.advancedFilter.FilterExpression.Replace("#", _magic).ToString(); //this.advancedFilter.FilterExpression.ToString();
        //System.Collections.Hashtable _htfilter = new System.Collections.Hashtable();
        //
        //12/10/2010 new search builder does not require parsing for Linq
        string _fex = get_query_from_rows(); //this.advancedFilter.GetFilterExpressionForOracle().ToString();
        //24/06/2011 for date in next/previous X days, parse out the current dates and replace with markers
        //so we can re-use the query

        //24/06/2011 if add to reports is ticked, flag in database so we can add to drop down on search form
        string _ck = this.dxckReport.Checked == true ? "___report" : "";
        string _fname = get_query_name() + _ck; 
        //force advanced search session to clear
        //09/06/2011 do not clear session so user can re-apply
        //Session.Remove("querytable");
        
        if (_fex != string.Empty)
        {
            //12/10/2010 new search builder does not require parsing for Linq, as the string
            //is formatted depending on the linq attribute in xml 
            //we just need to build the query from data rows in repeater
            //  
            //_fex = set_string_parser(_fex);
            //    
            //if (_fex.Contains("#"))
            //{
            //      _fex = set_datetime_parser(_fex);
            //}
            
            SessionParameterPasser _sessionWrapper = new SessionParameterPasser();
            _sessionWrapper["query"] = _fex;
            _sessionWrapper["name"] = _fname;
            
            this.txtQueryResult.Text = _fname;

            //pass search params back to parent
            //ClientScript.RegisterStartupScript(GetType(), "QRY_KEY", "window.parent.lblmsgbox.SetText(txtQuery.GetText());", true);
            //close this window
            //ClientScript.RegisterStartupScript(GetType(), "ANY_KEY", "window.parent.closefilterWindow();", true);
            //force reload of primary grid
            //ClientScript.RegisterStartupScript(GetType(), "DAT_KEY", "window.parent.grdOrder.PerformCallback();", true);
            //all one script
            //one script
            this.ClientScript.RegisterStartupScript(GetType(), "QRY_KEY", "window.parent.lblmsgbox.SetText(txtQuery.GetText());window.parent.popDefault.HideWindow(window.parent.popDefault.GetWindowByName('filterform'));window.parent.submit_query(2);", true);
        }
        else
        {  
            //just close popup
            //Session.Remove("querytable");
            ClientScript.RegisterStartupScript(GetType(), "EXT_KEY", "window.parent.popDefault.HideWindow(window.parent.popDefault.GetWindowByName('filterform'));", true);
        }
    }
    //end load

    #region grid databinding
    /// <summary>
    /// this code is used with LinqServerModeDataSource_Selecting so we can run in server mode
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void LinqServerModePod_Selecting(object sender, DevExpress.Data.Linq.LinqServerModeDataSourceSelectEventArgs e)
    {

        Int32 _companyid = -1; //after testing default to empty string 
        SessionParameterPasser _sessionWrapper = new SessionParameterPasser();
        ParameterCollection _params = new ParameterCollection();
        //check if session created from advanced search, in which case we can use the parameters passed back
        string _query = "";
        int _mode = this.dxhfsource.Contains("mode") ? wwi_func.vint(this.dxhfsource["mode"].ToString()) : 1; //default mode to quick search

        //a simplified version of the methods used in order tracking - no history but advanced search is available
        if (_sessionWrapper["query"] != null && _mode == 2)
        {
            _query = _sessionWrapper["query"].ToString();
        }
        else
        {
            _query = get_filter();
        }
        //company id: always add as a search param if user is logged in
        //if (Page.Session["user"] != null)
        //company id: always add as a search param if user is logged in UNLESS _mode = -1 which we can use to bypass params
        if (Page.Session["user"] != null)
        {
            _companyid = (Int32)((UserClass)Page.Session["user"]).CompanyId;

            if (_companyid != -1) //-1 is a WWI company
            {
                Parameter _p = return_default_view(-1);
                if (_p != null) { _params.Add(_p); }
            }

        }

        //now rebuild query with additional parameters
        string _f = "";
        if (_params.Count > 0)
        {
            foreach (Parameter p in _params)
            {
                string _a = _f != "" ? " AND " : "";
                _f += _a + "(" + p.Name.ToString() + "==" + p.DefaultValue.ToString() + ")";
            }

            if (_query != "") { _query = _f + " AND " + _query; } else { _query = _f; }
        }

        //get start date from dll value
        //e.g if search is for last 12 months dllvalue 1 start date = current date - (1 * 12) months
        //if search is for 2-3 years dllvalue 3 start date = current date - (3 * 12) months
        int _dllvalue = this.dxcboRange.Value != null ? wwi_func.vint(this.dxcboRange.Value.ToString()) : 1;
        //number of months to include after start date
        int _months = 12;
        //multiply base * 12 to get start date
        int _lowest = 0 - (_dllvalue * 12);
        DateTime _minDate = DateTime.Now.AddMonths(_lowest);

        //dynamic queries using system.Linq.dynamic + Dynamic.cs library
        //20/10/2010 we have build a unqiue index (OrderIx) from OrderId, TitleId, ContainerSubId as usual primary keys are not going to 
        //be unique in the view. aspxgrid only works properly when it has a unique key 
        e.KeyExpression = "OrderIx"; //"OrderID"; //a key expression is required 

        if (!string.IsNullOrEmpty(_query))
        {
            //var _nquery = new linq_classesDataContext().view_orders.Where(_query); //c => c.CompanyID == 7
            var _nquery = new linq.linq_view_orders_udfDataContext().view_orders_by_age(_minDate, _months).Where(_query); //c => c.CompanyID == 7
            e.QueryableSource = _nquery;
            //Int32 _count = _nquery.Count();

        }
        else //default to display nothing in grid 
        {
            //var _nquery = new linq_classesDataContext().view_orders.Where(c => c.OrderNumber == -1);
            var _nquery = new linq.linq_view_orders_udfDataContext().view_orders_by_age(_minDate, _months).Where(c => c.OrderNumber == -1);
            //_count = _nquery.Count();

            e.QueryableSource = _nquery;
        }
    }
    //end button save

    /// <summary>
    /// reset search
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnEndFilter_Click(object sender, EventArgs e)
    {
        this.txtQuickSearch.Text = "";
        this.dxhfsource.Set("mode", 1); //default to quick search 
        SessionParameterPasser _sessionWrapper = new SessionParameterPasser();
        _sessionWrapper["mode"] = null;
        _sessionWrapper["query"] = null;
        _sessionWrapper["name"] = null;

        this.dxgdvOrder.DataBind();
    }
    /// <summary>
    /// this code is used with LinqServerModeDataSource_Selecting so we can run in server mode
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void LinqServerModeOrders_Selecting(object sender, DevExpress.Data.Linq.LinqServerModeDataSourceSelectEventArgs e)
    {

        ParameterCollection _params = new ParameterCollection();
        SessionParameterPasser _sessionWrapper = new SessionParameterPasser();
        Int32 _companyid = -1; //after testing default to empty string 

        //check if session created from advanced search, in which case we can use the parameters passed back
        string _query = "";
        string _name = "";
        string _mode = "";

        if (_sessionWrapper["mode"] != null) //this is only usually set when we pass it back from history search or logout
        {
            _mode = (string)_sessionWrapper["mode"];
            _sessionWrapper["mode"] = null;
        }
        else
        {
            _mode = this.dxhfMethod.Contains("mode") ? this.dxhfMethod["mode"].ToString() : "0"; //this.dxhfQuery["method"].ToString();
        }

        //mode 0=history, 1=basic search so rebuild filter, 2=advanced search, 3=user status report
        if (_mode == "0")
        {
            if (_sessionWrapper["query"] != null && _sessionWrapper["name"] != null)
            {
                _query = _sessionWrapper["query"].ToString();
                _name = _sessionWrapper["name"].ToString();
            }
        }
        else if (_mode == "1")
        {
            _query = get_filter();
            _name = get_name();
        }
        else if (_mode == "2")
        {
            if (_sessionWrapper["query"] != null && _sessionWrapper["name"] != null)
            {
                _query = _sessionWrapper["query"].ToString();
                _name = _sessionWrapper["name"].ToString();
            }
        }

        //company id: always add as a search param if user is logged in
        //if (Page.Session["user"] != null)
        //company id: always add as a search param if user is logged in UNLESS _mode = -1 which we can use to bypass params
        if (Page.Session["user"] != null && _mode != "-1" && _mode != "0")
        {
            _companyid = (Int32)((UserClass)Page.Session["user"]).CompanyId;

            if (_companyid != -1) //-1 is a WWI company
            {
                Parameter _p = return_default_view(-1);
                if (_p != null) { _params.Add(_p); }
            }

            //11/03/2011 this is done below!
            //19/10/2010 if mode=3 add contact id/employee as param
            //if (_mode == "3")
            //{
            //    if (_companyid != -1) //-1 = ~WWI employee so need to use employee id
            //    {
            //        Parameter _p = return_default_view(1);
            //        if (_p != null) { _params.Add(_p); }
            //    }
            //    else
            //    {
            //        Parameter _p = return_default_view(3);
            //        if (_p != null) { _params.Add(_p); }
            //    }
            //    //for status report just show active jobs? or use combo below
            //    //_params.Add("JobClosed", Convert.ToBoolean("false").ToString());
            //} 
        }

        //check for additional parameters if query is not from history (mode=0)
        //but you can only apply these filters when a) user is logged in or b) a query parameter has been entered
        //otherwise you could create a default query of e.g. (Jobclosed==false) which would return ALL closed jobs in database
        //if ((_mode != "0") && (_query !="" | _companyid !=-1))
        //
        if ((_mode != "0" && _mode != "1") && (_query != "" || _params.Count > 0))
        {
            //28/08/2010 users can filter by individual contacts within the company
            //if its an employee we need to check
            //((OrderControllerID=={cboname.Value}) or (OperationsControllerID=={cboname.Value})) or
            //(OriginPortControllerID=={cboname.Value}) or (DestinationPortControllerID=={cboname.Value})) !!!
            //19/10/2010 only use contact id is user is not doing their own status report
            //if (_mode != "3" && this.cboName.Value != null)
            if (this.cboName.Value != null)
            {
                //11/03/2011 (All users) option added value = -1 use companyid to pull out all records for company instead of individual user
                //so we don't need to do anyhing as companyid has been parametised above
                if (!String.IsNullOrEmpty(this.cboName.Value.ToString()) && this.cboName.Value.ToString() != "-1")
                {
                    _params.Add("ContactID", this.cboName.Value.ToString());
                }

            }

            //15/09/2010 include closed jobs y/n when combo = Active jobs (jobclosed = 1) or combo = closed jobs (jobclosed = 0)
            //when combo = All jobs we can ignore this filter
            if (this.dxcboclosedyn.Value != null)
            {
                _params.Add("JobClosed", Convert.ToBoolean(this.dxcboclosedyn.Value).ToString());

            }
        }

        //additional filtering options e.g. today's updates
        if(this.dxhfMethod.Contains("hfparam"))
        {
            string _hfparam = this.dxhfMethod.Get("hfparam").ToString();

            switch (_hfparam)
            {
                case "today": {
                    _params.Add("dtupdated.Value.Date", "DateTime.Parse(\"" + DateTime.Today.ToShortDateString() + "\")");  
                    break;
                }
                default: {
                    break;
                }
            }

            this.dxhfMethod.Remove("hfparam"); 
        }

        //now build query with additional parameters
        string _f = "";
        if (_params.Count > 0)
        {
            foreach (Parameter p in _params)
            {
                string _a = _f != "" ? " AND " : "";
                _f += _a + "(" + p.Name.ToString() + "==" + p.DefaultValue.ToString() + ")";
            }

            if (_query != "") { _query = _f + " AND " + _query; } else { _query = _f; }
        }

        //get start date from dll value
        //e.g if search is for last 12 months dllvalue 1 start date = current date - (1 * 12) months
        //if search is for 2-3 years dllvalue 3 start date = current date - (3 * 12) months
        int _dllvalue = this.dxcboRange.Value != null ? wwi_func.vint(this.dxcboRange.Value.ToString()) : 1;
        //number of months to include after start date
        int _months = 12;
        //multiply base * 12 to get start date
        int _lowest = 0 - (_dllvalue * 12);
        DateTime _minDate = DateTime.Now.AddMonths(_lowest);

        //dynamic queries using system.Linq.dynamic + Dynamic.cs library
        //20/10/2010 we have build a unqiue index (OrderIx) from OrderId, TitleId, ContainerSubId as usual primary keys are not going to 
        //be unique in the view. aspxgrid only works properly when it has a unique key 
        e.KeyExpression = "OrderIx"; //"OrderID"; //a key expression is required 

        if (!string.IsNullOrEmpty(_query))
        {
            //var _nquery = new linq_classesDataContext().view_orders.Where(_query); //c => c.CompanyID == 7
            var _nquery = new linq.linq_view_orders_udfDataContext().view_orders_by_age(_minDate, _months).Where(_query); //c => c.CompanyID == 7
            e.QueryableSource = _nquery;
            //Int32 _count = _nquery.Count();

            if (!String.IsNullOrEmpty(_name)) { append_to_query_log(_query, _name); }
        }
        else //default to display nothing in grid 
        {
            //var _nquery = new linq_classesDataContext().view_orders.Where(c => c.OrderNumber == -1);
            var _nquery = new linq.linq_view_orders_udfDataContext().view_orders_by_age(DateTime.Now, 0).Where(c => c.OrderNumber == -1) ;
            //_count = _nquery.Count();
            e.QueryableSource = _nquery;
        }
    }
    /// <summary>
    /// remove filter
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnEndFilter_Click(object sender, EventArgs e)
    {
        this.txtQuickSearch.Text = "";
        this.cboName.Value = null;

        SessionParameterPasser _sessionWrapper = new SessionParameterPasser();
        _sessionWrapper["mode"] = null;
        _sessionWrapper["query"] = null;
        _sessionWrapper["name"] = null;

        //Session["filter"] = null; //so we don't save it again
        reset_hidden(); //sets mode back to default 0
        this.gridOrder.DataBind();
    }
    /// <summary>
    /// this code is used with LinqServerModeDataSource_Selecting so we can run in server mode
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void LinqServerModeOrders_Selecting(object sender, DevExpress.Data.Linq.LinqServerModeDataSourceSelectEventArgs e)
    {

        ParameterCollection _params = new ParameterCollection();
        SessionParameterPasser _sessionWrapper = new SessionParameterPasser();
        Int32 _companyid = -1; //after testing default to empty string 
        string _countries = "";
        //check if session created from advanced search, in which case we can use the parameters passed back
        string _query = "";
        string _name = "";
        string _mode = "";
                
        if (_sessionWrapper["mode"] != null) //this is only usually set when we pass it back from history search or logout
        {
            _mode = (string)_sessionWrapper["mode"];
            _sessionWrapper["mode"] = null;
        }
        else
        {
            _mode = this.dxhfMethod.Contains("mode") ? this.dxhfMethod["mode"].ToString() : "0"; //this.dxhfQuery["method"].ToString();
        }

        //mode 0=history, 1=basic search so rebuild filter, 2=advanced search, 3=user status report
        if (_mode == "0")
        {
            if (_sessionWrapper["query"] != null && _sessionWrapper["name"] != null)
            {
                _query = _sessionWrapper["query"].ToString();
                _name = _sessionWrapper["name"].ToString();
            }
        }
        else if (_mode == "1")
        {
            _query = get_filter();
            _name = get_name();
        }
        else if (_mode == "2")
        {
            if (_sessionWrapper["query"] != null && _sessionWrapper["name"] != null)
            {
                _query = _sessionWrapper["query"].ToString();
                _name = _sessionWrapper["name"].ToString();
            }
        }
        else if (_mode == "4")
        {
            _query = "OrderNumber > -1";
            this.dxhfMethod.Set("mode", 0); 
        }
        //company id: always add as a search param if user is logged in
        //if (Page.Session["user"] != null)
        //company id: always add as a search param if user is logged in UNLESS _mode = -1 which we can use to bypass params
        if (Page.Session["user"] != null)
        {
            bool _usedefaultid = false;

            if (_mode != "-1" && _mode != "0")
            {
                _companyid = (Int32)((UserClass)Page.Session["user"]).CompanyId;

                //if intrernal user check for a selected company
                //if external user but they have access to company drop dowm check for selected company and if restricted to particular countries for selected companyID
                //else return default
                if (_companyid == -1)
                {
                    if (!string.IsNullOrEmpty((string)this.dxcbocompany.Value)) { _params.Add("CompanyID", this.dxcbocompany.Value.ToString()); }
                    _name += this.dxcbocompany.Text.ToString() != "" ? ", company name equals " + this.dxcbocompany.Text.ToString() : ""; 
                }
                else if (_companyid > 0 && this.dxcbocompany.Enabled)
                {
                    string _selectedcompany = string.IsNullOrEmpty((string)this.dxcbocompany.Value) ? _companyid.ToString() : this.dxcbocompany.Value.ToString();
                    if (!string.IsNullOrEmpty(_selectedcompany))
                    {
                        _params.Add("CompanyID", this.dxcbocompany.Value.ToString()); //select for this company of list
                        _params.Add("ConsigneeID", _companyid.ToString()); //select for this user's company

                        //check for additional country restrictions e.g. EDC can see usborne shipments but ONLY to the US
                        IList<string> _args = wwi_func.array_from_xml("xml\\company_iso.xml", "companylist/company[id='" + _companyid + "']/visibleitems/item[itemid='" + this.dxcbocompany.Value.ToString() + "']/destinationid");
                        if (_args.Count > 0)
                        {
                            //don't use sql IN(n) as linq won't parse the statement
                            _countries = "CountryID==" + string.Join(" OR CountryID==", _args.Select(i => i.ToString()).ToArray());
                        }
                    }
                    else
                    {
                        _usedefaultid = true;
                    }
                }
                else
                {
                    _usedefaultid = true;
                }

            }
            else
            {
                _usedefaultid = true;
            }

            if (_usedefaultid)
            {
                Parameter _p = return_default_view(-1);
                if (_p != null) { _params.Add(_p); }
            }
        }

        //check for additional parameters if query is not from history (mode=0)
        //but you can only apply these filters when a) user is logged in or b) a query parameter has been entered
        //otherwise you could create a default query of e.g. (Jobclosed==false) which would return ALL closed jobs in database
        //if ((_mode != "0") && (_query !="" | _companyid !=-1))
        //
        if ((_mode != "0" & _mode != "1") && (_query != "" || _params.Count > 0))
        {
            //28/08/2010 users can filter by individual contacts within the company
            //if its an employee we need to check
            //((OrderControllerID=={cboname.Value}) or (OperationsControllerID=={cboname.Value})) or
            //(OriginPortControllerID=={cboname.Value}) or (DestinationPortControllerID=={cboname.Value})) !!!
            //19/10/2010 only use contact id is user is not doing their own status report
            //if (_mode != "3" && this.cboName.Value != null)
            if (this.cboName.Value != null)
            {
                //11/03/2011 (All users) option added value = -1 use companyid to pull out all records for company instead of individual user
                //so we don't need to do anyhing as companyid has been parametised above
                if (!String.IsNullOrEmpty(this.cboName.Value.ToString()) && this.cboName.Value.ToString() != "-1")
                {
                    _params.Add("ContactID", this.cboName.Value.ToString());
                    _name += ", user name equals " + this.cboName.Text.ToString(); 
                }

            }

            //15/09/2010 include closed jobs y/n when combo = Active jobs (jobclosed = 1) or combo = closed jobs (jobclosed = 0)
            //when combo = All jobs we can ignore this filter
            if (this.dxcboclosedyn.Value != null)
            {
                _params.Add("JobClosed", Convert.ToBoolean(this.dxcboclosedyn.Value).ToString());
                _name += ", job status equals " + this.dxcboclosedyn.Text.ToString().Replace("Search", "");  

            }

        }

        //now rebuild query with additional parameters
        string _f = "";
        if (_params.Count > 0)
        {
            foreach (Parameter p in _params)
            {
                string _a = _f != "" ? " AND " : "";
                _f += _a + "(" + p.Name.ToString() + "==" + p.DefaultValue.ToString() + ")";
            }

            if (_query != "") { _query = _f + " AND " + _query; } else { _query = _f; }
        }

        //add country restrictions
        if (_countries != "") { _query += " AND (" + _countries + ")"; }
        //finally if there's no query string check filter expression and force search, otherwise the default search is to display no records. this is only a problem for publiship 
        //users as everyone else will at least have the company filter
        if (_query == "") {
            if (this.gridOrder.FilterExpression.ToString() != "") {
                _query = "OrderNumber > -1";
            }  
        } 
        //19/04/2013 re-designed query means we can use subdeliveryid as key NO IT DOESN'T back to using OrderIx
        //dynamic queries using system.Linq.dynamic + Dynamic.cs library
        //20/10/2010 we have build a unqiue index (OrderIx) from OrderId, TitleId, ContainerSubId as usual primary keys are not going to 
        //be unique in the view. aspxgrid only works properly when it has a unique key 
        e.KeyExpression = "OrderIx"; //"OrderID"; //a key expression is required 
        
        if (!string.IsNullOrEmpty(_query))
        {
            //get start date from dll value
            //e.g if search is for last 12 months dllvalue 1 start date = current date - (1 * 12) months
            //if search is for 2-3 years dllvalue 3 start date = current date - (3 * 12) months
            int _dllvalue = this.dxcboMonths.Value != null ? wwi_func.vint(this.dxcboMonths.Value.ToString()) : 1;
            //number of months to include after start date
            int _months = 12;
            //multiply base * 12 to get start date
            int _lowest = 0 - (_dllvalue * 12);
            DateTime _minDate = DateTime.Now.AddMonths(_lowest);
            //get from date range startdate + N months
            //290413 using new usedefined inline table function so we can parametise with month range
            //in the anon view default to last 12 months
            //var _nquery = new linq_classesDataContext().view_order_2s.Where(_query); //c => c.CompanyID == 7
            var _nquery = new linq.linq_view_orders_udfDataContext().view_orders_by_age(_minDate, _months).Where(_query); //c => c.CompanyID == 7
            e.QueryableSource = _nquery;
            //Int32 _count = _nquery.Count();

            if (!String.IsNullOrEmpty(_name))
            {
                append_to_query_log(_query, _name);
            }
            this.gridOrder.SettingsText.Title = "Search results: " + _name;
        }
        else //default to display nothing in grid 
        {
            //var _nquery = new linq_classesDataContext().view_order_2s.Where(c => c.SubDeliveryID == -1);
            var _nquery = new linq.linq_view_orders_udfDataContext().view_orders_by_age(DateTime.Now, 0).Where(c => c.OrderNumber == -1); //c => c.CompanyID == 7
            //_count = _nquery.Count();

            e.QueryableSource = _nquery;
        }


    }