using Foresight.Fleet.Services.Asset;
using Foresight.Fleet.Services.AssetHealth;
using Foresight.Fleet.Services.JobSite;
using FU = Foresight.Fleet.Services.User;
using IronIntel.Contractor.Machines;
using IronIntel.Contractor.Maintenance;
using IronIntel.Contractor.MapView;
using IronIntel.Contractor.Users;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Foresight.Fleet.Services.Partner;
using Foresight.Fleet.Services.AssetHealth.WorkOrder;
using FFSDevice = Foresight.Fleet.Services.Device;
using System.Web;
using Foresight.Fleet.Services.Inspection;
using DocumentFormat.OpenXml.Wordprocessing;
using System.Security.Cryptography;

namespace IronIntel.Contractor
{
    public class ExportExcelManager
    {
        public static string SetExprotParams(string p)
        {
            string key = Guid.NewGuid().ToString();
            byte[] tmp = Encoding.UTF8.GetBytes(p);
            tmp = Foresight.Security.SecurityHelper.Compress(tmp);
            CacheManager.SetValue(key, tmp, new TimeSpan(0, 3, 0));
            return key;

        }

        public static string GetExportParams(string key)
        {
            byte[] tmp = CacheManager.GetValue(key);
            if (tmp != null)
            {
                tmp = Foresight.Security.SecurityHelper.Decompress(tmp);
                string p = Encoding.UTF8.GetString(tmp);
                CacheManager.Remove(key);
                return p;
            }
            return null;
        }

        public static byte[] ExportRentals(string lang, string sessionid, string companyid, long machineid, DateTime from, DateTime to, string searchtext, string useriid, string sortPath, bool desc)
        {
            if (string.IsNullOrEmpty(companyid))
                companyid = SystemParams.CompanyID;

            AssetRentalInfo[] rentalinfos = FleetServiceClientHelper.CreateClient<AssetQueryClient>(companyid, sessionid).GetAssetRentals(companyid, searchtext, useriid);

            List<MachineRentalInfo> ls = new List<MachineRentalInfo>();
            foreach (AssetRentalInfo ri in rentalinfos)
            {
                MachineRentalInfo mi = new MachineRentalInfo();
                Helper.CloneProperty(mi, ri);
                mi.RentalRate = (decimal)ri.RentalRate;
                ls.Add(mi);
            }

            var rentals = ls.ToArray();
            if (machineid > 0)
                rentals = rentals.Where(m => m.MachineID == machineid).ToArray();

            rentals = rentals.Where(m => m.RentalDate >= from && m.RentalDate <= to).ToArray();

            if (!string.IsNullOrEmpty(sortPath))
            {
                if (desc)
                {
                    rentals = rentals.OrderByDescending(m =>
                    {
                        return OrderHandler(m, sortPath);
                    }).ToArray();
                }
                else
                {
                    rentals = rentals.OrderBy(m =>
                    {
                        return OrderHandler(m, sortPath);
                    }).ToArray();
                }
            }

            ExportToExcel ete = new ExportToExcel();

            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_VINSN", "VIN/SN") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_ASSETNAME", "Asset Name") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_OUTSIDEINTERNAL", "Outside/Internal") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_RENTALVENDOR", "Rental Vendor") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_RENTALRATE", "Rental Rate") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_TERM", "Term") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_TERMUNIT", "Term Unit") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_RENTALDATEON", "Rental Date On") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_PROJECTRETURNDATE", "Project Return Date") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_RETURNDATE", "Return Date") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_PURCHASEORDERN", "Purchase Order #") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_INSUREDVALUE", "Insured Value") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_COMMENTS", "Comments") });

            foreach (var r in rentals)
            {
                int index = 0;
                var dr = dt.NewRow();
                dr[index] = r.VIN;
                dr[++index] = r.DisplayName;
                dr[++index] = r.Outside;
                dr[++index] = r.Vendor;
                dr[++index] = r.RentalRate;
                dr[++index] = r.Term;
                dr[++index] = r.TermUnit;
                dr[++index] = r.RentalDateStr;
                dr[++index] = r.ProjectReturnDateStr;
                dr[++index] = r.ReturnDateStr;
                dr[++index] = r.PONumber;
                dr[++index] = r.InsuredValue;
                dr[++index] = r.Comments;
                dt.Rows.Add(dr);
            }
            double[] widths = new double[] { 180d, 180d, 180d, 150d, 150d, 150d, 150d, 150d, 150d, 150d, 150d, 150d, 200d };
            byte[] data = ete.CreateExcel(dt, null, widths, null);

            return data;
        }

        public static byte[] ExportRentalChanges(string lang, string sessionid, string companyid, long machineid, long rentalid, DateTime from, DateTime to, string searchtext, string useriid, string sortPath, bool desc)
        {
            if (string.IsNullOrEmpty(companyid))
                companyid = SystemParams.CompanyID;

            AssetRentalChangeHistoryInfo[] assetrentals = FleetServiceClientHelper.CreateClient<AssetQueryClient>(companyid, sessionid).GetAssetRentalChangeHistory(companyid, Convert.ToInt64(rentalid));
            List<RentalChangeHistoryInfo> rentalHistory = new List<RentalChangeHistoryInfo>();
            foreach (AssetRentalChangeHistoryInfo ari in assetrentals)
            {
                RentalChangeHistoryInfo mri = new RentalChangeHistoryInfo();
                Helper.CloneProperty(mri, ari);
                mri.RentalRate = (decimal)ari.RentalRate;
                rentalHistory.Add(mri);
            }

            if (machineid > 0)
                rentalHistory = rentalHistory.Where(m => m.MachineID == machineid).ToList();

            if (rentalid > 0)
                rentalHistory = rentalHistory.Where(m => m.RentalID == rentalid).ToList();

            rentalHistory = rentalHistory.Where(m => m.RentalDate >= from && m.RentalDate <= to).ToList();

            if (!string.IsNullOrEmpty(sortPath))
            {
                if (desc)
                {
                    rentalHistory = rentalHistory.OrderByDescending(m =>
                    {
                        return OrderHandler(m, sortPath);
                    }).ToList();
                }
                else
                {
                    rentalHistory = rentalHistory.OrderBy(m =>
                    {
                        return OrderHandler(m, sortPath);
                    }).ToList();
                }
            }

            ExportToExcel ete = new ExportToExcel();

            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_RENTALID", "Rental ID") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_USERNAME", "User Name") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_LASTUPDATEDATE", "Last Update Date") });
            //dt.Columns.Add(new DataColumn() { ColumnName = "Operate Type" });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_VINSN", "VIN/SN") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_ASSETNAME", "Asset Name") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_OUTSIDEINTERNAL", "Outside/Internal") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_RENTALVENDOR", "Rental Vendor") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_RENTALRATE", "Rental Rate") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_TERM", "Term") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_TERMUNIT", "Term Unit") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_RENTALDATEON", "Rental Date On") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_PROJECTRETURNDATE", "Project Return Date") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_RETURNDATE", "Return Date") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_PURCHASEORDERN", "Purchase Order #") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_INSUREDVALUE", "Insured Value") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MR_COMMENTS", "Comments") });

            foreach (var r in rentalHistory)
            {
                int index = 0;
                var dr = dt.NewRow();
                dr[index] = r.RentalID;
                dr[++index] = r.LastUpdateUserName;
                dr[++index] = r.LastUpdateDateStr;
                dr[++index] = r.VIN;
                dr[++index] = r.DisplayName;
                dr[++index] = r.Outside;
                dr[++index] = r.Vendor;
                dr[++index] = r.RentalRate;
                dr[++index] = r.Term;
                dr[++index] = r.TermUnit;
                dr[++index] = r.RentalDateStr;
                dr[++index] = r.ProjectReturnDateStr;
                dr[++index] = r.ReturnDateStr;
                dr[++index] = r.PONumber;
                dr[++index] = r.InsuredValue;
                dr[++index] = r.Comments;
                dt.Rows.Add(dr);
            }
            double[] widths = new double[] { 120d, 150d, 150d, 180d, 180d, 180d, 150d, 150d, 150d, 150d, 150d, 150d, 150d, 150d, 150d, 200d };
            byte[] data = ete.CreateExcel(dt, null, widths, null);

            return data;
        }

        public static byte[] ExportOdometerAdjustHistory(string lang, string sessionid, string companyid, long machineid, DateTime from, DateTime to, string sortPath, bool desc)
        {
            if (string.IsNullOrEmpty(companyid))
                companyid = SystemParams.CompanyID;
            AssetBasicInfo asset = FleetServiceClientHelper.CreateClient<AssetQueryClient>(companyid, sessionid).GetAssetBasicInfoByID(companyid, machineid);
            AssetOdometerAdjustInfo[] odoHistory = FleetServiceClientHelper.CreateClient<AssetDataAdjustClient>(companyid, sessionid).GetOdometerAdjustmentHistory(companyid, machineid, from, to);
            if (!string.IsNullOrEmpty(sortPath))
            {
                if (desc)
                {
                    odoHistory = odoHistory.OrderByDescending(m =>
                    {
                        return OrderHandler(m, sortPath);
                    }).ToArray();
                }
                else
                {
                    odoHistory = odoHistory.OrderBy(m =>
                    {
                        return OrderHandler(m, sortPath);
                    }).ToArray();
                }
            }

            ExportToExcel ete = new ExportToExcel();

            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MA_ASSETNAME", "Asset Name") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MA_VIN", "VIN") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MA_USERNAME", "User Name") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MA_ADJUSTMENTTIME", "Adjustment Time") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MA_ODOMETERENTERED", "Odometer Entered") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MA_ODOMETERUOM", "Odometer UOM") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MA_ODOMETERTIME", "Odometer Time") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MA_NOTES", "Notes") });

            foreach (var r in odoHistory)
            {
                int index = 0;
                var dr = dt.NewRow();
                dr[index] = asset.DisplayName;
                dr[++index] = asset.VIN;
                dr[++index] = r.UserName;
                dr[++index] = r.AdjustmentLocalTime.ToString("M/d/yyyy h:mm tt");
                dr[++index] = r.Odometer;
                dr[++index] = r.UOM;
                dr[++index] = r.OdometerLocalTime.ToString("M/d/yyyy h:mm tt");
                dr[++index] = r.Notes;
                dt.Rows.Add(dr);
            }
            double[] widths = new double[] { 200d, 200d, 200d, 150d, 150d, 150d, 150d, 300d };
            byte[] data = ete.CreateExcel(dt, null, widths, null);

            return data;
        }

        public static byte[] ExportEngineHoursAdjustHistory(string lang, string sessionid, string companyid, long machineid, DateTime from, DateTime to, string sortPath, bool desc)
        {
            if (string.IsNullOrEmpty(companyid))
                companyid = SystemParams.CompanyID;
            AssetBasicInfo asset = FleetServiceClientHelper.CreateClient<AssetQueryClient>(companyid, sessionid).GetAssetBasicInfoByID(companyid, machineid);
            AssetEngineHoursAdjustInfo[] ehHistory = FleetServiceClientHelper.CreateClient<AssetDataAdjustClient>(companyid, sessionid).GetEngineHoursAdjustmentHistory(companyid, machineid, from, to);
            if (!string.IsNullOrEmpty(sortPath))
            {
                if (desc)
                {
                    ehHistory = ehHistory.OrderByDescending(m =>
                    {
                        return OrderHandler(m, sortPath);
                    }).ToArray();
                }
                else
                {
                    ehHistory = ehHistory.OrderBy(m =>
                    {
                        return OrderHandler(m, sortPath);
                    }).ToArray();
                }
            }

            ExportToExcel ete = new ExportToExcel();

            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MA_ASSETNAME", "Asset Name") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MA_VIN", "VIN") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MA_USERNAME", "User Name") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MA_ADJUSTMENTTIME", "Adjustment Time") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MA_ENGINEHOURNTERED", "Engine Hours Entered") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MA_ENGINEHOURSTIME", "Engine Hours Time") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MA_NOTES", "Notes") });

            foreach (var r in ehHistory)
            {
                int index = 0;
                var dr = dt.NewRow();
                dr[index] = asset.DisplayName;
                dr[++index] = asset.VIN;
                dr[++index] = r.UserName;
                dr[++index] = r.AdjustmentLocalTime.ToString("M/d/yyyy h:mm tt");
                dr[++index] = r.EngineHours;
                dr[++index] = r.EngineHoursLocalTime.ToString("M/d/yyyy h:mm tt");
                dr[++index] = r.Notes;
                dt.Rows.Add(dr);
            }
            double[] widths = new double[] { 200d, 200d, 200d, 150d, 150d, 150d, 300d };
            byte[] data = ete.CreateExcel(dt, null, widths, null);

            return data;
        }

        private static readonly string[] INSPECT = new string[] { "Red-Inspect", "Yellow-Inspect", "Green-Inspect", "Info-Inspect" };

        public static byte[] ExportAlertsView(string clientdata, string sessionid, string useriid, string lang)
        {
            AlertQueryParams alertparam = JsonConvert.DeserializeObject<AlertQueryParams>(clientdata);
            DateTime beginDate = Helper.DBMinDateTime;
            DateTime endDate = DateTime.MaxValue;
            if (!DateTime.TryParse(alertparam.BeginDate, out beginDate))
                beginDate = Helper.DBMinDateTime;
            //else
            //    beginDate = beginDate.ToUniversalTime();
            if (!DateTime.TryParse(alertparam.EndDate, out endDate))
                endDate = DateTime.MaxValue;

            int assigned = -1;
            int completed = -1;
            if (alertparam.AlertStatus != null && alertparam.AlertStatus.Length > 0)
            {
                if (alertparam.AlertStatus.Contains("Unassigned") && !alertparam.AlertStatus.Contains("Assigned"))
                    assigned = 0;
                if (!alertparam.AlertStatus.Contains("Unassigned") && alertparam.AlertStatus.Contains("Assigned"))
                    assigned = 1;

                if (alertparam.AlertStatus.Contains("Completed") && !alertparam.AlertStatus.Contains("Uncompleted"))
                    completed = 1;
                if (!alertparam.AlertStatus.Contains("Completed") && alertparam.AlertStatus.Contains("Uncompleted"))
                    completed = 0;
            }

            AssetAlertGridViewItem[] assetalerts = null;
            if (alertparam.AssetID > 0)
                assetalerts = FleetServiceClientHelper.CreateClient<WorkOrderProvider>(sessionid).GetAssetAlertGridViewItemsByAsset(SystemParams.CompanyID, alertparam.AssetID, beginDate, endDate, alertparam.AlertTypes, alertparam.JobSites, assigned, completed, alertparam.SearchText, alertparam.IncludeunCompleted, alertparam.Category);
            else
                assetalerts = FleetServiceClientHelper.CreateClient<AlertProvider>(sessionid).GetAssetAlertGridViewItems(SystemParams.CompanyID, beginDate, endDate, alertparam.AlertTypes, alertparam.AssetGroups, alertparam.JobSites, assigned, completed, alertparam.SearchText, useriid, alertparam.IncludeunCompleted, alertparam.Category);

            List<AlertInfo> list = new List<AlertInfo>();
            if (assetalerts != null && assetalerts.Length > 0)
            {
                foreach (AssetAlertGridViewItem item in assetalerts)
                {
                    AlertInfo ai = ConvertAlertObj(item);
                    ai.AlertTime_UTC = item.LastAlertLocalTime;
                    list.Add(ai);
                }
            }

            ExportToExcel ete = new ExportToExcel();

            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_WORKORDERID", "Work Order ID") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_WORKORDERSTATUS", "Work Order Status") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_ASSETNAME", "Asset Name") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_MAKE", "Make") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_MODEL", "Model") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_VIN", "SN/VIN") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_CURRENTHOURS", "Current Hours") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_HOURS", "Hours") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_ALERTTYPE", "Alert Type") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_DESCRIPTION", "Description") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_ALERTCOUNT", "Alert Count") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_LATESTALERTDATETIME", "Latest Alert DateTime") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_OPENWORKORDERS", "Open Work Orders") });

            foreach (var r in list)
            {
                int index = 0;
                var dr = dt.NewRow();
                dr[index] = r.WorkOrderID > 0 ? r.WorkOrderID.ToString() : "";
                dr[++index] = r.WorkOrderStatus;
                dr[++index] = r.MachineName;
                dr[++index] = r.Make;
                dr[++index] = r.Model;
                dr[++index] = r.VIN;
                dr[++index] = r.CurrentHours;
                dr[++index] = r.EngineHours;
                dr[++index] = r.AlertType;
                dr[++index] = r.Description;
                dr[++index] = r.AlertCount;
                dr[++index] = r.AlertTime_UTC;
                dr[++index] = r.OpenWorkOrderCount;
                dt.Rows.Add(dr);
            }
            double[] widths = new double[] { 120d, 140d, 180d, 120d, 120d, 180d, 120d, 120d, 120d, 240d, 80d, 150d, 130d };
            byte[] data = ete.CreateExcel(dt, null, widths, null);

            return data;
        }

        public static byte[] ExportAssetView(string clientdata, string sessionid, string useriid, string lang)
        {
            AlertQueryParams alertparam = JsonConvert.DeserializeObject<AlertQueryParams>(clientdata);
            DateTime beginDate = Helper.DBMinDateTime;
            DateTime endDate = DateTime.MaxValue;
            if (!DateTime.TryParse(alertparam.BeginDate, out beginDate))
                beginDate = Helper.DBMinDateTime;
            //else
            //    beginDate = beginDate.ToUniversalTime();
            if (!DateTime.TryParse(alertparam.EndDate, out endDate))
                endDate = DateTime.MaxValue;

            int assigned = -1;
            int completed = -1;
            if (alertparam.AlertStatus != null && alertparam.AlertStatus.Length > 0)
            {
                if (alertparam.AlertStatus.Contains("Unassigned") && !alertparam.AlertStatus.Contains("Assigned"))
                    assigned = 0;
                if (!alertparam.AlertStatus.Contains("Unassigned") && alertparam.AlertStatus.Contains("Assigned"))
                    assigned = 1;

                if (alertparam.AlertStatus.Contains("Completed") && !alertparam.AlertStatus.Contains("Uncompleted"))
                    completed = 1;
                if (!alertparam.AlertStatus.Contains("Completed") && alertparam.AlertStatus.Contains("Uncompleted"))
                    completed = 0;
            }

            AssetAlertGridViewItem[] assetalerts = null;
            if (alertparam.AssetID > 0)
                assetalerts = FleetServiceClientHelper.CreateClient<WorkOrderProvider>(sessionid).GetAssetAlertGridViewItemsByAsset(SystemParams.CompanyID, alertparam.AssetID, beginDate, endDate, alertparam.AlertTypes, alertparam.JobSites, assigned, completed, alertparam.SearchText, alertparam.IncludeunCompleted, alertparam.Category);
            else
                assetalerts = FleetServiceClientHelper.CreateClient<AlertProvider>(sessionid).GetAssetAlertGridViewItems(SystemParams.CompanyID, beginDate, endDate, alertparam.AlertTypes, alertparam.AssetGroups, alertparam.JobSites, assigned, completed, alertparam.SearchText, useriid, alertparam.IncludeunCompleted, alertparam.Category);

            List<MachineInfoForAlert> list = new List<MachineInfoForAlert>();
            if (assetalerts != null && assetalerts.Length > 0)
            {
                foreach (AssetAlertGridViewItem item in assetalerts)
                {
                    AlertInfo ai = ConvertAlertObj(item);
                    MachineInfoForAlert mi = list.FirstOrDefault((i) => i.MachineID == ai.MachineID);
                    if (mi == null)
                    {
                        mi = new MachineInfoForAlert();
                        mi.MachineID = ai.MachineID;
                        mi.MachineName = ai.MachineName;
                        mi.VIN = ai.VIN;
                        mi.Make = ai.Make;
                        mi.Model = ai.Model;
                        mi.EngineHours = ai.CurrentHours;
                        mi.OpenWorkOrders = ai.OpenWorkOrderCount;

                        list.Add(mi);
                    }
                    mi.Alerts.Add(ai);

                    int count = ai.RepeatedAlerts.Count + 1;

                    if (ai.AlertType == "Preventative Maintenance"
                      || ai.AlertType == "PM_ALERT" || ai.AlertType == "TBM_ALERT" || ai.AlertType == "HM_ALERT"
                      || ai.AlertType == "RDM_ALERT" || ai.AlertType == "ADM_ALERT")
                        mi.PMAlertCount += count;
                    else if (INSPECT.Contains(ai.AlertType, StringComparer.OrdinalIgnoreCase))
                        mi.InspectAlertCount += count;
                    else
                        mi.DTCAlertCount += count;
                    if (ai.AlertLocalTime > mi.LatestAlertDateTime)
                        mi.LatestAlertDateTime = ai.AlertLocalTime;
                }
            }

            ExportToExcel ete = new ExportToExcel();

            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_ASSETNAME", "Asset Name") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_MAKE", "Make") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_MODEL", "Model") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_VIN", "VIN/SN") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_ENGINEHOURS", "Engine Hours") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_DTCALERTS", "DTC Alerts") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_PMALERTS", "PM Alerts") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_INSPECTALERTS", "Inspect Alerts") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_OPENWORKORDERS", "Open Work Orders") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_LATESTALERTDATETIME", "Latest Alert DateTime") });

            foreach (var r in list)
            {
                int index = 0;
                var dr = dt.NewRow();
                dr[index] = r.MachineName;
                dr[++index] = r.Make;
                dr[++index] = r.Model;
                dr[++index] = r.VIN;
                dr[++index] = r.EngineHours == 0 ? "" : r.EngineHours.ToString();
                dr[++index] = r.DTCAlertCount;
                dr[++index] = r.PMAlertCount;
                dr[++index] = r.InspectAlertCount;
                dr[++index] = r.OpenWorkOrders;
                dr[++index] = r.LatestAlertDateTimeStr;
                dt.Rows.Add(dr);
            }
            double[] widths = new double[] { 150d, 120d, 120d, 200d, 150d, 80d, 80d, 120d, 120d, 200d };
            byte[] data = ete.CreateExcel(dt, null, widths, null);

            return data;
        }

        public static byte[] ExportAcknowledgedAlerts(string clientdata, string sessionid, string useriid, string lang)
        {
            AlertQueryParams alertparam = JsonConvert.DeserializeObject<AlertQueryParams>(clientdata);
            DateTime beginDate = Helper.DBMinDateTime;
            DateTime endDate = DateTime.MaxValue;
            if (!DateTime.TryParse(alertparam.BeginDate, out beginDate))
                beginDate = Helper.DBMinDateTime;
            //else
            //    beginDate = beginDate.ToUniversalTime();
            if (!DateTime.TryParse(alertparam.EndDate, out endDate))
                endDate = DateTime.MaxValue;

            alertparam.AlertStatus = new string[0];

            AcknowledgedAlertItem[] ackalerts = FleetServiceClientHelper.CreateClient<AlertProvider>(sessionid).GetAcknowledgedAlerts(SystemParams.CompanyID, beginDate, endDate, alertparam.AlertTypes, alertparam.AssetGroups, alertparam.SearchText);

            List<AlertInfo> list = new List<AlertInfo>();
            foreach (AcknowledgedAlertItem item in ackalerts)
            {
                AlertInfo ai = ConvertAlertObj2(item);
                list.Add(ai);
            }

            if (alertparam.AssetID > 0)
                list = list.Where(m => m.MachineID == alertparam.AssetID).ToList();


            ExportToExcel ete = new ExportToExcel();

            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_ACKNOWLEDGEDBY", "Acknowledged By") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_ACKNOWLEDGEDDATETIME", "Acknowledged DateTime") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_ASSETNAME", "Asset Name") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_MAKE", "Make") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_MODEL", "Model") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_VIN", "SN/VIN") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_HOURS", "Hours") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_ALERTTYPE", "Alert Type") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_DESCRIPTION", "Description") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_ALERTCOUNT", "Alert Count") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_LATESTALERTDATETIME", "Latest Alert DateTime") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_OPENWORKORDERS", "Open Work Orders") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_ACKNOWLEDGEDCOMMENT", "Acknowledged Comment") });

            foreach (var r in list)
            {
                int index = 0;
                var dr = dt.NewRow();
                dr[index] = r.AcknowledgedByName;
                dr[++index] = r.AcknowledgedTime_LocalStr;
                dr[++index] = r.MachineName;
                dr[++index] = r.Make;
                dr[++index] = r.Model;
                dr[++index] = r.VIN;
                dr[++index] = r.EngineHours;
                dr[++index] = r.AlertType;
                dr[++index] = r.Description;
                dr[++index] = r.AlertCount;
                dr[++index] = r.AlertLocalTimeStr;
                dr[++index] = r.OpenWorkOrderCount;
                dr[++index] = r.AcknowledgedComment;
                dt.Rows.Add(dr);
            }
            double[] widths = new double[] { 150d, 150d, 150d, 180d, 120d, 120d, 180d, 120d, 120d, 180d, 240d, 200d, 240d };
            byte[] data = ete.CreateExcel(dt, null, widths, null);

            return data;
        }

        public static byte[] ExportAutoAcknowledChangeHistory(string sessionid, string useriid, string lang)
        {
            AutoAcknowledgeItem[] items = FleetServiceClientHelper.CreateClient<WorkOrderProvider>(sessionid).GetAutoAcknowledgeAlertTypesHistory(SystemParams.CompanyID, useriid);

            List<AutoAcknowledgeInfo> list = new List<AutoAcknowledgeInfo>();
            if (items != null || items.Length > 0)
            {

                foreach (AutoAcknowledgeItem item in items)
                {
                    AutoAcknowledgeInfo ai = new AutoAcknowledgeInfo();
                    Helper.CloneProperty(ai, item);
                    ai.LocalUpdatedOn = ai.UpdatedOnLocal;
                    list.Add(ai);
                }
                list = list.OrderBy(m => m.LocalUpdatedOn).ToList();
            }
            ExportToExcel ete = new ExportToExcel();

            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_ALERTTYPE", "Alert Type") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_AUTOACKNOWLEDGE1", "Auto Acknowledge") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_USERNAME", "User Name") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AM_UPDATEDATE", "Update Date") });

            foreach (var r in list)
            {
                int index = 0;
                var dr = dt.NewRow();
                dr[index] = r.AlertType;
                dr[++index] = r.AutoAcknowledge > 0 ? "Yes" : "No";
                dr[++index] = r.UpdatedByName;
                dr[++index] = r.LocalUpdatedOnStr;
                dt.Rows.Add(dr);
            }
            double[] widths = new double[] { 300d, 150d, 250d, 180d };
            byte[] data = ete.CreateExcel(dt, null, widths, null);

            return data;
        }

        public static byte[] ExportAlertMappings(string lang, string sessionid, string searchtxt)
        {
            var client = FleetServiceClientHelper.CreateClient<AlertProvider>(sessionid);
            AlertMappingInfo[] mappings = client.GetAlertMappings(SystemParams.CompanyID, searchtxt, true);
            List<AlertMappingClient> ls = new List<AlertMappingClient>();
            if (mappings != null && mappings.Length > 0)
            {
                var ap = FleetServiceClientHelper.CreateClient<AssetClassProvider>(sessionid);
                AssetMake[] makes = ap.GetAssetMakes("");
                AssetModel[] models = ap.GetAssetModels(-1, "");
                foreach (AlertMappingInfo ami in mappings)
                {
                    if (ami.Items.Count > 0)
                    {
                        foreach (AlertMappingItem amitem in ami.Items)
                        {
                            AlertMappingClient amc = new AlertMappingClient();
                            Helper.CloneProperty(amc, amitem);
                            amc.MappingId = ami.Id;
                            amc.Source = ami.Source;
                            amc.SPN = ami.SPN;
                            amc.FMI = ami.FMI;
                            amc.Description = ami.Description;
                            amc.EnhancedDescription = ami.EnhancedDescription;

                            if (amc.Make == -1)
                                amc.MakeName = "(All)";
                            else
                            {
                                AssetMake make = makes.FirstOrDefault(m => m.ID == amc.Make);
                                if (make != null)
                                    amc.MakeName = make.Name;
                            }
                            if (amc.Models != null && amc.Models.Length > 0)
                            {
                                List<string> lsmodelname = new List<string>();
                                foreach (int modeid in amc.Models)
                                {
                                    if (modeid == -1)
                                        lsmodelname.Add("(All)");
                                    else
                                    {
                                        AssetModel model = models.FirstOrDefault(m => m.ID == modeid);
                                        if (model != null)
                                            lsmodelname.Add(model.Name);
                                    }
                                }
                                amc.ModelNames = string.Join(",", lsmodelname);
                            }

                            ls.Add(amc);
                        }
                    }
                    else
                    {
                        AlertMappingClient amc = new AlertMappingClient();
                        amc.MappingId = ami.Id;
                        amc.Source = ami.Source;
                        amc.SPN = ami.SPN;
                        amc.FMI = ami.FMI;
                        amc.Description = ami.Description;
                        amc.EnhancedDescription = ami.EnhancedDescription;
                        ls.Add(amc);
                    }
                }
            }


            ExportToExcel ete = new ExportToExcel();

            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AMP_SOURCE", "Source") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AMP_SPN", "SPN") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AMP_FMI", "FMI") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AMP_DESCRIPTION", "Description") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AMP_ENHANCEDDESCRIPTION", "Enhanced Description") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AMP_MAKE", "Make") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AMP_MODELS", "Models") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AMP_ALERTTYPE", "Alert Type") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_AMP_CATEGORY", "Category") });

            foreach (var r in ls)
            {
                int index = 0;
                var dr = dt.NewRow();
                dr[index] = r.Source;
                dr[++index] = r.SPN;
                dr[++index] = r.FMI;
                dr[++index] = r.Description;
                dr[++index] = r.EnhancedDescription;
                dr[++index] = r.MakeName;
                dr[++index] = r.ModelNames;
                dr[++index] = r.AlertType;
                dr[++index] = r.Category;
                dt.Rows.Add(dr);
            }
            double[] widths = new double[] { 200d, 200d, 200d, 200d, 200d, 180d, 200d, 200d, 200d, 200d };
            byte[] data = ete.CreateExcel(dt, null, widths, null);

            return data;
        }

        public static byte[] ExportUsers(string lang, string searchtext, string layout)
        {
            UserInfo[] users = UserManagement.GetUsers(null, searchtext).OrderBy(u => u.ID).ToArray();
            var colinfos = JsonConvert.DeserializeObject<LayoutColumn[]>(layout);
            colinfos = colinfos.Where(c => c.Visible && !new string[] { "Edit", "Copy", "AssetAssignment", "AssetGroupAssignment", "AssetTypeAssignment", "JobsiteAssignment", "Delete", "ResetPassword" }.Contains(c.ColumnKey)).ToArray();

            ExportToExcel ete = new ExportToExcel();

            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn() { ColumnName = "ID", Caption = SystemParams.GetTextByKey(lang, "P_UM_USERID", "User ID") });
            dt.Columns.Add(new DataColumn() { ColumnName = "DisplayName", Caption = SystemParams.GetTextByKey(lang, "P_UM_USERNAME", "User Name") });
            dt.Columns.Add(new DataColumn() { ColumnName = "UserType", Caption = SystemParams.GetTextByKey(lang, "P_UM_USERTYPE", "User Type") });
            dt.Columns.Add(new DataColumn() { ColumnName = "Active", Caption = SystemParams.GetTextByKey(lang, "P_UM_ACTIVE", "Active") });
            dt.Columns.Add(new DataColumn() { ColumnName = "IsUser", Caption = SystemParams.GetTextByKey(lang, "P_UM_ISUSER", "Is User") });
            dt.Columns.Add(new DataColumn() { ColumnName = "AssignedWorkOrders", Caption = SystemParams.GetTextByKey(lang, "P_UM_ASSIGNEDWORKORDERS", "Assigned Work Orders") });
            dt.Columns.Add(new DataColumn() { ColumnName = "TextAddress", Caption = SystemParams.GetTextByKey(lang, "P_UM_TEXTADDRESS", "Text Address") });
            dt.Columns.Add(new DataColumn() { ColumnName = "Mobile", Caption = SystemParams.GetTextByKey(lang, "P_UM_MOBILE", "Mobile") });
            dt.Columns.Add(new DataColumn() { ColumnName = "BusinessPhone", Caption = SystemParams.GetTextByKey(lang, "P_UM_BUSINESSPHONE", "Business Phone") });
            dt.Columns.Add(new DataColumn() { ColumnName = "ContactTypeName", Caption = SystemParams.GetTextByKey(lang, "P_UM_CONTACTTYPE", "Contact Type") });
            dt.Columns.Add(new DataColumn() { ColumnName = "FOB", Caption = SystemParams.GetTextByKey(lang, "P_UM_EMPLOYEEIDORFOB", "Employee ID or FOB") });
            dt.Columns.Add(new DataColumn() { ColumnName = "ManagerName", Caption = SystemParams.GetTextByKey(lang, "P_UM_MANAGER", "Manager") });
            dt.Columns.Add(new DataColumn() { ColumnName = "EmailOptOut", Caption = SystemParams.GetTextByKey(lang, "P_UM_OPTOUTOFFICOMMUNICATIONS", "Opt Out of FI Communications?") });
            dt.Columns.Add(new DataColumn() { ColumnName = "Notes", Caption = SystemParams.GetTextByKey(lang, "P_UM_NOTES", "Notes") });
            dt.Columns.Add(new DataColumn() { ColumnName = "GroupNames", Caption = SystemParams.GetTextByKey(lang, "P_UM_GROUPNAME", "Group Name") });

            foreach (var r in users)
            {
                string usertype = "";
                if (r.UserType == UserTypes.Admin)
                    usertype = "Admin";
                else if (r.UserType == UserTypes.Common)
                    usertype = "Common";
                else
                    usertype = "Read Only";

                int index = 0;
                var dr = dt.NewRow();
                dr[index] = r.ID;
                dr[++index] = r.DisplayName;
                dr[++index] = usertype;
                dr[++index] = r.Active ? "Yes" : "No";
                dr[++index] = r.IsUser ? "Yes" : "No";
                dr[++index] = r.AssignedWorkOrders ? "Yes" : "No";
                dr[++index] = r.TextAddressDisplayText;
                dr[++index] = r.MobilePhoneDisplayText;
                dr[++index] = r.BusinessPhoneDisplayText;
                dr[++index] = r.ContactTypeName;
                dr[++index] = r.FOB;
                dr[++index] = r.ManagerName;
                dr[++index] = r.EmailOptOut ? "Yes" : "No";
                dr[++index] = r.Notes;
                dr[++index] = r.GroupNamesStr;
                dt.Rows.Add(dr);
            }
            double[] widths = null;
            if (colinfos.Length > 0)
            {
                for (int i = dt.Columns.Count - 1; i >= 0; i--)
                {//删除不显示的列
                    bool exists = false;
                    for (int j = 0; j < colinfos.Length; j++)
                    {
                        if (colinfos[j].ColumnKey == dt.Columns[i].ColumnName)
                        {
                            exists = true;
                            break;
                        }
                    }
                    if (!exists)
                        dt.Columns.RemoveAt(i);
                }

                for (int j = 0; j < colinfos.Length; j++)
                {
                    for (int i = dt.Columns.Count - 1; i >= 0; i--)
                    {
                        if (colinfos[j].ColumnKey == dt.Columns[i].ColumnName)
                        {
                            if (!string.IsNullOrWhiteSpace(colinfos[j].Caption))
                                dt.Columns[i].Caption = colinfos[j].Caption;
                            if (colinfos[j].Sort != 0)
                            {
                                if (colinfos[j].Sort == 1)
                                    dt.DefaultView.Sort = dt.Columns[i].ColumnName;
                                else if (colinfos[j].Sort == -1)
                                    dt.DefaultView.Sort = dt.Columns[i].ColumnName + " desc";
                            }
                            dt.Columns[i].SetOrdinal(j);
                            break;
                        }
                    }
                }
                dt = dt.DefaultView.ToTable();
                widths = colinfos.Select(c => (double)c.Width).ToArray();
            }
            //double[] widths = new double[] { 130d, 130d, 80d, 80d, 80d, 130d, 130d, 130d, 120d, 130d, 130d, 130d, 150d, 130d };
            byte[] data = ete.CreateExcel(dt, null, widths, null);

            return data;
        }

        public static byte[] ExportJobSites(string lang, string sessionid, string useriid, string searchtext, string typesdata, bool active, string layout)
        {
            string[] types = JsonConvert.DeserializeObject<string[]>(typesdata);
            var jss = FleetServiceClientHelper.CreateClient<JobSiteProvider>(sessionid).GetJobSiteItems(SystemParams.CompanyID, searchtext, types, active);
            var colinfos = JsonConvert.DeserializeObject<LayoutColumn[]>(layout);
            colinfos = colinfos.Where(c => c.Visible && !new string[] { "Edit", "Delete", "ManageAssets" }.Contains(c.ColumnKey)).ToArray();
            //var sortcol = colinfos.FirstOrDefault((c) => c.Sort == 1);

            List<JobSiteViewItem> list = new List<JobSiteViewItem>();
            foreach (var js in jss)
            {
                JobSiteViewItem item = new JobSiteViewItem();
                Helper.CloneProperty(item, js);
                item.BaseOnMachineID = js.BaseonMachineID;
                item.Types = new string[] { js.JobSiteTypes };
                item.ColorString = js.Color;
                System.Drawing.Color color = System.Drawing.Color.Orange;
                try
                {
                    color = System.Drawing.ColorTranslator.FromHtml(item.ColorString);
                }
                catch
                {
                }
                item.Color = new IIColor() { Alpha = color.A, Red = color.R, Green = color.G, Blue = color.B };

                item.StartDate = js.StartDate == null ? DateTime.MinValue : js.StartDate.Value;
                item.ProjectedEndDate = js.ProjectedEndDate == null ? DateTime.MinValue : js.ProjectedEndDate.Value;
                item.EndDate = js.EndDate == null ? DateTime.MinValue : js.EndDate.Value;
                item.Radius_UOM = js.RadiusUOM;
                if (js.Polygon != null && js.Polygon.Length > 0)
                {
                    List<PostionItem> temps = new List<PostionItem>();
                    foreach (var p in js.Polygon)
                    {
                        temps.Add(new PostionItem(p.Latitude, p.Longtitude));
                    }
                    item.Polygon = temps.ToArray();
                }

                list.Add(item);
            }

            ExportToExcel ete = new ExportToExcel();

            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_JS_NAME", "Name"), ColumnName = "Name" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_JS_REGION", "Region"), ColumnName = "Region" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_JS_NUMBER", "Number"), ColumnName = "Number" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_JS_CODE", "Code"), ColumnName = "Code" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_JS_TYPES", "Types"), ColumnName = "Types" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_JS_LATITUDE", "Latitude"), ColumnName = "Latitude" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_JS_LONGITUDE", "Longitude"), ColumnName = "Longitude" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_JS_COLOR", "Color"), ColumnName = "ColorString" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_JS_RADIUS", "Radius"), ColumnName = "RadiusStr" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_JS_BINDINGTOASSET", "Binding to Asset"), ColumnName = "BaseonAsset" });
            //dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_JS_RADIUSUOM", "Radius UOM") });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_JS_FOREMAN", "Foreman"), ColumnName = "Foreman" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_JS_MANAGER", "Manager"), ColumnName = "Manager" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_JS_PHONE", "Phone"), ColumnName = "Phone" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_JS_EMAIL", "Email"), ColumnName = "Email" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_JS_GROUP", "Group"), ColumnName = "Group" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_JS_DELIVERYADDRESS1", "Delivery Address 1"), ColumnName = "Address1" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_JS_DELIVERYADDRESS2", "Delivery Address 2"), ColumnName = "Address2" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_JS_CITY", "City"), ColumnName = "City" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_JS_STATE", "State"), ColumnName = "State" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_JS_ZIP", "Zip"), ColumnName = "Zip" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_JS_COUNTY", "County"), ColumnName = "County" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_JS_STATDATE", "Start Date"), ColumnName = "StartDate" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_JS_PROJECTEDENDDATE", "Projected End Date"), ColumnName = "ProjectedEndDate" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_JS_ENDDATE", "End Date"), ColumnName = "EndDate" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_JS_NOTES", "Notes"), ColumnName = "Notes" });

            foreach (var r in list)
            {
                int index = 0;
                var dr = dt.NewRow();
                dr[index] = r.Name;
                dr[++index] = r.Region;
                dr[++index] = r.Number;
                dr[++index] = r.Code;
                dr[++index] = (r.Types == null || r.Types.Length == 0) ? "" : r.Types[0];
                dr[++index] = r.Latitude;
                dr[++index] = r.Longitude;
                dr[++index] = r.ColorString;
                dr[++index] = r.RadiusStr;
                dr[++index] = r.BaseonMachineName;
                dr[++index] = r.Foreman;
                dr[++index] = r.Manager;
                dr[++index] = r.Phone;
                dr[++index] = r.Email;
                dr[++index] = r.Group;
                dr[++index] = r.Address1;
                dr[++index] = r.Address2;
                dr[++index] = r.City;
                dr[++index] = r.State;
                dr[++index] = r.Zip;
                dr[++index] = r.County;
                dr[++index] = r.StartDateStr;
                dr[++index] = r.ProjectedEndDateStr;
                dr[++index] = r.EndDateStr;
                dr[++index] = r.Notes;
                dt.Rows.Add(dr);
            }
            double[] widths = null;
            if (colinfos.Length > 0)
            {
                for (int i = dt.Columns.Count - 1; i >= 0; i--)
                {//删除不显示的列
                    bool exists = false;
                    for (int j = 0; j < colinfos.Length; j++)
                    {
                        if (colinfos[j].ColumnKey == dt.Columns[i].ColumnName)
                        {
                            exists = true;
                            break;
                        }
                    }
                    if (!exists)
                        dt.Columns.RemoveAt(i);
                }

                for (int j = 0; j < colinfos.Length; j++)
                {
                    for (int i = dt.Columns.Count - 1; i >= 0; i--)
                    {
                        if (colinfos[j].ColumnKey == dt.Columns[i].ColumnName)
                        {
                            if (!string.IsNullOrWhiteSpace(colinfos[j].Caption))
                                dt.Columns[i].Caption = colinfos[j].Caption;
                            if (colinfos[j].Sort != 0)
                            {
                                if (colinfos[j].Sort == 1)
                                    dt.DefaultView.Sort = dt.Columns[i].ColumnName;
                                else if (colinfos[j].Sort == -1)
                                    dt.DefaultView.Sort = dt.Columns[i].ColumnName + " desc";
                            }
                            dt.Columns[i].SetOrdinal(j);
                            break;
                        }
                    }
                }
                dt = dt.DefaultView.ToTable();
                widths = colinfos.Select(c => (double)c.Width).ToArray();
            }
            //if (widths == null)
            //    widths = new double[] { 150d, 150d, 150d, 150d, 120d, 120d, 120d, 120d, 120d, 120d, 120d, 120d, 120d };
            byte[] data = ete.CreateExcel(dt, null, widths, null);

            return data;
        }
        public static byte[] ExportRequirements(string lang, string sessionid, string clientdata)
        {
            JobSiteRequirementQueryItem p = JsonConvert.DeserializeObject<JobSiteRequirementQueryItem>(clientdata);
            DateTime latestStartDate = Helper.DBMinDateTime;
            if (!DateTime.TryParse(p.LatestStartDate, out latestStartDate))
                latestStartDate = Helper.DBMinDateTime;

            List<JobSiteRequirmentItem> list = new List<JobSiteRequirmentItem>();
            JobSiteRequirmentInfo[] reqs = FleetServiceClientHelper.CreateClient<JobSiteDispatchProvider>(SystemParams.CompanyID, sessionid).GetRequirmentItems(SystemParams.CompanyID, latestStartDate, p.JobSites, p.Regions, p.UnScheduledOnly);
            if (reqs != null && reqs.Length > 0)
            {
                foreach (JobSiteRequirmentInfo re in reqs)
                {
                    JobSiteRequirmentItem item = new JobSiteRequirmentItem();
                    Helper.CloneProperty(item, re);
                    list.Add(item);
                }
            }
            list = list.OrderBy(r => r.BeginDate).ToList();

            ExportToExcel ete = new ExportToExcel();

            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_JS_BEGINDATE", "Begin Date") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_JS_ENDDATE", "End Date") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_JS_ASSETTYPE", "Asset Type") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_JS_QUANTITY", "Quantity") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_JS_SCHEDULED", "Scheduled") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_JOBSITE", "Jobsite") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_JS_NUMBEROFDAYS", "Number of Days") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_JS_NOTES", "Notes") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_JS_POINTOFCONTACT", "Point Of Contact") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_JS_CREATOR", "Creator") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_JS_FULFILLEDBY", "Fulfilled By") });

            foreach (var r in list)
            {
                int index = 0;
                var dr = dt.NewRow();
                dr[index] = r.BeginDateStr;
                dr[++index] = r.EndDateStr;
                dr[++index] = r.AssetTypeName;
                dr[++index] = r.Quantity;
                dr[++index] = r.ScheduledQuantity;
                dr[++index] = r.JobSiteName;
                dr[++index] = r.NumberOfDays;
                dr[++index] = r.Notes;
                dr[++index] = r.PointOfContact;
                dr[++index] = r.AddedByName;
                dr[++index] = r.FulfilledByName;
                dt.Rows.Add(dr);
            }
            double[] widths = new double[] { 150d, 150d, 150d, 120d, 120d, 120d, 150d, 180d, 180d, 150d, 150d };
            byte[] data = ete.CreateExcel(dt, null, widths, null);

            return data;
        }

        public static byte[] ExportCustomerRecords(string lang, string sessionid, string searchtext)
        {
            BusinessPartnerInfo[] items = FleetServiceClientHelper.CreateClient<BusinessPartnerProvider>(sessionid).GetPartners(SystemParams.CompanyID, searchtext);

            ExportToExcel ete = new ExportToExcel();

            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_CR_CODE", "Code") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_CR_COMPANYNAME", "Company Name") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_CR_SALESPERSONCODE", "Salesperson Code") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_CR_SALESPERSONNAME", "Salesperson Name") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_CR_ADDRESS", "Address") });
            //dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_CR_CONTACTNAME", "Contact Name") });
            //dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_CR_CONTACTEMAIL", "Contact Email") });
            //dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_CR_CONTACTMOBILE", "Contact Mobile") });
            //dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_CR_CONTACTPREFERENCES", "Contact Preferences") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_CR_NOTES", "Notes") });

            foreach (var r in items)
            {
                int index = 0;
                var dr = dt.NewRow();
                dr[index] = r.Code;
                dr[++index] = r.Name;
                dr[++index] = r.SalespersonCode;
                dr[++index] = r.SalespersonName;
                dr[++index] = r.Address;
                dr[++index] = r.Notes;
                dt.Rows.Add(dr);
            }
            double[] widths = new double[] { 150d, 150d, 150d, 150d, 150d, 180d };
            byte[] data = ete.CreateExcel(dt, null, widths, null);

            return data;
        }

        public static byte[] ExportDispatchRequests(string lang, string sessionid, string filter)
        {
            JobSiteRequirementQueryItem p = JsonConvert.DeserializeObject<JobSiteRequirementQueryItem>(filter);
            DateTime latestStartDate = Helper.DBMinDateTime;
            if (!DateTime.TryParse(p.LatestStartDate, out latestStartDate))
                latestStartDate = Helper.DBMinDateTime;

            JobSiteAssetDispatchInfo[] list = FleetServiceClientHelper.CreateClient<JobSiteDispatchProvider>(SystemParams.CompanyID, sessionid).GetAssetDispatchItems(SystemParams.CompanyID, latestStartDate, p.JobSites, p.Regions, p.UnScheduledOnly);

            ExportToExcel ete = new ExportToExcel();

            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_JS_MOVEDATE", "Move Date") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_JS_ASSETNAME", "Asset Name") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_JS_ASSETTYPE", "Asset Type") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_JS_MODEL", "Model") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_JS_FROMJOBSITE", "From Jobsite") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_JS_TOJOBSITE", "To Jobsite") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_JS_MARKCOMPLETE", "Mark Complete") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_JS_COMPLETEDATE", "Completed Date") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_JS_NOTES", "Notes") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_JS_ASSIGNEDTO", "Assigned To") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_JS_POINTOFCONTACT", "Point Of Contact") });

            foreach (var r in list)
            {
                int index = 0;
                var dr = dt.NewRow();
                dr[index] = (r.BeginDate == null ? "" : r.BeginDate.Value.ToString("M/d/yyyy"));
                dr[++index] = r.AssetName;
                dr[++index] = r.AssetTypeName;
                dr[++index] = r.AssetModelName;
                dr[++index] = r.CurrentJobSiteName;
                dr[++index] = r.RequiredJobSiteName;
                dr[++index] = r.Completed;
                dr[++index] = (r.Completed ? (r.CompletedTime == null ? "" : r.CompletedTime.Value.ToString("M/d/yyyy")) : "");
                dr[++index] = r.Notes;
                dr[++index] = r.AssignedToAssetName;
                dr[++index] = r.PointOfContact;
                dt.Rows.Add(dr);
            }
            double[] widths = new double[] { 100d, 200d, 180d, 180d, 120d, 120d, 100d, 120d, 200d, 200d, 200d };
            byte[] data = ete.CreateExcel(dt, null, widths, null);

            return data;
        }

        public static byte[] ExportFuelRecordManagement(string lang, string sessionid, string searchtext, DateTime beginDate, DateTime endDate, string type, long assetid)
        {
            FuelRecord[] fuels = FleetServiceClientHelper.CreateClient<FuelManagementClient>(sessionid).GetFuelRecords(SystemParams.CompanyID, Convert.ToInt64(type), beginDate, endDate, searchtext);
            if (assetid > 0)
                fuels = fuels.Where(m => m.AssetID == assetid).ToArray();
            Foresight.Fleet.Services.Asset.AssetBasicInfo[] assets = FleetServiceClientHelper.CreateClient<AssetQueryClient>(sessionid).GetAssetBasicInfo(SystemParams.CompanyID);

            List<FuelRecordInfo> list = new List<FuelRecordInfo>();
            foreach (FuelRecord fuel in fuels)
            {
                FuelRecordInfo fi = new FuelRecordInfo();
                Helper.CloneProperty(fi, fuel);
                if (fi.FuelingAsset > 0)
                {
                    Foresight.Fleet.Services.Asset.AssetBasicInfo asset = assets.FirstOrDefault(m => m.ID == fi.FuelingAsset);
                    fi.FuelingAssetName = asset == null ? fi.FuelingAsset.ToString() : asset.DisplayName;
                }
                list.Add(fi);
            }

            ExportToExcel ete = new ExportToExcel();

            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_FR_ASSETNAME", "Asset Name") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_FR_MAKE", "Make") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_FR_MODEL", "Model") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_FR_SNVIN", "SN/VIN") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_FR_TRANSACTIONDATE", "Transaction Date") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_FR_DISTRIBUTEDBY", "Distributed By") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_FR_RETAILERNAME", "Retailer Name") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_FR_ASSET", "Asset") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_FR_QUANTITY", "Quantity") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_FR_UOM", "UOM") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_FR_UOMCOST", "Unit Cost") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_FR_TOTALCOST", "Total Cost") });

            foreach (var r in list)
            {
                int index = 0;
                var dr = dt.NewRow();
                dr[index] = r.AssetName;
                dr[++index] = r.AssetMake;
                dr[++index] = r.AssetModel;
                dr[++index] = r.VIN;
                dr[++index] = r.TransactionLocalDateStr;
                dr[++index] = r.DistributedBy == 0 ? "Fueling Station" : "Fueling Asset";
                dr[++index] = r.RetailerName;
                dr[++index] = r.FuelingAssetName;
                dr[++index] = r.Quantity.ToString("#,##0.##");
                dr[++index] = r.Uom;
                dr[++index] = r.UnitCost.ToString("#,##0.##");
                dr[++index] = r.TotalCost.ToString("#,##0.##");
                dt.Rows.Add(dr);
            }
            double[] widths = new double[] { 180d, 120d, 120d, 180d, 120d, 120d, 180d, 180d, 80d, 80d, 80d, 80d };
            byte[] data = ete.CreateExcel(dt, null, widths, null);

            return data;
        }

        #region ExportWorkOrders
        public static byte[] ExportWorkOrders(string lang, Foresight.Fleet.Services.User.UserInfo user, string sessionid, string clientdata, string layout)
        {
            clientdata = System.Web.HttpUtility.HtmlDecode(clientdata);
            WorkOrderQueryParams p = JsonConvert.DeserializeObject<WorkOrderQueryParams>(clientdata);

            WorkOrderListItem[] workorders = null;
            if (p.AssetID > 0)
                workorders = FleetServiceClientHelper.CreateClient<WorkOrderProvider>(sessionid).GetWorkOrderItemsByAsset(SystemParams.CompanyID, p.AssetID);
            else
                workorders = FleetServiceClientHelper.CreateClient<WorkOrderProvider>(sessionid).GetWorkOrderItems(SystemParams.CompanyID, p.Contacts, p.Statuses, p.OrderTypes, p.AssetGroups, p.SearchText, p.Completed, p.Locations, p.Departments, p.Advisors);

            var colinfos = JsonConvert.DeserializeObject<LayoutColumn[]>(layout);
            colinfos = colinfos.Where(c => c.Visible && !new string[] { "Edit", "Print", "Delete", "AssetAlert", "Surveys" }.Contains(c.ColumnKey)).ToArray();
            //var sortcol = colinfos.FirstOrDefault((c) => c.Sort == 1);

            List<WorkOrderListItemClient> list = new List<WorkOrderListItemClient>();

            WorkOrderListItemClient[] maintenanceworkorders = null;//
            if (p.ShowMaintenance)
                maintenanceworkorders = MaintenanceManagement.GetMaintenanceWorkOrders(sessionid, SystemParams.CompanyID, p.Contacts, p.AssetGroups, p.SearchText, user.UID);

            if (maintenanceworkorders != null)
            {
                //普通用户机器权限过滤
                if (user.UserType < Foresight.Fleet.Services.User.UserTypes.Admin)
                {
                    long[] availableAssetsids = FleetServiceClientHelper.CreateClient<AssetQueryClient>(sessionid).GetAvailableAssetsForUsers(SystemParams.CompanyID, user.UID);
                    foreach (WorkOrderListItemClient wi in maintenanceworkorders)
                    {
                        if (availableAssetsids != null && !availableAssetsids.Contains(wi.AssetId))
                            continue;
                        list.Add(wi);
                    }
                }
                else
                    list.AddRange(maintenanceworkorders);
            }
            foreach (WorkOrderListItem wo in workorders)
            {
                WorkOrderListItemClient wi = new WorkOrderListItemClient();
                Helper.CloneProperty(wi, wo);
                if (wi.CreateDate != null)
                    wi.CreateDate = wi.CreateDate.Value.Date;
                if (wi.LastCommunicationDate != null)
                    wi.LastCommunicationDate = wi.LastCommunicationDate.Value.Date;
                if (wi.LastInternalCommunicationDate != null)
                    wi.LastInternalCommunicationDate = wi.LastInternalCommunicationDate.Value.Date;

                list.Add(wi);
            }

            var ci = colinfos.FirstOrDefault(c => c.Sort != 0);
            if (ci != null && ci.ColumnKey == "Id" && ci.Sort == -1)//处理WorkOrder 特殊排序
            {
                list = list.OrderByDescending((m) =>
                {
                    int v = 0;
                    if (int.TryParse(m.WorkOrderNumber, out v))
                        return m.WorkOrderNumber.PadLeft(50, '0');
                    else
                        return m.WorkOrderNumber;
                }).ToList();
            }
            else
            {
                list = list.OrderBy((m) =>
                {
                    int v = 0;
                    if (int.TryParse(m.WorkOrderNumber, out v))
                        return m.WorkOrderNumber.PadLeft(50, '0');
                    else
                        return m.WorkOrderNumber;
                }).ToList();
            }

            ExportToExcel ete = new ExportToExcel();

            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_WORKORDERNUMBER", "Work Order Number"), ColumnName = "Id" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_WORKORDERTYPE", "Work Order Type"), ColumnName = "WorkOrderType" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_ASSIGNEDTO", "Assigned To"), ColumnName = "AssignedToName" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_STATUS", "Status"), ColumnName = "StatusName", DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_DESCRIPTION", "Description"), ColumnName = "Description" });

            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_ASSET", "Asset"), ColumnName = "AssetName" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_VIN", "VIN"), ColumnName = "VIN" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_MAKE", "Make"), ColumnName = "Make" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_MODEL", "Model"), ColumnName = "Model" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_CUSTOMERCODE", "Customer Code"), ColumnName = "CustomerCode" });

            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_CR_COMPANYNAME", "Company Name"), ColumnName = "Customer" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_LASTCOMMUNICATIONTEXT", "Last Communication Text"), ColumnName = "LastCommunication" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_LASTCOMMUNICATIONBY", "Last Communication By"), ColumnName = "LastCommunicationBy" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_LASTCOMMUNICATIONDATE", "Last Communication Date"), ColumnName = "LastCommunicationDate" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_DEPARTMENT", "Department"), ColumnName = "Department" });

            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_LOCATION", "Location"), ColumnName = "Location" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_ADVISOR", "Advisor"), ColumnName = "Advisor" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_SALESPERSON", "Salesperson"), ColumnName = "SalespersonName" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_CURRJOBSITE", "Current Jobsite"), ColumnName = "CurrentJobsites" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_CREATEDDATE", "Created Date"), ColumnName = "CreateDate" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_CREATIONDATE", "Creation Date"), ColumnName = "CreationDate" });

            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_DUEDATE", "Due Date"), ColumnName = "DueDate", DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_NEXTFOLLOWUPDATE", "Next Follow Up Date"), ColumnName = "NextFollowUpDate", DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_PARTSEXPECTEDDATE", "Parts Expected Date"), ColumnName = "PartsExpectedDate", DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_LASTLABORDATE", "Last Labor Date"), ColumnName = "LastLaborDate" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_COMPLETEDDATE", "Completed Date"), ColumnName = "CompleteDate" });

            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_INVOICENUMBER", "Invoice Number"), ColumnName = "InvoiceNumber" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_ALTERNATESTATUS", "Alternate Status"), ColumnName = "AlternateStatus" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_INSPECTIONS", "Inspections"), ColumnName = "InspectionCount" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_INSPECTIONREQUIRED", "Inspection Required"), ColumnName = "InspectionRequired" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_AUTOSENDCOMMUNICATIONENABLED", "Auto-send Communication Enabled"), ColumnName = "AutoText" });

            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_NOTES", "Notes"), ColumnName = "Notes" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_CONTACTS", "Contacts"), ColumnName = "Contacts" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_ESTIMATESTATUS", "Estimate Status"), ColumnName = "EstimateStatus" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_PUBLISHEDESTIMATES", "Published Estimates"), ColumnName = "PublishedEstimates" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_APPROVEDESTIMATES", "Approved Estimates"), ColumnName = "ApprovedEstimates" });

            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_REJECTEDESTIMATES", "Rejected Estimates"), ColumnName = "RejectedEstimates" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_PENDINGESTIMATES", "Pending Estimates"), ColumnName = "PendingEstimates" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_COMPONENT", "Component"), ColumnName = "Component" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_BILLABLE", "Billable"), ColumnName = "Billable" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_BILLTOJOB", "Bill to job"), ColumnName = "BillToJob" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_PARTSORDERNUMBER", "Parts Order Number"), ColumnName = "PartsOrderNumber" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_PARTSSTATUS", "Parts Status"), ColumnName = "PartsStatus" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_LASTINTERNALCOMMUNICATION", "Last Internal Communication"), ColumnName = "LastInternalCommunication" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_LASTINTERNALCOMMUNICATIONBY", "Last Internal Communication By"), ColumnName = "LastInternalCommunicationBy" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_WO_LASTINTERNALCOMMUNICATIONDATE", "Last Internal Communication Date"), ColumnName = "LastInternalCommunicationDate" });

            foreach (var r in list)
            {
                int index = 0;
                var dr = dt.NewRow();
                string wonumber = r.WorkOrderNumber ?? "";
                if (string.IsNullOrEmpty(wonumber) && r.Id > 0)
                    wonumber = r.Id.ToString();
                dr[index] = wonumber;
                dr[++index] = r.WorkOrderType;
                dr[++index] = r.AssignedToName;
                System.Drawing.Color bgcolor = System.Drawing.Color.White;
                try
                {
                    if (!string.IsNullOrWhiteSpace(r.StatusColor))
                        bgcolor = System.Drawing.ColorTranslator.FromHtml(r.StatusColor);
                }
                catch
                {
                }
                CExcelCellValue cStatus = new CExcelCellValue() { Value = r.StatusName, BackgroundColor = bgcolor };
                dr[++index] = cStatus;
                dr[++index] = r.Description;

                dr[++index] = r.AssetName;
                dr[++index] = r.VIN;
                dr[++index] = r.Make;
                dr[++index] = r.Model;
                dr[++index] = r.CustomerCode;

                dr[++index] = r.CustomerName;
                dr[++index] = r.LastCommunication;
                dr[++index] = r.LastCommunicationBy;
                dr[++index] = r.LastCommunicationDateStr;
                dr[++index] = r.Department;

                dr[++index] = r.Location;
                dr[++index] = r.AdvisorName;
                dr[++index] = r.SalespersonName;
                dr[++index] = r.CurrentJobsites;
                dr[++index] = r.CreateDateStr;
                dr[++index] = r.CreationDateStr;

                bgcolor = System.Drawing.Color.White;
                if (!r.Completed && r.DueDate != null && r.DueDate.Value < DateTime.Now.Date)
                {
                    bgcolor = System.Drawing.Color.Red;
                    dr[++index] = new CExcelCellValue() { Value = r.DueDateStr, BackgroundColor = bgcolor };
                }
                else
                    dr[++index] = r.DueDateStr;

                bgcolor = System.Drawing.Color.White;
                if (!r.Completed && r.NextFollowUpDate != null && r.NextFollowUpDate.Value < DateTime.Now.Date)
                {
                    bgcolor = System.Drawing.Color.Red;
                    dr[++index] = new CExcelCellValue() { Value = r.NextFollowUpDateStr, BackgroundColor = bgcolor };
                }
                else
                    dr[++index] = r.NextFollowUpDateStr;

                bgcolor = System.Drawing.Color.White;
                if (!r.Completed && r.PartsExpectedDate != null && r.PartsExpectedDate.Value < DateTime.Now.Date)
                {
                    bgcolor = System.Drawing.Color.Red;
                    dr[++index] = new CExcelCellValue() { Value = r.PartsExpectedDateStr, BackgroundColor = bgcolor };
                }
                else
                    dr[++index] = r.PartsExpectedDateStr;

                dr[++index] = r.LastLaborDateStr;
                dr[++index] = r.CompleteDateStr;
                dr[++index] = r.InvoiceNumber;

                dr[++index] = r.AlternateStatus;
                dr[++index] = r.InspectionCount;
                dr[++index] = r.InspectionRequired ? "Yes" : "No";
                dr[++index] = r.AutoText ? "Yes" : "No";
                dr[++index] = r.Notes;
                dr[++index] = GetWOContacts(r.Contacts);

                dr[++index] = GetEstimateStatus(r.EstimateStatus, lang);
                dr[++index] = r.PublishedEstimates;
                dr[++index] = r.ApprovedEstimates;
                dr[++index] = r.RejectedEstimates;
                dr[++index] = r.PendingEstimates;
                dr[++index] = r.Component;
                dr[++index] = r.Billable ? "Yes" : "No";
                dr[++index] = r.BillToJobName;
                dr[++index] = r.PartsOrderNumber;
                dr[++index] = r.PartsStatus;

                dr[++index] = r.LastInternalCommunication;
                dr[++index] = r.LastInternalCommunicationBy;
                dr[++index] = r.LastInternalCommunicationDateStr;

                dt.Rows.Add(dr);
            }

            double[] widths = null;
            if (colinfos.Length > 0)
            {
                for (int i = dt.Columns.Count - 1; i >= 0; i--)
                {//删除不显示的列
                    bool exists = false;
                    for (int j = 0; j < colinfos.Length; j++)
                    {
                        if (colinfos[j].ColumnKey == dt.Columns[i].ColumnName)
                        {
                            exists = true;
                            break;
                        }
                    }
                    if (!exists)
                        dt.Columns.RemoveAt(i);
                }

                for (int j = 0; j < colinfos.Length; j++)
                {
                    for (int i = dt.Columns.Count - 1; i >= 0; i--)
                    {
                        if (colinfos[j].ColumnKey == dt.Columns[i].ColumnName)
                        {
                            if (!string.IsNullOrWhiteSpace(colinfos[j].Caption))
                                dt.Columns[i].Caption = colinfos[j].Caption;
                            if (colinfos[j].Sort != 0 && dt.Columns[i].Caption != "Id")
                            {
                                if (colinfos[j].Sort == 1)
                                    dt.DefaultView.Sort = dt.Columns[i].ColumnName;
                                else if (colinfos[j].Sort == -1)
                                    dt.DefaultView.Sort = dt.Columns[i].ColumnName + " desc";
                            }
                            dt.Columns[i].SetOrdinal(j);
                            break;
                        }
                    }
                }

                dt = dt.DefaultView.ToTable();
                widths = colinfos.Select(c => (double)c.Width).ToArray();
            }

            bool IsCustomerRecordAllow = SystemParams.HasLicense("CustomerRecord");
            bool crpermission = SystemParams.CheckRight(SystemParams.CompanyID, user, FU.Feature.CUSTOMER_RECORD);
            if (!IsCustomerRecordAllow || !crpermission)
            {
                for (int i = dt.Columns.Count - 1; i >= 0; i--)
                {
                    var col = dt.Columns[i];
                    if (new string[] { "Advisor", "CustomerCode", "Contacts", "LastCommunication", "LastCommunicationDate", "LastCommunicationBy", "AlternateStatus", "EstimateStatus", "PublishedEstimates", "ApprovedEstimates", "RejectedEstimates", "PendingEstimates", "AutoText" }.Contains(col.Caption))
                        dt.Columns.Remove(col);
                }
            }

            byte[] data = ete.CreateExcel(dt, null, widths, null);

            return data;
        }

        private static string GetEstimateStatus(WorkOrderEstimateStatus s, string lang)
        {
            var text = "";
            if (s == WorkOrderEstimateStatus.Draft)
                text = SystemParams.GetTextByKey(lang, "P_WO_DRAFT", "Draft");
            else if (s == WorkOrderEstimateStatus.Pending)
                text = SystemParams.GetTextByKey(lang, "P_WO_AWAITINGCUSTOMERAPPROVAL", "Awaiting Customer Approval");
            else if (s == WorkOrderEstimateStatus.Canceled)
                text = SystemParams.GetTextByKey(lang, "P_WO_CANCELLEDBYDEALER", "Cancelled by Dealer");
            else if (s == WorkOrderEstimateStatus.Declined)
                text = SystemParams.GetTextByKey(lang, "P_WO_CUSTOMERREJECTED", "Customer Rejected");
            else if (s == WorkOrderEstimateStatus.Approved)
                text = SystemParams.GetTextByKey(lang, "P_WO_CUSTOMERAPPROVED", "Customer Approved");
            else if (s == WorkOrderEstimateStatus.None)
                text = "";
            return text;
        }
        private static string GetWOContacts(List<Foresight.Fleet.Services.AssetHealth.WorkOrder.ContactInfo> contacts)
        {
            StringBuilder text = new StringBuilder();
            if (contacts != null && contacts.Count > 0)
            {
                for (int i = 0; i < contacts.Count; i++)
                {
                    var contact = contacts[i];
                    var ptext = contact.Name;
                    if (contact.ContactPreference == FU.ContactPreferences.Text)
                    {
                        ptext += " – T";
                        if (contact.MobilePhone != "")
                            ptext += " – " + contact.MobilePhoneDisplayText;
                    }
                    else if (contact.ContactPreference == FU.ContactPreferences.Email)
                    {
                        if (contact.Email != "")
                            ptext += " - " + contact.Email;
                    }
                    else if (contact.ContactPreference == FU.ContactPreferences.Phone)
                    {
                        ptext += " – P";
                        if (contact.MobilePhone != "")
                            ptext += " – " + contact.MobilePhoneDisplayText;
                    }
                    text.AppendLine(ptext);
                }
            }
            return text.ToString();
        }

        #endregion


        public static byte[] ExportManageAssets(string lang, string sessionid, string useriid, string clientdata, string layout, FU.UserInfo user)
        {
            string[] p = JsonConvert.DeserializeObject<string[]>(clientdata);

            string companyid = p[0];
            bool showHidden = p[1] == "1";
            string searchtxt = p[2];
            bool attachment = p[3] == "1";
            int att = attachment ? 0 : 2;

            if (string.IsNullOrEmpty(companyid))
                companyid = SystemParams.CompanyID;

            if (string.IsNullOrWhiteSpace(companyid) && SystemParams.IsDealer)
                return null;

            AssetBasicInfo[] assets = FleetServiceClientHelper.CreateClient<AssetQueryClient>(companyid, sessionid).GetAssetBasicInfoByUser(companyid, searchtxt, useriid, att);
            List<AssetBasicItem> list = new List<AssetBasicItem>();
            foreach (var a in assets)
            {
                if (!showHidden && a.Hide) continue;
                AssetBasicItem asset = new AssetBasicItem();
                Helper.CloneProperty(asset, a);
                asset.EngineHours = a.EngineHours ?? 0;
                asset.Odometer = a.Odometer ?? 0;
                list.Add(asset);
            }
            list = list.OrderBy((m) => m.VIN).ToList();
            var colinfos = JsonConvert.DeserializeObject<LayoutColumn[]>(layout);
            colinfos = colinfos.Where(c => c.Visible && !new string[] { "Selected", "UploadAssetIcon", "DeleteAssetIcon", "Detail", "DeleteAsset" }.Contains(c.ColumnKey)).ToArray();
            if (user.UserType != FU.UserTypes.SupperAdmin)
            {
                colinfos = colinfos.Where(c => !new string[] { "Preloaded" }.Contains(c.ColumnKey)).ToArray();
            }

            ExportToExcel ete = new ExportToExcel();

            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MA_VINSN", "SN/VIN"), ColumnName = "VIN" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MA_ASSETNAME", "Asset Name"), ColumnName = "Name" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MA_ASSETNAME2", "Asset Name(Custom)"), ColumnName = "Name2" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MA_MAKE", "Make"), ColumnName = "Make" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MA_MODEL", "Model"), ColumnName = "Model" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MA_TYPE", "Asset Type"), ColumnName = "MachineType" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MA_YEAR", "Year"), ColumnName = "MakeYear" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MA_ENGINEHOURS", "Engine Hours"), ColumnName = "EngineHours" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MA_ENGINEHOURSDATE", "Engine Hours Date"), ColumnName = "EngineHoursDate" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MA_ODOMETER", "Odometer"), ColumnName = "Odometer" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MA_ODOMETERDATE", "Odometer Date"), ColumnName = "OdometerDate" });

            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MA_DESCRIPTION", "Description"), ColumnName = "Description" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MA_JOBSITE", "Jobsite"), ColumnName = "Jobsite" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MA_PAIREDDEVICESN", "Paired Device SN"), ColumnName = "GpsDeviceSN" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MA_ACQUISITIONTYPE", "Acquisition Type"), ColumnName = "AcquisitionType" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MA_ADDEDON", "Added On"), ColumnName = "AddedOn" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MA_AVAILABILITY", "Availability"), ColumnName = "CustomStatus" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MA_PMPLAN", "PMPlan"), ColumnName = "PMPlan" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_JS_ASSETGROUP", "Asset Group"), ColumnName = "AssetGroups" });

            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MA_ONROAD", "On-Road"), ColumnName = "OnRoad" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MA_ATTACHMENT", "Attachment"), ColumnName = "Attachment" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MA_HIDE", "Hide"), ColumnName = "Hide" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MA_TELEMATICSENABLED", "Telematics Enabled"), ColumnName = "TelematicsEnabled" });

            if (user.UserType == FU.UserTypes.SupperAdmin)
            {
                dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MA_PRELOADED", "Preloaded"), Caption = "Preloaded" });
            }

            foreach (var r in list)
            {
                int index = 0;
                var dr = dt.NewRow();
                dr[index] = r.VIN;
                dr[++index] = r.Name;
                dr[++index] = r.Name2;
                dr[++index] = r.MakeName;
                dr[++index] = r.ModelName;
                dr[++index] = r.TypeName;
                dr[++index] = r.MakeYear == 0 ? "" : r.MakeYear + "";
                dr[++index] = r.EngineHours;
                dr[++index] = r.EngineHoursDateStr;
                dr[++index] = r.Odometer + (r.Odometer > 0 ? " " + r.OdometerUOM : "");
                dr[++index] = r.OdometerDateStr;

                dr[++index] = r.Description;
                dr[++index] = r.Jobsites;
                dr[++index] = r.CalampDeviceAirID;
                dr[++index] = r.AcquisitionType;
                dr[++index] = r.AddedTimeStr;
                if (r.CustomStatus == AssetCustomStatus.InUse)
                    dr[++index] = SystemParams.GetTextByKey(lang, "P_MA_INUSE", "In Use");
                else if (r.CustomStatus == AssetCustomStatus.Available)
                    dr[++index] = SystemParams.GetTextByKey(lang, "P_MA_AVAILABLE", "Available");
                else if (r.CustomStatus == AssetCustomStatus.Standby)
                    dr[++index] = SystemParams.GetTextByKey(lang, "P_MA_STANDBY", "Standby");
                else if (r.CustomStatus == AssetCustomStatus.Down)
                    dr[++index] = SystemParams.GetTextByKey(lang, "P_MA_DOWN", "Down");
                else
                    dr[++index] = "";
                dr[++index] = r.PMPlans;
                dr[++index] = r.AssetGroups;

                dr[++index] = r.OnRoad ? "Yes" : "No";
                dr[++index] = r.Attachment ? "Yes" : "No";
                dr[++index] = r.Hide ? "Yes" : "No";
                dr[++index] = r.TelematicsEnabled ? "Yes" : "No";
                if (user.UserType == FU.UserTypes.SupperAdmin)
                {
                    dr[++index] = r.Preloaded ? "Yes" : "No";
                }
                dt.Rows.Add(dr);
            }

            double[] widths = null;
            if (colinfos.Length > 0)
            {
                for (int i = dt.Columns.Count - 1; i >= 0; i--)
                {//删除不显示的列
                    bool exists = false;
                    for (int j = 0; j < colinfos.Length; j++)
                    {
                        if (colinfos[j].ColumnKey == dt.Columns[i].ColumnName)
                        {
                            exists = true;
                            break;
                        }
                    }
                    if (!exists)
                        dt.Columns.RemoveAt(i);
                }

                for (int j = 0; j < colinfos.Length; j++)
                {
                    for (int i = dt.Columns.Count - 1; i >= 0; i--)
                    {
                        if (colinfos[j].ColumnKey == dt.Columns[i].ColumnName)
                        {
                            if (!string.IsNullOrWhiteSpace(colinfos[j].Caption))
                                dt.Columns[i].Caption = colinfos[j].Caption;
                            if (colinfos[j].Sort != 0)
                            {
                                if (colinfos[j].Sort == 1)
                                    dt.DefaultView.Sort = dt.Columns[i].ColumnName;
                                else if (colinfos[j].Sort == -1)
                                    dt.DefaultView.Sort = dt.Columns[i].ColumnName + " desc";
                            }
                            dt.Columns[i].SetOrdinal(j);
                            break;
                        }
                    }
                }

                dt = dt.DefaultView.ToTable();
                widths = colinfos.Select(c => (double)c.Width).ToArray();
            }


            byte[] data = ete.CreateExcel(dt, null, widths, null);

            return data;
        }

        public static byte[] ExportAssetGroups(string lang, string sessionid, string useriid, string searchtext)
        {
            var list = FleetServiceClientHelper.CreateClient<AssetQueryClient>(SystemParams.CompanyID, sessionid).GetAssetGroups(SystemParams.CompanyID, searchtext, useriid);
            list = list.OrderBy(g => g.Name).ToArray();

            string json = "[{\"ColumnKey\":\"Name\",\"Width\":360,\"Sort\":0},{\"ColumnKey\":\"Description\",\"Width\":360,\"Sort\":0},{\"ColumnKey\":\"Code\",\"Width\":200,\"Sort\":0},{\"ColumnKey\":\"Edit\",\"Width\":30,\"Sort\":0},{\"ColumnKey\":\"Delete\",\"Width\":30,\"Sort\":0}]";
            var colinfos = JsonConvert.DeserializeObject<LayoutColumn[]>(json);
            colinfos = colinfos.Where(c => c.Visible && !new string[] { "Edit", "Delete" }.Contains(c.ColumnKey)).ToArray();

            ExportToExcel ete = new ExportToExcel();
            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_AG_GROUPNAME", "Group Name"), ColumnName = "Name" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_AG_DESCRIPTION", "Description"), ColumnName = "Description" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_AG_CODE", "Code"), ColumnName = "Code" });

            foreach (var r in list)
            {
                int index = 0;
                var dr = dt.NewRow();
                dr[index] = r.Name;
                dr[++index] = r.Description;
                dr[++index] = r.Code;
                dt.Rows.Add(dr);
            }

            double[] widths = null;
            if (colinfos.Length > 0)
            {
                for (int j = 0; j < colinfos.Length; j++)
                {
                    for (int i = dt.Columns.Count - 1; i >= 0; i--)
                    {
                        if (colinfos[j].ColumnKey == dt.Columns[i].ColumnName)
                        {
                            if (!string.IsNullOrWhiteSpace(colinfos[j].Caption))
                                dt.Columns[i].Caption = colinfos[j].Caption;
                            if (colinfos[j].Sort != 0)
                            {
                                if (colinfos[j].Sort == 1)
                                    dt.DefaultView.Sort = dt.Columns[i].ColumnName;
                                else if (colinfos[j].Sort == -1)
                                    dt.DefaultView.Sort = dt.Columns[i].ColumnName + " desc";
                            }
                            dt.Columns[i].SetOrdinal(j);
                            break;
                        }
                    }
                }

                dt = dt.DefaultView.ToTable();
                widths = colinfos.Select(c => (double)c.Width).ToArray();
            }


            byte[] data = ete.CreateExcel(dt, null, widths, null);

            return data;
        }

        public static byte[] ExportManageDevices(string lang, string sessionid, string clientdata, FU.UserInfo user)
        {
            string[] p = JsonConvert.DeserializeObject<string[]>(clientdata);

            string contractorid = p[0];
            string searchtxt = p[1];
            if (string.IsNullOrEmpty(contractorid))
                contractorid = SystemParams.CompanyID;

            FFSDevice.DeviceInfo[] devs = FleetServiceClientHelper.CreateClient<FFSDevice.DeviceProvider>(contractorid, sessionid).GetDevices(contractorid, searchtxt);

            if (devs == null)
                return new byte[0];

            List<DeviceItem> list = new List<DeviceItem>();
            foreach (var dev in devs)
            {
                DeviceItem deviceitem = new DeviceItem();
                Helper.CloneProperty(deviceitem, dev);

                if (dev.PairedAsset != null)
                {
                    deviceitem.PairedAsset = new PairedAssetItem();
                    Helper.CloneProperty(deviceitem.PairedAsset, dev.PairedAsset);
                }

                list.Add(deviceitem);
            }


            string json = "[{\"ColumnKey\":\"SerialNumber\",\"Width\":120,\"Sort\":0},{\"ColumnKey\":\"AlternativeSerialNumber\",\"Width\":120,\"Sort\":0},{\"ColumnKey\":\"DeviceType\",\"Width\":120,\"Sort\":0},{\"ColumnKey\":\"SourceName\",\"Width\":120,\"Sort\":0},{\"ColumnKey\":\"Status\",\"Width\":80,\"Sort\":0},{\"ColumnKey\":\"AddDate\",\"Width\":100,\"Sort\":0},{\"ColumnKey\":\"FIInstalltion\",\"Width\":100,\"Sort\":0},{\"ColumnKey\":\"Installer\",\"Width\":100,\"Sort\":0},{\"ColumnKey\":\"Notes\",\"Width\":200,\"Sort\":0},{\"ColumnKey\":\"ServiceStartDate\",\"Width\":110,\"Sort\":0},{\"ColumnKey\":\"VIN\",\"Width\":200,\"Sort\":0},{\"ColumnKey\":\"Name\",\"Width\":200,\"Sort\":0},{\"ColumnKey\":\"Year\",\"Width\":80,\"Sort\":0},{\"ColumnKey\":\"Make\",\"Width\":150,\"Sort\":0},{\"ColumnKey\":\"Model\",\"Width\":150,\"Sort\":0},{\"ColumnKey\":\"MachineType\",\"Width\":150,\"Sort\":0},{\"ColumnKey\":\"EngineHours\",\"Width\":90,\"Sort\":0},{\"ColumnKey\":\"EngineHoursDate\",\"Width\":120,\"Sort\":0},{\"ColumnKey\":\"InvoiceDate\",\"Width\":100,\"Sort\":0},{\"ColumnKey\":\"InvoiceNumber\",\"Width\":120,\"Sort\":0},{\"ColumnKey\":\"SalesOrderNumber\",\"Width\":120,\"Sort\":0},{\"ColumnKey\":\"Edit\",\"Width\":30,\"Sort\":0},{\"ColumnKey\":\"ONotes\",\"Width\":30,\"Sort\":0},{\"ColumnKey\":\"ChangeContractor\",\"Width\":30,\"Sort\":0}]";
            var colinfos = JsonConvert.DeserializeObject<LayoutColumn[]>(json);
            colinfos = colinfos.Where(c => c.Visible && !new string[] { "Edit", "Delete" }.Contains(c.ColumnKey)).ToArray();
            if (user.UserType < FU.UserTypes.SupperAdmin)
            {
                colinfos = colinfos.Where(c => !new string[] { "FIInstalltion", "Installer", "SalesOrderNumber" }.Contains(c.ColumnKey)).ToArray();
            }

            ExportToExcel ete = new ExportToExcel();
            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MD_AIRDIORSN", "Air ID or SN"), ColumnName = "SerialNumber" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MD_ESN", "ESN"), ColumnName = "AlternativeSerialNumber" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MD_DEVICETYPE", "Device Type"), ColumnName = "DeviceType" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MD_SOURCE", "Source"), ColumnName = "SourceName" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MD_STATUS", "Status"), ColumnName = "Status" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MD_ADDDATE", "Add Date"), ColumnName = "AddDate" });
            if (user.UserType == FU.UserTypes.SupperAdmin)
            {
                dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MD_FIINSTALL", "FI Install"), ColumnName = "FIInstalltion" });
                dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MD_INSTALLER", "Installer"), ColumnName = "Installer" });
            }
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MD_NOTES", "Notes"), ColumnName = "Notes" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MD_SERVICESTATDATE", "Service Start Date"), ColumnName = "ServiceStartDate" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MD_ASSETVINSN", "Asset VIN/SN"), ColumnName = "VIN" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MD_ASSETNAME", "Asset Name"), ColumnName = "Name" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MD_YEAR", "Year"), ColumnName = "Year" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MD_MAKE", "Make"), ColumnName = "Make" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MD_MODEL", "Model"), ColumnName = "Model" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MD_TYPE", "Type"), ColumnName = "MachineType" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MD_ENGINEHOURS", "Engine Hours"), ColumnName = "EngineHours" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MD_ENGINEHOURSDATE", "Engine Hours Date"), ColumnName = "EngineHoursDate" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MD_INVOICEDATE", "Invoice Date"), ColumnName = "InvoiceDate" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MD_INVOICENUMBER", "Invoice #"), ColumnName = "InvoiceNumber" });
            if (user.UserType == FU.UserTypes.SupperAdmin)
            {
                dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MD_SALESORDER", "Sales Order #"), Caption = "SalesOrderNumber" });
            }

            foreach (var r in list)
            {
                int index = 0;
                var dr = dt.NewRow();
                dr[index] = r.SerialNumber;
                dr[++index] = r.AlternativeSerialNumber;
                dr[++index] = r.DeviceType;
                dr[++index] = r.SourceName;
                dr[++index] = r.Status == 1 ? "Active" : "Inactive";
                dr[++index] = r.AddDateStr;
                if (user.UserType == FU.UserTypes.SupperAdmin)
                {
                    dr[++index] = r.FIInstalltion ? "Yes" : "No";
                    dr[++index] = r.Installer;
                }
                dr[++index] = r.Notes;
                dr[++index] = r.ServiceStartDateStr;
                dr[++index] = r.PairedAsset == null ? "" : r.PairedAsset.VIN;
                dr[++index] = r.PairedAsset == null ? "" : r.PairedAsset.Name;
                dr[++index] = (r.PairedAsset == null || r.PairedAsset.Year == 0) ? "" : r.PairedAsset.Year + "";
                dr[++index] = r.PairedAsset == null ? "" : r.PairedAsset.MakeName;
                dr[++index] = r.PairedAsset == null ? "" : r.PairedAsset.ModelName;
                dr[++index] = r.PairedAsset == null ? "" : r.PairedAsset.TypeName;
                dr[++index] = (r.PairedAsset == null || r.PairedAsset.EngineHours == 0) ? "" : r.PairedAsset.EngineHours + "";
                dr[++index] = r.PairedAsset == null ? "" : r.PairedAsset.EngineHoursDateStr;
                dr[++index] = r.InvoiceDateStr;
                dr[++index] = r.InvoiceNumber;
                if (user.UserType == FU.UserTypes.SupperAdmin)
                {
                    dr[++index] = r.SalesOrderNumber;
                }
                dt.Rows.Add(dr);
            }

            double[] widths = null;
            if (colinfos.Length > 0)
            {
                for (int j = 0; j < colinfos.Length; j++)
                {
                    for (int i = dt.Columns.Count - 1; i >= 0; i--)
                    {
                        if (colinfos[j].ColumnKey == dt.Columns[i].ColumnName)
                        {
                            if (!string.IsNullOrWhiteSpace(colinfos[j].Caption))
                                dt.Columns[i].Caption = colinfos[j].Caption;
                            if (colinfos[j].Sort != 0)
                            {
                                if (colinfos[j].Sort == 1)
                                    dt.DefaultView.Sort = dt.Columns[i].ColumnName;
                                else if (colinfos[j].Sort == -1)
                                    dt.DefaultView.Sort = dt.Columns[i].ColumnName + " desc";
                            }
                            dt.Columns[i].SetOrdinal(j);
                            break;
                        }
                    }
                }

                dt = dt.DefaultView.ToTable();
                widths = colinfos.Select(c => (double)c.Width).ToArray();
            }


            byte[] data = ete.CreateExcel(dt, null, widths, null);

            return data;
        }

        public static byte[] ExportMaintenanceRecords(string lang, string sessionid, string useriid, string clientdata)
        {
            string[] p = JsonConvert.DeserializeObject<string[]>(clientdata);

            long assetid = -1;
            long.TryParse(p[0], out assetid);
            string maintenanceType = p[1];
            string mtype = p[2];
            string searchtxt = p[3];
            string sortype = p[4];
            string sortdata = p[5];
            string sdatestr = p[6];
            string edatestr = p[7];

            DateTime beginDate = Helper.DBMinDateTime;
            DateTime endDate = DateTime.MaxValue;
            if (!DateTime.TryParse(sdatestr, out beginDate))
                beginDate = Helper.DBMinDateTime;
            if (!DateTime.TryParse(edatestr, out endDate))
                endDate = DateTime.MaxValue;

            MaintenanceLogInfo[] logs = MaintenanceManagement.GetMaintenanceLog(sessionid, assetid, maintenanceType, string.IsNullOrWhiteSpace(mtype) ? -1 : Convert.ToInt32(mtype), searchtxt, beginDate, endDate, useriid);

            if (!string.IsNullOrWhiteSpace(sortype))
            {
                if (string.Compare(sortype, "1", true) == 0)
                {
                    if (string.Compare(sortdata, "DESC", true) == 0)
                    {
                        logs = logs.OrderByDescending(m => m.MaintenanceDate).ToArray();
                    }
                    else
                    {
                        logs = logs.OrderBy(m => m.MaintenanceDate).ToArray();
                    }
                }

                if (string.Compare(sortype, "2", true) == 0)
                {
                    if (string.Compare(sortdata, "DESC", true) == 0)
                    {
                        logs = logs.OrderByDescending(m => m.AlertTime).ToArray();
                    }
                    else
                    {
                        logs = logs.OrderBy(m => m.AlertTime).ToArray();
                    }
                }
            }


            string json = "[{\"ColumnKey\":\"MachineID\",\"Width\":120,\"Sort\":0},{\"ColumnKey\":\"MachinePin\",\"Width\":200,\"Sort\":0},{\"ColumnKey\":\"DisplayName\",\"Width\":200,\"Sort\":0},{\"ColumnKey\":\"MaintenanceDate\",\"Width\":120,\"Sort\":0},{\"ColumnKey\":\"LogType\",\"Width\":130,\"Sort\":0},{\"ColumnKey\":\"MaintenanceHours\",\"Width\":120,\"Sort\":0},{\"ColumnKey\":\"ODOMeter\",\"Width\":120,\"Sort\":0},{\"ColumnKey\":\"ODOMemterUOM\",\"Width\":120,\"Sort\":0},{\"ColumnKey\":\"Cost\",\"Width\":120,\"Sort\":0},{\"ColumnKey\":\"InvoiceNumber\",\"Width\":120,\"Sort\":0},{\"ColumnKey\":\"CompletedByName\",\"Width\":150,\"Sort\":0},{\"ColumnKey\":\"Notes\",\"Width\":200,\"Sort\":0},{\"ColumnKey\":\"MachineMake\",\"Width\":150,\"Sort\":0},{\"ColumnKey\":\"MachineModel\",\"Width\":150,\"Sort\":0},{\"ColumnKey\":\"MachineType\",\"Width\":150,\"Sort\":0},{\"ColumnKey\":\"AlertID\",\"Width\":80,\"Sort\":0},{\"ColumnKey\":\"AlertTitle\",\"Width\":200,\"Sort\":0},{\"ColumnKey\":\"AlertType\",\"Width\":150,\"Sort\":0},{\"ColumnKey\":\"AlertTime\",\"Width\":120,\"Sort\":0},{\"ColumnKey\":\"Attachment\",\"Width\":30,\"Sort\":0},{\"ColumnKey\":\"Edit\",\"Width\":30,\"Sort\":0},{\"ColumnKey\":\"Delete\",\"Width\":30,\"Sort\":0}]";
            var colinfos = JsonConvert.DeserializeObject<LayoutColumn[]>(json);
            colinfos = colinfos.Where(c => c.Visible && !new string[] { "Edit", "Delete" }.Contains(c.ColumnKey)).ToArray();

            ExportToExcel ete = new ExportToExcel();
            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MRM_ASSETID", "Asset ID"), ColumnName = "MachineID" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MRM_SN", "SN"), ColumnName = "MachinePin" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MRM_NAME", "Name"), ColumnName = "DisplayName" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MRM_MAINTENANCEDATE", "Maintenance Date"), ColumnName = "MaintenanceDate" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MRM_MAINTENANCETYPE", "Maintenance Type"), ColumnName = "LogType" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MRM_MAINTENANCEHOURS", "Maintenance Hours"), ColumnName = "MaintenanceHours" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MRM_MAINTENANCEDISTANCE", "Maintenance Distance"), ColumnName = "ODOMeter" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MRM_DISTANCEUOM", "Distance UOM"), ColumnName = "ODOMemterUOM" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MRM_COST", "Cost"), ColumnName = "Cost" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MRM_INVOICENUMBER", "Invoice Number"), ColumnName = "InvoiceNumber" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MRM_COMPLETEDBY", "Completed By"), ColumnName = "CompletedByName" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MRM_DESCRIPTION", "Description"), ColumnName = "Notes" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MRM_MAKE", "Make"), ColumnName = "MachineMake" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MRM_MODEL", "Model"), ColumnName = "MachineModel" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MRM_ASSETTYPE", "Type"), ColumnName = "MachineType" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MRM_ALERTID", "Alert ID"), ColumnName = "AlertID" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MRM_ALERTTITLE", "Alert Title"), ColumnName = "AlertTitle" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MRM_ALERTTYPE", "Alert Type"), ColumnName = "AlertType" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_MRM_ALERTTIME", "Alert Time"), ColumnName = "AlertTime" });

            foreach (var r in logs)
            {
                string distype = r.LogType;
                if (r.LogType == "TimeOffRoad")
                    distype = "Time/Off-Road";
                else if (r.LogType == "TimeOverRoad")
                    distype = "Time/Over Road";
                int index = 0;
                var dr = dt.NewRow();
                dr[index] = r.MachineID;
                dr[++index] = r.MachinePin;
                dr[++index] = r.DisplayName;
                dr[++index] = r.StrForMaintenanceDate;
                dr[++index] = distype;
                dr[++index] = r.MaintenanceHours;
                dr[++index] = r.ODOMeter;
                dr[++index] = r.ODOMemterUOM;
                dr[++index] = r.Cost;
                dr[++index] = r.InvoiceNumber;
                dr[++index] = r.CompletedByName;
                dr[++index] = r.Notes;
                dr[++index] = r.MachineMake;
                dr[++index] = r.MachineModel;
                dr[++index] = r.MachineType;
                dr[++index] = r.AlertID <= 0 ? "" : r.AlertID + "";
                dr[++index] = r.AlertTitle;
                dr[++index] = r.AlertType;
                dr[++index] = r.StrForAlertTime;
                dt.Rows.Add(dr);
            }

            double[] widths = null;
            if (colinfos.Length > 0)
            {
                for (int j = 0; j < colinfos.Length; j++)
                {
                    for (int i = dt.Columns.Count - 1; i >= 0; i--)
                    {
                        if (colinfos[j].ColumnKey == dt.Columns[i].ColumnName)
                        {
                            if (!string.IsNullOrWhiteSpace(colinfos[j].Caption))
                                dt.Columns[i].Caption = colinfos[j].Caption;
                            if (colinfos[j].Sort != 0)
                            {
                                if (colinfos[j].Sort == 1)
                                    dt.DefaultView.Sort = dt.Columns[i].ColumnName;
                                else if (colinfos[j].Sort == -1)
                                    dt.DefaultView.Sort = dt.Columns[i].ColumnName + " desc";
                            }
                            dt.Columns[i].SetOrdinal(j);
                            break;
                        }
                    }
                }

                dt = dt.DefaultView.ToTable();
                widths = colinfos.Select(c => (double)c.Width).ToArray();
            }


            byte[] data = ete.CreateExcel(dt, null, widths, null);

            return data;
        }

        public static byte[] ExportInspectChanges(string lang, string sessionid, string clientdata)
        {
            string[] ps = JsonConvert.DeserializeObject<string[]>(clientdata);
            bool teamintelligence = Helper.IsTrue(ps[0]);
            string inspectid = HttpUtility.HtmlDecode(ps[1]);

            AssetInspectItem[] insplectitems = null;

            if (teamintelligence)
            {
                var client = FleetServiceClientHelper.CreateClient<TeamIntelligenceClient>(sessionid);
                insplectitems = client.GetInspectHistoryItems(SystemParams.CompanyID, inspectid);
            }
            else
            {
                var client = FleetServiceClientHelper.CreateClient<AssetInspectClient>(sessionid);
                insplectitems = client.GetInspectHistoryItems(SystemParams.CompanyID, inspectid);
            }

            if (insplectitems == null || insplectitems.Length == 0)
                return new byte[0];

            List<AssetInspectInfo> list = new List<AssetInspectInfo>();
            foreach (AssetInspectItem item in insplectitems)
            {
                AssetInspectInfo inspect = new AssetInspectInfo();
                Helper.CloneProperty(inspect, item);
                list.Add(inspect);
            }

            string json = "[{\"ColumnKey\":\"LastUpdatedByUserName\",\"Width\":250,\"Sort\":0},{\"ColumnKey\":\"LastUpdatedTimeLocal\",\"Width\":150,\"Sort\":0},{\"ColumnKey\":\"VIN\",\"Width\":200,\"Sort\":0},{\"ColumnKey\":\"AssetName\",\"Width\":200,\"Sort\":0},{\"ColumnKey\":\"WorkOrderNumber\",\"Width\":200,\"Sort\":0}]";
            var colinfos = JsonConvert.DeserializeObject<LayoutColumn[]>(json);
            colinfos = colinfos.Where(c => c.Visible && !new string[] { "Edit", "Delete" }.Contains(c.ColumnKey)).ToArray();

            ExportToExcel ete = new ExportToExcel();
            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_IPT_USERNAME", "User Name"), ColumnName = "LastUpdatedByUserName" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_IPT_DATETIME", "Date Time"), ColumnName = "LastUpdatedTimeLocal" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_IPT_VINSN", "VIN/SN"), ColumnName = "VIN" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_IPT_ASSETNAME", "Asset Name"), ColumnName = "AssetName" });
            dt.Columns.Add(new DataColumn() { Caption = SystemParams.GetTextByKey(lang, "P_IPT_WORKORDER", "Work Order #"), ColumnName = "WorkOrderNumber" });
            foreach (var r in list)
            {
                int index = 0;
                var dr = dt.NewRow();
                dr[index] = r.LastUpdatedByUserName;
                dr[++index] = r.LastUpdatedTimeLocalStr;
                dr[++index] = r.VIN;
                dr[++index] = r.AssetName;
                dr[++index] = r.WorkOrderNumber;
                dt.Rows.Add(dr);
            }

            double[] widths = null;
            if (colinfos.Length > 0)
            {
                for (int j = 0; j < colinfos.Length; j++)
                {
                    for (int i = dt.Columns.Count - 1; i >= 0; i--)
                    {
                        if (colinfos[j].ColumnKey == dt.Columns[i].ColumnName)
                        {
                            if (!string.IsNullOrWhiteSpace(colinfos[j].Caption))
                                dt.Columns[i].Caption = colinfos[j].Caption;
                            if (colinfos[j].Sort != 0)
                            {
                                if (colinfos[j].Sort == 1)
                                    dt.DefaultView.Sort = dt.Columns[i].ColumnName;
                                else if (colinfos[j].Sort == -1)
                                    dt.DefaultView.Sort = dt.Columns[i].ColumnName + " desc";
                            }
                            dt.Columns[i].SetOrdinal(j);
                            break;
                        }
                    }
                }

                dt = dt.DefaultView.ToTable();
                widths = colinfos.Select(c => (double)c.Width).ToArray();
            }


            byte[] data = ete.CreateExcel(dt, null, widths, null);

            return data;
        }

        public static byte[] ExportWorkOrderHistory(string lang, string sessionid, string companyid, long woid, DateTime from, DateTime to, string filter)
        {
            if (string.IsNullOrEmpty(companyid))
                companyid = SystemParams.CompanyID;

            WorkOrderHistoryInfo[] items = FleetServiceClientHelper.CreateClient<WorkOrderProvider>(companyid, sessionid).GetWorkOrderHistorys(companyid, woid, from, to, filter);

            ExportToExcel ete = new ExportToExcel();

            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_WO_HIS_DATETIMESTAMP", "Date/Time Stamp") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_WO_HIS_UPDATE", "Update") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_WO_HIS_UPDATETYPE", "Update Type") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_WO_HIS_BY", "By") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_WO_HIS_CATEGORY", "Category") });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_WO_HIS_DETAIL", "Detail") });

            foreach (var r in items)
            {
                int index = 0;
                string type = "";
                string status = "";
                string category = "";
                GetWorkOrderHistoryStr(lang, r, out type, out status, out category);
                var dr = dt.NewRow();
                dr[index] = r.DateTime.ToString();
                dr[++index] = status;
                dr[++index] = type;
                dr[++index] = r.UpdateBy;
                dr[++index] = category;
                dr[++index] = r.Detail;
                dt.Rows.Add(dr);
            }
            double[] widths = new double[] { 150d, 80d, 120d, 200d, 200d, 400d };
            byte[] data = ete.CreateExcel(dt, null, widths, null);

            return data;
        }

        private static void GetWorkOrderHistoryStr(string lang, WorkOrderHistoryInfo r, out string type, out string status, out string category)
        {
            type = "";
            status = "";
            category = "";
            if (r.UpdateType == 0)
                type = SystemParams.GetTextByKey(lang, "P_WO_HIS_MANUALLY", "Manually");
            else if (r.UpdateType == 1)
                type = SystemParams.GetTextByKey(lang, "P_WO_HIS_AUTOMATICALLY", "Automatically");
            else if (r.UpdateType == 2)
                type = SystemParams.GetTextByKey(lang, "P_WO_HIS_SYSTEM", "System");

            if (r.UpdateStatus == 0)
                status = SystemParams.GetTextByKey(lang, "P_WO_HIS_CREATED", "Created");
            else if (r.UpdateStatus == WorkOrderUpdateStatus.Modified || r.UpdateStatus == WorkOrderUpdateStatus.Deleted || r.UpdateStatus == WorkOrderUpdateStatus.Restore)
                status = SystemParams.GetTextByKey(lang, "P_WO_HIS_MODIFIED", "Modified");
            else if (r.UpdateStatus == WorkOrderUpdateStatus.Closed)
                status = SystemParams.GetTextByKey(lang, "P_WO_HIS_CLOSED", "Closed");
            else if (r.UpdateStatus == WorkOrderUpdateStatus.ReOpened)
                status = SystemParams.GetTextByKey(lang, "P_WO_HIS_REOPENED", "Re_Opened");
            //else if (r.UpdateStatus == WorkOrderUpdateStatus.Restore)
            //    status = SystemParams.GetTextByKey(lang, "P_WO_HIS_RESTORED", "Restored");
            //else if (r.UpdateStatus == WorkOrderUpdateStatus.Deleted)
            //    status = SystemParams.GetTextByKey(lang, "P_WO_HIS_DELETED", "Deleted");

            switch ((int)r.Category)
            {
                case 0:
                    category = SystemParams.GetTextByKey(lang, "P_WO_WORKORDERSTATUS", "Work Order Status");
                    break;
                case 1:
                    category = SystemParams.GetTextByKey(lang, "P_WO_ASSIGNEDTO", "Assigned To");
                    break;
                case 2:
                    category = SystemParams.GetTextByKey(lang, "P_WO_ADVISOR", "Advisor");
                    break;
                case 3:
                    category = SystemParams.GetTextByKey(lang, "P_WO_WORKORDERTYPE", "Work Order Type");
                    break;
                case 4:
                    category = SystemParams.GetTextByKey(lang, "P_WO_LOCATION", "Location");
                    break;
                case 5:
                    category = SystemParams.GetTextByKey(lang, "P_WO_DEPARTMENT", "Department");
                    break;
                case 6:
                    category = SystemParams.GetTextByKey(lang, "P_WO_ALTERNATESTATUS", "Alternate Status");
                    break;
                case 7:
                    category = SystemParams.GetTextByKey(lang, "P_WO_DESCRIPTION", "Description");
                    break;
                case 8:
                    category = SystemParams.GetTextByKey(lang, "P_WO_INVOICENUMBER", "Invoice Number");
                    break;
                case 9:
                    category = SystemParams.GetTextByKey(lang, "P_WO_INTERNALID", "Internal ID");
                    break;
                case 10:
                    category = SystemParams.GetTextByKey(lang, "P_WO_COMPLETEDATE", "Complete Date");
                    break;
                case 11:
                    category = SystemParams.GetTextByKey(lang, "P_WO_NEXTFOLLOWUPDATE", "Next Follow Up Date");
                    break;
                case 12:
                    category = SystemParams.GetTextByKey(lang, "P_WO_DUEDATE", "Due Date");
                    break;
                case 13:
                    category = SystemParams.GetTextByKey(lang, "P_WO_PARTSEXPECTEDDATE", "Parts Expected Date");
                    break;
                case 14:
                    category = SystemParams.GetTextByKey(lang, "P_WO_LASTLABORDATE", "Last Labor Date");
                    break;
                case 15:
                    category = SystemParams.GetTextByKey(lang, "P_WO_TOTALCOST", "Total Cost");
                    break;
                case 16:
                    category = SystemParams.GetTextByKey(lang, "P_WO_EXPECTEDCOST", "Expected Cost");
                    break;
                case 17:
                    category = SystemParams.GetTextByKey(lang, "P_WO_PARTSCOST1", "Parts Cost");
                    break;
                case 18:
                    category = SystemParams.GetTextByKey(lang, "P_WO_TRAVELTIMECOST1", "Travel Time Cost");
                    break;
                case 19:
                    category = SystemParams.GetTextByKey(lang, "P_WO_LABORCOST1", "Labor Cost");
                    break;
                case 20:
                    category = SystemParams.GetTextByKey(lang, "P_WO_OTHERCOST1", "Other Cost");
                    break;
                case 21:
                    category = SystemParams.GetTextByKey(lang, "P_WO_ESTIMATE", "Estimate");
                    break;
                case 22:
                    category = SystemParams.GetTextByKey(lang, "P_WO_INSPECTION", "Inspection");
                    break;
                case 23:
                    category = SystemParams.GetTextByKey(lang, "P_WO_INVOICE", "Invoice");
                    break;
                case 24:
                    category = SystemParams.GetTextByKey(lang, "P_WO_SEGMENTUSER", "Segment User");
                    break;
                case 25:
                    category = SystemParams.GetTextByKey(lang, "P_WO_SEGMENTHOURS", "Segment Hours");
                    break;
                case 26:
                    category = SystemParams.GetTextByKey(lang, "P_WO_SEGMENTJOBSITE", "Segment Jobsite");
                    break;
                case 27:
                    category = SystemParams.GetTextByKey(lang, "P_WO_SEGMENTCOST", "Segment Cost");
                    break;
                case 28:
                    category = SystemParams.GetTextByKey(lang, "P_WO_SEGMENTCOMPONENT", "Segment Component");
                    break;
                case 29:
                    category = SystemParams.GetTextByKey(lang, "P_WO_SEGMENTCOMPLETED", "Segment Completed");
                    break;
                case 30:
                    category = SystemParams.GetTextByKey(lang, "P_WO_SEGMENTCOMPLETEDDATE", "Segment Completed Date");
                    break;
                case 31:
                    category = SystemParams.GetTextByKey(lang, "P_WO_SEGMENTDESCRIPTION", "Segment Description");
                    break;
                case 32:
                    category = SystemParams.GetTextByKey(lang, "P_WO_SEGMENTNOTES", "Segment Notes");
                    break;
                case 33:
                    category = SystemParams.GetTextByKey(lang, "P_WO_SEGMENT", "Segment");
                    break;
                case 34:
                    category = SystemParams.GetTextByKey(lang, "P_WO_ALERTS", "Alerts");
                    break;
                case 35:
                    category = SystemParams.GetTextByKey(lang, "P_WO_SEGMENTTYPE", "Segment Type");
                    break;
                case 36:
                    category = SystemParams.GetTextByKey(lang, "P_WO_SEGMENTBILLABLE", "Segment Billable");
                    break;
                case 37:
                    category = SystemParams.GetTextByKey(lang, "P_WO_COMPONENT", "Component");
                    break;
                case 38:
                    category = SystemParams.GetTextByKey(lang, "P_WO_BILLABLE", "Billable");
                    break;
                case 39:
                    category = SystemParams.GetTextByKey(lang, "P_WO_BILLTOJOB", "Bill to job");
                    break;
                case 40:
                    category = SystemParams.GetTextByKey(lang, "P_WO_WORKORDERATTACHMENT", "Work Order Attachment");
                    break;
                case 41:
                    category = SystemParams.GetTextByKey(lang, "P_WO_ESTIMATEATTACHMENT", "Estimate Attachment");
                    break;
                case 42:
                    category = SystemParams.GetTextByKey(lang, "P_WO_INVOICEATTACHMENT", "Invoice Attachment");
                    break;
                case 43:
                    category = SystemParams.GetTextByKey(lang, "P_WO_COMPANYNAME", "Company Name");
                    break;
                case 44:
                    category = SystemParams.GetTextByKey(lang, "P_WO_ASSET", "Asset");
                    break;
                case 45:
                    category = SystemParams.GetTextByKey(lang, "P_WO_PARTSORDERNUMBER", "Parts Order Number");
                    break;
                case 46:
                    category = SystemParams.GetTextByKey(lang, "P_WO_PARTSSTATUS", "Parts Status");
                    break;
                case 47:
                    category = SystemParams.GetTextByKey(lang, "P_WO_SALESPERSON", "Salesperson");
                    break;
                case 48:
                    category = SystemParams.GetTextByKey(lang, "P_WO_INSPECTIONTEMPLATE", "Inspection Template");
                    break;
                case 97:
                    category = SystemParams.GetTextByKey(lang, "P_WO_HIS_DELETED", "Deleted");
                    break;
                case 98:
                    category = SystemParams.GetTextByKey(lang, "P_WO_HIS_RESTORED", "Restored");
                    break;
                case 99:
                    category = SystemParams.GetTextByKey(lang, "P_WO_HIS_WOLIFECYCLE", "WO Life Cycle");
                    break;
                default:
                    category = SystemParams.GetTextByKey(lang, "P_WO_HIS_OTHER", "Other");
                    break;
            }
        }

        public static byte[] ExportAssetsTimeLine(string lang, string sessionid, string companyid, long[] assetids, DateTime date)
        {
            if (string.IsNullOrEmpty(companyid))
                companyid = SystemParams.CompanyID;

            var events = FleetServiceClientHelper.CreateClient<AssetLocationQueryClient>(companyid, sessionid).GetAssetsOnOffTimeline(companyid, assetids, date);
            var assets = FleetServiceClientHelper.CreateClient<AssetQueryClient>(companyid, sessionid).GetAssetBasicInfo(companyid, assetids, 0);
            List<AssetsOnOffEventInfo> items = new List<AssetsOnOffEventInfo>();
            foreach (var e in events)
            {
                AssetsOnOffEventInfo ei = new AssetsOnOffEventInfo();
                var asset = assets.FirstOrDefault(a => a.ID == e.AssetId);
                if (asset == null)
                    continue;
                ei.DisplayName = asset.DisplayName;
                ei.VIN = asset.VIN;
                ei.MakeName = asset.MakeName;
                ei.ModelName = asset.ModelName;

                ei.AssetId = e.AssetId;
                ei.Events.AddRange(e.Events);
                items.Add(ei);
            }

            ExportToExcel ete = new ExportToExcel();

            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MA_ASSETNAME", "Asset Name"), DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MA_VIN", "VIN/SN"), DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MA_MAKENAME", "Make Name"), DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { ColumnName = SystemParams.GetTextByKey(lang, "P_MA_MODELNAME", "Model Name"), DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { ColumnName = "12AM-1AM", DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { ColumnName = "1AM-2AM", DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { ColumnName = "2AM-3AM", DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { ColumnName = "3AM-4AM", DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { ColumnName = "4AM-5AM", DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { ColumnName = "5AM-6AM", DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { ColumnName = "6AM-7AM", DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { ColumnName = "7AM-8AM", DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { ColumnName = "8AM-9AM", DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { ColumnName = "9AM-10AM", DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { ColumnName = "10AM-11AM", DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { ColumnName = "11AM-12PM", DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { ColumnName = "12PM-1PM", DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { ColumnName = "1PM-2PM", DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { ColumnName = "2PM-3PM", DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { ColumnName = "3PM-4PM", DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { ColumnName = "4PM-5PM", DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { ColumnName = "5PM-6PM", DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { ColumnName = "6PM-7PM", DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { ColumnName = "7PM-8PM", DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { ColumnName = "8PM-9PM", DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { ColumnName = "9PM-10PM", DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { ColumnName = "10PM-11PM", DataType = typeof(object) });
            dt.Columns.Add(new DataColumn() { ColumnName = "11PM-12AM", DataType = typeof(object) });

            int valueIndex = 4;
            var now = FleetServiceClientHelper.CreateClient<Foresight.Fleet.Services.SystemUtil>(sessionid).GetCustomerDateTimeNow(companyid);
            List<double[]> total = new List<double[]>();
            foreach (var it in items.OrderBy(i => i.DisplayName))
            {
                int index = 0;
                var dr = dt.NewRow();
                dr[index] = it.DisplayName;
                dr[++index] = it.VIN;
                dr[++index] = it.MakeName;
                dr[++index] = it.ModelName;

                double[] values = new double[24];
                foreach (var e in it.Events)
                {
                    double startSeconds = e.On?.TimeOfDay.TotalSeconds ?? 0;
                    double endSeconds = 0;
                    if (e.Off != null)
                    {
                        endSeconds = e.Off.Value.TimeOfDay.TotalSeconds;
                    }
                    else
                    {
                        if (now.Date == date.Date && (e.On == null || now > e.On.Value))
                        {
                            endSeconds = now.TimeOfDay.TotalSeconds;
                        }
                        else
                        {
                            // 23:59:59.999
                            endSeconds = 24 * 60 * 60 - .001;
                        }
                    }
                    var start = startSeconds / 3600;
                    var end = endSeconds / 3600;
                    if (endSeconds > startSeconds)
                    {
                        int startHour = (int)Math.Floor(start);
                        int endHour = (int)Math.Ceiling(end);
                        for (var h = startHour; h < endHour; h++)
                        {
                            var hourStartSeconds = h * 3600d;
                            var hourEndSeconds = (h + 1) * 3600d;
                            if (startSeconds > hourStartSeconds)
                            {
                                hourStartSeconds = startSeconds;
                            }
                            if (hourEndSeconds - endSeconds >= 1)
                            {
                                hourEndSeconds = endSeconds;
                            }
                            var totalSeconds = hourEndSeconds - hourStartSeconds;
                            values[h] += totalSeconds;
                        }
                    }
                }

                for (int i = 0; i < values.Length; i++)
                {
                    string text = "";
                    if (values[i] > 0)
                    {
                        if (values[i] >= 3600)
                            text = "01:00:00";
                        else
                        {
                            text = "00:" +
                                Math.Floor(values[i] / 60).ToString().PadLeft(2, '0') + ":" +
                                Math.Round((values[i] % 60)).ToString().PadLeft(2, '0');
                        }
                    }
                    dr[valueIndex + i] = text;
                }
                total.Add(values);
                dt.Rows.Add(dr);
            }
            if (total.Count > 0)
            {
                var drt = dt.NewRow();
                drt[0] = new CExcelCellValue() { Value = SystemParams.GetTextByKey(lang, "P_MA_TOTALCOLON", "Total:") + total.Count, BackgroundColor = System.Drawing.Color.FromArgb(170, 170, 170) };
                drt[1] = new CExcelCellValue() { Value = "", BackgroundColor = System.Drawing.Color.FromArgb(170, 170, 170) };
                drt[2] = new CExcelCellValue() { Value = "", BackgroundColor = System.Drawing.Color.FromArgb(170, 170, 170) };
                drt[3] = new CExcelCellValue() { Value = SystemParams.GetTextByKey(lang, "P_MA_TOTALRUNTIMECOLON", "Total Runtime:"), BackgroundColor = System.Drawing.Color.FromArgb(170, 170, 170) };

                for (int i = 0; i < 24; i++)
                {
                    string text = "";
                    double v = total.Sum(s => s[i]);
                    if (v > 0)
                    {
                        text = Math.Floor(v / 3600).ToString().PadLeft(2, '0') + ":" +
                            Math.Floor((v % 3600) / 60).ToString().PadLeft(2, '0') + ":" +
                            Math.Round(v % 60).ToString().PadLeft(2, '0');

                    }
                    CExcelCellValue ctotal = new CExcelCellValue() { Value = text, BackgroundColor = System.Drawing.Color.FromArgb(170, 170, 170) };
                    drt[valueIndex + i] = ctotal;
                }

                dt.Rows.Add(drt);
            }


            double[] widths = new double[] { 180d, 160d, 100d, 100d, 94d, 94d, 94d, 94d, 94d, 94d, 94d, 94d, 94d, 94d, 94d, 94d, 94d, 94d, 94d, 94d, 94d, 94d, 94d, 94d, 94d, 94d, 94d, 94d };
            byte[] data = ete.CreateExcel(dt, date.ToShortDateString(), widths, null);

            return data;
        }

        private static AlertInfo ConvertAlertObj(AssetAlertGridViewItem item)
        {
            AlertInfo ai = new AlertInfo();
            ai.AlertID = item.ID;
            ai.WorkOrderID = item.WorkOrderId;
            ai.WorkOrderStatus = item.WorkOrderStatus;
            ai.AlertType = item.AlertType;
            ai.AlertTime_UTC = item.LastAlertTime;
            ai.AlertLocalTime = item.AlertLocalTime;
            ai.Completed = item.Completed;
            ai.MachineID = item.AssetID;
            //ai.ModelID = item.ModelName;
            ai.Model = item.ModelName;
            //ai.MakeID = item.MakeName;
            ai.Make = item.MakeName;
            ai.VIN = item.VIN;
            ai.MachineName = item.AssetName;
            ai.EngineHours = item.EngineHours;
            ai.CurrentHours = item.CurrentEngineHours;
            ai.Description = item.Description;
            ai.Description = ai.FormatDescription(ai.Description);
            //ai.ServiceDescription = item.ServiceDescription;
            ai.RepeatedAlerts = item.RepeatedAlerts;
            ai.AlertCount = item.RepeatedAlerts.Count + 1;
            ai.OpenWorkOrderCount = item.OpenWorkOrderCount;

            return ai;
        }
        private static AlertInfo ConvertAlertObj2(AcknowledgedAlertItem item)
        {
            AlertInfo ai = new AlertInfo();
            ai.AlertID = item.ID;
            ai.WorkOrderID = item.WorkOrderId;
            ai.AlertType = item.AlertType;
            ai.AlertTime_UTC = item.LastAlertTime;
            ai.AlertLocalTime = item.AlertLocalTime;
            ai.MachineID = item.AssetID;
            ai.Model = item.ModelName;
            ai.Make = item.MakeName;
            ai.VIN = item.VIN;
            ai.MachineName = item.AssetName;
            ai.EngineHours = item.EngineHours;
            ai.Description = item.Description;
            ai.Description = ai.FormatDescription(ai.Description);
            ai.RepeatedAlerts = item.RepeatedAlerts;
            ai.AlertCount = item.RepeatedAlerts.Count + 1;
            ai.OpenWorkOrderCount = item.OpenWorkOrderCount;
            ai.AcknowledgedByName = item.AcknowledgedBy;
            ai.AcknowledgedTime_UTC = item.AcknowledgedTime;
            ai.AcknowledgedTime_Local = item.AcknowledgedLocalTime;
            ai.AcknowledgedComment = item.AcknowledgedComment;

            return ai;
        }

        private static object OrderHandler(object obj, string sortPath)
        {
            Type type = obj.GetType();
            System.Reflection.PropertyInfo propertyInfo = type.GetProperty(sortPath);
            if (propertyInfo != null)
                return propertyInfo.GetValue(obj, null);
            return null;
        }

    }

    public class LayoutColumn
    {
        public string ColumnKey { get; set; }
        public int Width { get; set; }
        public int Sort { get; set; }
        public bool Visible { get; set; } = true;
        public string Caption { get; set; }
    }
    public class JobSiteRequirementQueryItem
    {
        public string LatestStartDate { get; set; }
        public long[] JobSites { get; set; }
        public string[] Regions { get; set; }
        public string SearchText { get; set; }
        public bool UnScheduledOnly { get; set; }
    }
    public class JobSiteRequirmentItem : JobSiteRequirmentInfo
    {
        public string BeginDateStr { get { return BeginDate == null ? "" : BeginDate.ToString("M/d/yyyy"); } }
        public string EndDateStr { get { return EndDate == null ? "" : EndDate.ToString("M/d/yyyy"); } }
    }
    public class WorkOrderQueryParams
    {
        public long AssetID { get; set; }
        public long WorkOrderID { get; set; }
        public string SearchText { get; set; }
        public string[] Contacts { get; set; }
        public string[] Statuses { get; set; }
        public string[] AssetGroups { get; set; }
        public bool ShowMaintenance { get; set; }
        public int Completed { get; set; }
        public string[] Locations { get; set; }
        public string[] Departments { get; set; }
        public string[] Advisors { get; set; }
        public string[] OrderTypes { get; set; }
    }
    public class AssetInspectInfo : AssetInspectItem
    {
        public string CommitTimeStr { get { return CommitTime == DateTime.MinValue ? "" : CommitTime.ToString(("M/d/yyyy h:mm tt")); } }
        public string CommitTimeLocalStr { get { return CommitTimeLocal == DateTime.MinValue ? "" : CommitTimeLocal.ToString(("M/d/yy h:mm tt")); } }
        public string LastUpdatedTimeLocalStr { get { return LastUpdatedTime.Year <= 1900 ? "" : LastUpdatedTimeLocal.ToString(("M/d/yyyy h:mm tt")); } }
        public WorkOrderListItem[] WorkOrders { get; set; }
    }
    public class AssetsOnOffEventInfo : AssetsOnOffEvent
    {
        public string VIN { get; set; }
        public string DisplayName { get; set; }
        public string MakeName { get; set; }
        public string ModelName { get; set; }
    }

    public class AlertMappingClient : AlertMappingItem
    {
        public string Source { get; set; }
        public string SPN { get; set; }
        public string FMI { get; set; }
        public string Description { get; set; }
        public string EnhancedDescription { get; set; }
        public string MakeName { get; set; }
        public string ModelNames { get; set; }
    }
}
