using Dapper;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using XYY.Common.Standard;
using XYY.Model.Standard.Finance;
using XYY.Data.Standard.Finance;
using Microsoft.Extensions.Caching.Distributed;
using XYY.Core.Standard.ExcelHelper.MSExcelHelper;
using Microsoft.Office.Interop.Excel;
using System.Reflection;
using XYY.Model.Standard;
using XYY.Service.Standard.Finance.Charging.CustomerOrderFee;
using XYY.Service.Standard.Finance.MappingModel;
using XYY.Service.Standard.Finance.Model;
using System.Text;

namespace XYY.Service.Standard.Finance
{
    public class FinanceOrderChargesGroup
    {
        public string Key
        {
            get; set;
        }

        public decimal 收入
        {
            get; set;
        }

        public decimal 成本
        {
            get; set;
        }

        public int 收货单量
        {
            get; set;
        }

        public int 收货重量
        {
            get; set;
        }

        public decimal 毛利
        {
            get; set;
        }
    }
    public interface ILadingBillService
    {

        Task<List<LoadingBatchInputDto>> ConvertLoadingBatchInputDto(byte[] data, FinanceIncidentalTypeEnum feeType);

        Task<List<Finance_IncidentalType>> CacheGetIncidentalTypes();
        Task<int> CreateBill(Finance_Logistics_LadingBill ladingBill);
        Task<byte[]> GetBillsDetails(int channelId, int customerId, DateTime start, DateTime end, SettlementCompany? SettlementCompany);
        Task<Dictionary<int, int>> GetGroupCounts();
        Task<List<Finance_Incidental>> GetIncidentals(int billId, int type);
        Task<View_Finance_Logistics_LadingBill> GetInfo(string billNumber);
        Task<List<Finance_Logistics_LadingBillLog>> GetLadingBillLogs(int BillId, FinanceIncidentalTypeEnum typeId);
        Task<List<View_FinanceBill2>> GetView_FinanceBills(int channelId, int customerId, DateTime start, DateTime end, SettlementCompany? SettlementCompany);
        Task<byte[]> OutBill(int billdId, int type);
        Task PostPayment(int Id, decimal PostPaymentFee, FinanceIncidentalTypeEnum feeType, string remark);
        Task<PageResult<View_Finance_Logistics_LadingBill>> QueryPager(QueryModel queryModel);
        Task<bool> Review(string billNumber, bool pass = true);
        Task<int> StartClare(string BillNumber, string url, decimal ClareFee, string ClareCurreny, int BoxQty, decimal Weight, int Pieces);
        Task StartFrist(FinanceLadingBillDto dto);
        Task<int> StartFrist(string BillNumber, string url, decimal FristFee);
        Task Update(FinanceLadingBillDto bill);

        Task RefreshIncidentalTypesCache();

        Task<PageResult<View_Finance_Logistics_LadingBill>> GetData(QueryModel queryModel);
        Task DeleteBill(int billId);
        Task<List<EFFinanceBill>> GetEFFinanceBillGroup(DateTime start, DateTime end, int channelId, int customerId);
        Task<List<EFFinanceGroupBill>> GetEFFinanceBillGroupAsChannel(DateTime start, DateTime end);
        Task<List<EFFinanceGroupBill>> GetEFFinanceBillGroupAsCustomer(DateTime start, DateTime end);
        Task<byte[]> GetEFFinanceBillDetails(DateTime start, DateTime end, int channelId, int customerId);


        Task<List<EFFinanceBill>> GetFinanceBillGroup(DateTime start, DateTime end, int channelId, int customerId);
        Task<List<EFFinanceGroupBill>> GetFinanceBillGroupAsChannel(DateTime start, DateTime end);
        Task<List<EFFinanceGroupBill>> GetFinanceBillGroupAsCustomer(DateTime start, DateTime end);
        Task<byte[]> GetFinanceBillDetails(DateTime start, DateTime end, int channelId, int customerId);
        Task<byte[]> DownFinanceReport(SearchFinanceReportParam param);
        Task<byte[]> DownFinanceBranchProfitReport(SearchFinanceReportParam param);

        Task<PageResult<View_FinanceBill_WithBranchCompany>> QueryFinanceReport(QueryModel queryModel);

        Task<List<CompletionRate>> GetCompletionRate(DateTime start, DateTime end, int channelId, int customerId);
        Task<FinanceBillDetailWeightDifferenceGroup> GetFinanceBillDetailWeightDifferenceGroup(DateTime startDate, DateTime endDate, int channelId, int customerId);
        Task<byte[]> OutFinanceBillDetailWeightDifferenceDetails(DateTime startDate, DateTime endDate, int channelId, int customerId);
        Task<bool> PassRemittanceForFirstBill(int CustomerId, IEnumerable<Finance_CustomerDeliveryBill> billList);

        Task<byte[]> OutFinanceBillCustomerMonitoring(QueryModel queryModel);
        Task<List<FinanceOrderChargesGroup>> GetIncidentalGroupData(QueryModel queryModel);
        Task<Dictionary<int, string>> GetIncidentalGroup();
    }

    public class LadingBillService : ILadingBillService
    {
        IFinance_Logistics_LadingBillRepository _billRepository;
        IFinance_OrderCostRepository _orderCostRepository;
        IFinance_IncidentalRepository _financeIncidentalRepository;
        IFinanceIncidentalTypeRepository _incidentalTypeRepository;
        IExcelHelper _excel;
        IDistributedCache _cache;
        ICustomerladingBillFeeService _customerladingBillFeeService;
        XYY.Core.Standard.Data.Infrastructure.IUnitOfWork _unitOfWork;
        public LadingBillService(IFinance_Logistics_LadingBillRepository billRepository,
            IFinance_IncidentalRepository financeIncidentalRepository,
            IFinanceIncidentalTypeRepository incidentalTypeRepository,
            IFinance_OrderCostRepository orderCostRepository,
            IExcelHelper excel,
            IDistributedCache cache,
            ICustomerladingBillFeeService customerladingBillFeeService
,
            Core.Standard.Data.Infrastructure.IUnitOfWork unitOfWork)
        {
            _billRepository = billRepository;
            _financeIncidentalRepository = financeIncidentalRepository;
            _incidentalTypeRepository = incidentalTypeRepository;
            _orderCostRepository = orderCostRepository;
            _excel = excel;
            _cache = cache;
            _customerladingBillFeeService = customerladingBillFeeService;
            _unitOfWork = unitOfWork;
        }

        public LadingBillService()
        {
        }

        public async Task<PageResult<View_Finance_Logistics_LadingBill>> GetData(QueryModel queryModel)
        {
            var data = await _billRepository.GetData(queryModel);
            //data.ForEach(x => x.CustomerName = customers.FirstOrDefault(y => y.Id == x.CustomerId)?.CompanyName);
            return data;
        }
        public async Task<byte[]> OutBill(int billdId, int type)
        {
            //return null;
            var bill = await _billRepository.GetAsync(billdId);
            var inciedentals = await GetIncidentals(billdId, type);
            var types = await CacheGetIncidentalTypes();
            string serviceName = "";
            if (type == 1)
            {
                serviceName = bill.FristServiceName + "头程帐单";
            }
            else if (type == 2)
            {
                serviceName = bill.DomesticClearServiceName + "国内清关帐单";
            }
            else if (type == 3)
            {
                serviceName = bill.OverseasClearServiceName + "国外清关帐单";
            }
            else if (type == 4)
            {
                serviceName = bill.CustomerName + "收款";
            }

            HSSFWorkbook excelBook = new HSSFWorkbook();
            ISheet sheet = excelBook.CreateSheet("Sheet1");
            IRow header = sheet.CreateRow(0);
            CellRangeAddress region = new CellRangeAddress(0, 0, 0, 4);
            sheet.AddMergedRegion(region);
            header.CreateCell(0).SetCellValue(serviceName);
            ICellStyle headStyle = excelBook.CreateCellStyle();
            headStyle.Alignment = HorizontalAlignment.Center;
            headStyle.BorderBottom = BorderStyle.Thin;
            headStyle.BorderTop = BorderStyle.Thin;
            headStyle.BorderLeft = BorderStyle.Thin;
            headStyle.BorderRight = BorderStyle.Thin;
            ((HSSFSheet)sheet).SetEnclosedBorderOfRegion(region, BorderStyle.Thin, NPOI.HSSF.Util.HSSFColor.Black.Index);

            headStyle.VerticalAlignment = VerticalAlignment.Center;
            NPOI.SS.UserModel.IFont headFont = excelBook.CreateFont();
            headFont.FontHeightInPoints = 14;
            headFont.Boldweight = (short)FontBoldWeight.Bold;
            headStyle.SetFont(headFont);
            header.GetCell(0).CellStyle = headStyle;
            header.Height = 200 * 3;



            ICellStyle styleCommonBottom = excelBook.CreateCellStyle();
            NPOI.SS.UserModel.IFont headFont2 = excelBook.CreateFont();
            headFont.FontHeightInPoints = 16;
            headFont.Boldweight = (short)FontBoldWeight.Bold;
            styleCommonBottom.SetFont(headFont);


            ICellStyle styleCommonLeft = excelBook.CreateCellStyle();
            styleCommonLeft.Alignment = HorizontalAlignment.Left;
            styleCommonLeft.WrapText = true;
            styleCommonLeft.VerticalAlignment = VerticalAlignment.Center;
            styleCommonLeft.BorderBottom = BorderStyle.Thin;
            styleCommonLeft.BorderTop = BorderStyle.Thin;
            styleCommonLeft.BorderLeft = BorderStyle.Thin;
            styleCommonLeft.BorderRight = BorderStyle.Thin;

            ICellStyle styleCommonCenter = excelBook.CreateCellStyle();
            styleCommonCenter.Alignment = HorizontalAlignment.Center;
            styleCommonCenter.WrapText = true;
            styleCommonCenter.VerticalAlignment = VerticalAlignment.Center;
            styleCommonCenter.BorderBottom = BorderStyle.Thin;
            styleCommonCenter.BorderTop = BorderStyle.Thin;
            styleCommonCenter.BorderLeft = BorderStyle.Thin;
            styleCommonCenter.BorderRight = BorderStyle.Thin;

            IRow r2 = sheet.CreateRow(1);
            r2.CreateCell(0).SetCellValue("日期");
            if (type != 4)
                r2.CreateCell(1).SetCellValue(bill.CreateTime.Value.ToString("yyyy-MM-dd"));
            else
                r2.CreateCell(1).SetCellValue(bill.CustomerBillTime.HasValue ? bill.CustomerBillTime.Value.ToString("yyyy-MM-dd") : "");
            r2.CreateCell(2).SetCellValue("MAWB NO(单号)");
            r2.CreateCell(3).SetCellValue(bill.BillNumber);


            CellRangeAddress region2 = new CellRangeAddress(1, 1, 3, 4);
            sheet.AddMergedRegion(region2);
            ((HSSFSheet)sheet).SetEnclosedBorderOfRegion(region2, BorderStyle.Thin, NPOI.HSSF.Util.HSSFColor.Black.Index);

            IRow r3 = sheet.CreateRow(2);
            r3.CreateCell(0).SetCellValue("PIECE(件数)");
            r3.CreateCell(1).SetCellValue(bill.BoxQty);
            r3.CreateCell(2).SetCellValue("WEIGHT (重量)");
            r3.CreateCell(3).SetCellValue((double)bill.Weight);
            CellRangeAddress region3 = new CellRangeAddress(2, 2, 3, 4);
            sheet.AddMergedRegion(region3);
            ((HSSFSheet)sheet).SetEnclosedBorderOfRegion(region3, BorderStyle.Thin, NPOI.HSSF.Util.HSSFColor.Black.Index);

            IRow r4 = sheet.CreateRow(3);
            r4.CreateCell(0).SetCellValue("Departure(始发站)");
            r4.CreateCell(1).SetCellValue(bill.Departure);
            r4.CreateCell(2).SetCellValue("Destination (目的站)");
            r4.CreateCell(3).SetCellValue(bill._Destination);
            CellRangeAddress region4 = new CellRangeAddress(3, 3, 3, 4);
            sheet.AddMergedRegion(region4);
            ((HSSFSheet)sheet).SetEnclosedBorderOfRegion(region4, BorderStyle.Thin, NPOI.HSSF.Util.HSSFColor.Black.Index);



            IRow r5 = sheet.CreateRow(4);
            r5.CreateCell(0).SetCellValue("费用项目");
            r5.CreateCell(1).SetCellValue("重量/票数");
            r5.CreateCell(2).SetCellValue("币制");
            r5.CreateCell(3).SetCellValue("单价");
            r5.CreateCell(4).SetCellValue("金额");

            for (var i = 0; i < inciedentals.Count; i++)
            {
                var inciedental = inciedentals[i];
                IRow r = sheet.CreateRow(i + 5);
                var t = types.First(x => x.Id == inciedentals[i].IncidentalType);
                string name = t.Name;
                r.CreateCell(0).SetCellValue(name);
                if (t.CalculationMethod == CalculationMethodEnum.固定)
                {
                    r.CreateCell(1).SetCellValue(1);
                }
                else if (t.CalculationMethod == CalculationMethodEnum.按KG数)
                {
                    r.CreateCell(1).SetCellValue(bill.Weight + "KG");
                }
                else
                {
                    r.CreateCell(1).SetCellValue(bill.Pieces + "票");
                }
                if (type == 1 || type == 2 || type == 4)
                {
                    r.CreateCell(2).SetCellValue("RMB");
                }
                else
                {
                    r.CreateCell(2).SetCellValue(bill.OverseasClearCurreny);
                }

                r.CreateCell(3).SetCellValue((double)inciedental.IncidentalFee);


                if (t.CalculationMethod == CalculationMethodEnum.固定)
                {
                    r.CreateCell(4).SetCellValue((double)inciedental.IncidentalFee);
                }
                else if (t.CalculationMethod == CalculationMethodEnum.按KG数)
                {
                    r.CreateCell(4).SetCellValue((double)bill.Weight * (double)inciedental.IncidentalFee);
                }
                else
                {
                    r.CreateCell(4).SetCellValue((double)bill.Pieces * (double)inciedental.IncidentalFee);
                }
            }
            IRow rb = sheet.CreateRow(inciedentals.Count + 5);
            rb.CreateCell(0).SetCellValue("合计（TOTAL）");
            rb.CreateCell(1).SetCellValue("");
            rb.CreateCell(2).SetCellValue("");
            rb.CreateCell(3).SetCellValue("");
            if (type == 1)
            {
                rb.CreateCell(4).SetCellValue((double)bill.FristFee);
            }
            else if (type == 2)
            {
                rb.CreateCell(4).SetCellValue((double)bill.DomesticClearFee);
            }
            else if (type == 3)
            {
                rb.CreateCell(4).SetCellValue((double)bill.OverseasClearFee);
            }
            else if (type == 4)
            {
                rb.CreateCell(4).SetCellValue((double)bill.CusetomerFee);
            }

            for (int i = 1; i < inciedentals.Count + 6; i++)
            {
                sheet.GetRow(i).Height = 200 * 3;
                sheet.GetRow(i).GetCell(0).CellStyle = styleCommonLeft;
                sheet.GetRow(i).GetCell(1).CellStyle = styleCommonCenter;
                if (i > 3)
                    sheet.GetRow(i).GetCell(2).CellStyle = styleCommonCenter;
                else
                    sheet.GetRow(i).GetCell(2).CellStyle = styleCommonLeft;
                sheet.GetRow(i).GetCell(3).CellStyle = styleCommonCenter;
                if (i > 3)
                    sheet.GetRow(i).GetCell(4).CellStyle = styleCommonCenter;
            }
            sheet.SetColumnWidth(0, 30 * 256);
            sheet.SetColumnWidth(1, 15 * 256);
            sheet.SetColumnWidth(2, 22 * 256);
            sheet.SetColumnWidth(3, 15 * 256);
            sheet.SetColumnWidth(4, 15 * 256);


            CellRangeAddress region5 = new CellRangeAddress(inciedentals.Count + 5, inciedentals.Count + 5, 1, 3);
            sheet.AddMergedRegion(region5);
            ((HSSFSheet)sheet).SetEnclosedBorderOfRegion(region5, BorderStyle.Thin, NPOI.HSSF.Util.HSSFColor.Black.Index);


            if (type == 4)
            {
                IRow bottom11 = sheet.CreateRow(inciedentals.Count + 6);
                bottom11.CreateCell(0).SetCellValue("");
                bottom11.RowStyle = styleCommonBottom;
                bottom11.Height = 200 * 3;

                string companyName = bill.DataBindRole == "头程-朗天" ? "广州朗天供应链有限公司" : "广州行运易国际供应链有限公司";

                IRow bottom1 = sheet.CreateRow(inciedentals.Count + 7);
                bottom1.CreateCell(0).SetCellValue("公司：");
                bottom1.CreateCell(1).SetCellValue(companyName);
                bottom1.RowStyle = styleCommonBottom;
                bottom1.Height = 200 * 3;

                IRow bottom = sheet.CreateRow(inciedentals.Count + 8);
                bottom.CreateCell(0).SetCellValue("");
                bottom.RowStyle = styleCommonBottom;
                bottom.Height = 200 * 3;


                IRow bottom2 = sheet.CreateRow(inciedentals.Count + 9);
                bottom2.CreateCell(0).SetCellValue("公户收款信息：");
                bottom2.RowStyle = styleCommonBottom;
                bottom2.Height = 200 * 3;

                if (companyName == "广州朗天供应链有限公司")
                {

                    IRow bottom3 = sheet.CreateRow(inciedentals.Count + 10);
                    bottom3.CreateCell(0).SetCellValue("名称：");
                    bottom3.CreateCell(1).SetCellValue("广州朗天供应链有限公司");
                    bottom3.RowStyle = styleCommonBottom;
                    bottom3.Height = 200 * 3;

                    IRow bottom4 = sheet.CreateRow(inciedentals.Count + 11);
                    bottom4.CreateCell(0).SetCellValue("开户行：");
                    bottom4.CreateCell(1).SetCellValue("中国农业银行股份有限公司广州竹料支行");
                    bottom4.RowStyle = styleCommonBottom;
                    bottom4.Height = 200 * 3;


                    IRow bottom5 = sheet.CreateRow(inciedentals.Count + 12);
                    bottom5.CreateCell(0).SetCellValue("银行账户：");
                    bottom5.CreateCell(1).SetCellValue("44069101040015327");
                    bottom5.RowStyle = styleCommonBottom;
                    bottom5.Height = 200 * 3;


                    IRow bottom6 = sheet.CreateRow(inciedentals.Count + 13);
                    bottom6.CreateCell(0).SetCellValue("");
                    bottom6.RowStyle = styleCommonBottom;
                    bottom6.Height = 200 * 3;

                    IRow bottom7 = sheet.CreateRow(inciedentals.Count + 14);
                    bottom7.CreateCell(0).SetCellValue("私户收款信息：");
                    bottom7.RowStyle = styleCommonBottom;
                    bottom7.Height = 200 * 3;

                    IRow bottom8 = sheet.CreateRow(inciedentals.Count + 15);
                    bottom8.CreateCell(0).SetCellValue("");
                    bottom8.RowStyle = styleCommonBottom;
                    bottom8.Height = 200 * 3;

                    IRow bottom9 = sheet.CreateRow(inciedentals.Count + 16);
                    bottom9.CreateCell(0).SetCellValue("户名：");
                    bottom9.CreateCell(1).SetCellValue("罗建新");
                    bottom9.RowStyle = styleCommonBottom;
                    bottom9.Height = 200 * 3;

                    IRow bottom10 = sheet.CreateRow(inciedentals.Count + 17);
                    bottom10.CreateCell(0).SetCellValue("开户行：");
                    bottom10.CreateCell(1).SetCellValue("中国工商银行广州花都四季支行");
                    bottom10.RowStyle = styleCommonBottom;
                    bottom10.Height = 200 * 3;


                    IRow bottom12 = sheet.CreateRow(inciedentals.Count + 18);
                    bottom12.CreateCell(0).SetCellValue("银行账号：");
                    bottom12.CreateCell(1).SetCellValue("6212253602010176776");
                    bottom12.RowStyle = styleCommonBottom;
                    bottom12.Height = 200 * 3;
                }
                else
                {
                    IRow bottom3 = sheet.CreateRow(inciedentals.Count + 10);
                    bottom3.CreateCell(0).SetCellValue("名称：");
                    bottom3.CreateCell(1).SetCellValue("广州行运易国际供应链有限公司");
                    bottom3.RowStyle = styleCommonBottom;
                    bottom3.Height = 200 * 3;

                    IRow bottom4 = sheet.CreateRow(inciedentals.Count + 11);
                    bottom4.CreateCell(0).SetCellValue("开户行：");
                    bottom4.CreateCell(1).SetCellValue("中国建设银行股份有限公司广州五羊新城支行");
                    bottom4.RowStyle = styleCommonBottom;
                    bottom4.Height = 200 * 3;

                    IRow bottom5 = sheet.CreateRow(inciedentals.Count + 12);
                    bottom5.CreateCell(0).SetCellValue("银行账户：");
                    bottom5.CreateCell(1).SetCellValue("44050140090500000537");
                    bottom5.RowStyle = styleCommonBottom;
                    bottom5.Height = 200 * 3;

                }
            }
            var ms = new System.IO.MemoryStream();
            excelBook.Write(ms);
            ms.Flush();
            excelBook = null;
            return ms.ToArray();
        }

        public async Task<int> CreateBill(Finance_Logistics_LadingBill ladingBill)
        {
            return (int)(await _billRepository.InsertAsync(ladingBill));
        }



        public async Task<Dictionary<int, int>> GetGroupCounts()
        {
            return await _billRepository.GetGroupCounts();
        }

        public async Task<View_Finance_Logistics_LadingBill> GetInfo(string billNumber)
        {
            return await _billRepository.GetInfo(billNumber);
        }

        public async Task<PageResult<View_Finance_Logistics_LadingBill>> QueryPager(QueryModel queryModel)
        {
            return await _billRepository.QueryPager(queryModel);
        }



        public async Task<bool> Review(string billNumber, bool pass = true)
        {
            return true;
        }
        public async Task Update(FinanceLadingBillDto bill)
        {
            //清理旧的杂费项目
            string sql = $"update a set a.IsDeleted = 1 from Finance_Incidental(nolock) a join Finance_IncidentalType(nolock) b on a.IncidentalType = b.Id where b.FeeType={bill.Type.GetValue()} and a.LadingBillId = {bill.Id}";
            await _incidentalTypeRepository.ExecuteSqlAsync(sql, null);

            var feeSum = await AddIncidentals(bill.Id, bill.IncidentalFees, bill.Weight, bill.Pieces);
            string curreny = string.Empty;
            #region 更新检查
            //填写新的杂费项目
            if (bill.Type == FinanceIncidentalTypeEnum.头程杂费)
            {
                if (bill.PaymentFristFee > 0)
                    throw new Exception("已支付头程运费后，无法再调整费用明细");
                bill.FristFee = feeSum;
            }
            else if (bill.Type == FinanceIncidentalTypeEnum.国内清关杂费)
            {
                if (bill.PaymentDomesticClearFee > 0)
                    throw new Exception("已支付国内清关杂费后，无法再调整费用明细");
                bill.DomesticClearFee = feeSum;
            }
            else if (bill.Type == FinanceIncidentalTypeEnum.国外清关杂费)
            {
                if (bill.PaymentOverseasClearFee > 0)
                    throw new Exception("已支付国外清关杂费后，无法再调整费用明细");
                bill.OverseasClearFee = feeSum;
                curreny = bill.OverseasClearCurreny;
            }
            else if (bill.Type == FinanceIncidentalTypeEnum.收款)
            {
                bill.CusetomerFee = feeSum;
            }
            else if (bill.Type == FinanceIncidentalTypeEnum.一级中转)
            {
                if (bill.PaymentFirstTransferFee > 0)
                    throw new Exception("已支付一级中转费后，无法再调整费用明细");
                bill.FirstTransferFee = feeSum;
            }
            else if (bill.Type == FinanceIncidentalTypeEnum.二级中转)
            {
                if (bill.PaymentSecondTransferFee > 0)
                    throw new Exception("已支付二级中转费后，无法再调整费用明细");
                bill.SecondTransferFee = feeSum;
            }
            else if (bill.Type == FinanceIncidentalTypeEnum.关税成本)
            {
                if (bill.PaymentTaxFee > 0)
                    throw new Exception("已支付关税后，无法再调整费用明细");
                bill.TaxFee = feeSum;
                curreny = bill.TaxFeeCurrency;
            }
            else if (bill.Type == FinanceIncidentalTypeEnum.海外中转)
            {
                if (bill.PaymentOverseaTransferFee > 0)
                    throw new Exception("已支付海外中转费后，无法再调整费用明细");
                bill.OverSeaTransferFee = feeSum;
                curreny = bill.OverSeaTransferFeeCurrency;
            }
            else if (bill.Type == FinanceIncidentalTypeEnum.补贴)
            {
                if (bill.PaymentSubsidy > 0)
                    throw new Exception("已收取补贴后，无法再调整费用明细");
                bill.SubsidyFee = feeSum;
                curreny = bill.SubsidyCurrency;
            }
            #endregion

            await _billRepository.UpdateAsync(bill);

            string ladingBillNumber = bill.BillNumber;
            //计算订单均摊成本
            await _orderCostRepository.UpdateOrderCost(ladingBillNumber, feeSum, bill.Type, curreny);
            //进行扣费处理
            await _customerladingBillFeeService.Charges(bill);
        }


        public async Task<int> StartClare(string BillNumber, string url, decimal ClareFee, string ClareCurreny, int BoxQty, decimal Weight, int Pieces)
        {
            var bill = (await _billRepository.QueryAsync(x => x.BillNumber == BillNumber)).First();
            bill.DomesticClearFee = ClareFee;
            bill.OverseasClearCurreny = ClareCurreny;

            bill.DomesticClearFileUrl = url;
            await _billRepository.UpdateAsync(bill);
            return bill.Id;
            //}
        }

        /// <summary>
        /// 开始头程核对
        /// </summary>
        /// <param name="BillNumber">提单号</param>
        /// <param name="file">文件</param>
        /// <param name="FristFee">头程费用</param>
        /// <returns></returns>
        public async Task<int> StartFrist(string BillNumber, string url, decimal FristFee)
        {
            if (await _billRepository.IsExistsAsync(x => x.BillNumber == BillNumber))
            {
                throw new Exception("已存在提单帐单" + BillNumber + "不允许创建新的提单帐单");
            }

            return await CreateBill(new Finance_Logistics_LadingBill { BillNumber = BillNumber, FristFee = FristFee, FristFileUrl = url });
        }

        public async Task<List<View_FinanceBill2>> GetView_FinanceBills(int channelId, int customerId, DateTime start, DateTime end, SettlementCompany? SettlementCompany)
        {
            return await _billRepository.GetView_FinanceBills(channelId, customerId, start, end, SettlementCompany);
        }

        public async Task PostPayment(int Id, decimal PostPaymentFee, FinanceIncidentalTypeEnum feeType, string remark)
        {
            var bill = await _billRepository.GetAsync(Id);
            if (feeType == FinanceIncidentalTypeEnum.头程杂费)
            {
                if (bill.PaymentFristFee + PostPaymentFee > bill.FristFee)
                    throw new Exception("付款金额不可大于应付金额");
                bill.PaymentFristFee += PostPaymentFee;

                if (bill.PaymentFristFee == bill.FristFee)
                    bill.PaymentFristFeeStatus = PaymentStatus.结款结束;
                else
                    bill.PaymentFristFeeStatus = PaymentStatus.结款中;
            }
            else if (feeType == FinanceIncidentalTypeEnum.国内清关杂费)
            {
                if (bill.PaymentDomesticClearFee + PostPaymentFee > bill.DomesticClearFee)
                    throw new Exception("付款金额不可大于应付金额");
                bill.PaymentDomesticClearFee += PostPaymentFee;

                if (bill.PaymentDomesticClearFee == bill.DomesticClearFee)
                    bill.PaymentDomesticClearFeeStatus = PaymentStatus.结款结束;
                else
                    bill.PaymentDomesticClearFeeStatus = PaymentStatus.结款中;
            }
            else if (feeType == FinanceIncidentalTypeEnum.国外清关杂费)
            {
                if (bill.PaymentOverseasClearFee + PostPaymentFee > bill.OverseasClearFee)
                    throw new Exception("付款金额不可大于应付金额");
                bill.PaymentOverseasClearFee += PostPaymentFee;

                if (bill.PaymentOverseasClearFee == bill.OverseasClearFee)
                    bill.PaymentOverseasClearFeeStatus = PaymentStatus.结款结束;
                else
                    bill.PaymentOverseasClearFeeStatus = PaymentStatus.结款中;
            }
            else if (feeType == FinanceIncidentalTypeEnum.收款)
            {
                if (bill.CusetomerCheques + PostPaymentFee > bill.CusetomerFee)
                    throw new Exception("付款金额不可大于应付金额");
                bill.CusetomerCheques += PostPaymentFee;

                if (bill.CusetomerCheques == bill.CusetomerFee)
                    bill.CusetomerChequesStatus = PaymentStatus.结款结束;
                else
                    bill.CusetomerChequesStatus = PaymentStatus.结款中;
            }
            else if (feeType == FinanceIncidentalTypeEnum.一级中转)
            {
                if (bill.PaymentFirstTransferFee + PostPaymentFee > bill.FirstTransferFee)
                    throw new Exception("付款金额不可大于应付金额");
                bill.PaymentFirstTransferFee += PostPaymentFee;

                if (bill.PaymentFirstTransferFee == bill.FirstTransferFee)
                    bill.PaymentFirstTransferStatus = PaymentStatus.结款结束;
                else
                    bill.PaymentFirstTransferStatus = PaymentStatus.结款中;
            }
            else if (feeType == FinanceIncidentalTypeEnum.二级中转)
            {
                if (bill.PaymentSecondTransferFee + PostPaymentFee > bill.SecondTransferFee)
                    throw new Exception("付款金额不可大于应付金额");
                bill.PaymentSecondTransferFee += PostPaymentFee;

                if (bill.PaymentSecondTransferFee == bill.SecondTransferFee)
                    bill.PaymentSecondTransferStatus = PaymentStatus.结款结束;
                else
                    bill.PaymentSecondTransferStatus = PaymentStatus.结款中;
            }
            else if (feeType == FinanceIncidentalTypeEnum.关税成本)
            {
                if (bill.PaymentTaxFee + PostPaymentFee > bill.TaxFee)
                    throw new Exception("付款金额不可大于应付金额");
                bill.PaymentTaxFee += PostPaymentFee;

                if (bill.PaymentTaxFee == bill.FirstTransferFee)
                    bill.PaymentTaxStatus = PaymentStatus.结款结束;
                else
                    bill.PaymentTaxStatus = PaymentStatus.结款中;
            }
            else if (feeType == FinanceIncidentalTypeEnum.海外中转)
            {
                if (bill.PaymentOverseaTransferFee + PostPaymentFee > bill.OverSeaTransferFee)
                    throw new Exception("付款金额不可大于应付金额");
                bill.PaymentOverseaTransferFee += PostPaymentFee;

                if (bill.PaymentOverseaTransferFee == bill.FirstTransferFee)
                    bill.PaymentOverSeaTransferStatus = PaymentStatus.结款结束;
                else
                    bill.PaymentOverSeaTransferStatus = PaymentStatus.结款中;
            }
            else if (feeType == FinanceIncidentalTypeEnum.补贴)
            {

                bill.PaymentSubsidy += PostPaymentFee;

                if (bill.PaymentSubsidy >= bill.FirstTransferFee)
                    bill.PaymentSubsidyStatus = PaymentStatus.结款结束;
                else
                    bill.PaymentSubsidyStatus = PaymentStatus.结款中;
            }
            if (!string.IsNullOrEmpty(remark))
            {
                bill.Remark = remark;
            }
            await _billRepository.UpdateAsync(bill);
        }

        public async Task<List<Finance_Logistics_LadingBillLog>> GetLadingBillLogs(int BillId, FinanceIncidentalTypeEnum typeId)
        {
            var list = await _billRepository.GetLadingBillLogs(BillId, typeId);
            return list;
        }

        readonly string tempPath = AppContext.BaseDirectory + "\\temp";
        public async Task<byte[]> GetBillsDetails(int channelId, int customerId, DateTime start, DateTime end, SettlementCompany? SettlementCompany)
        {
            var list = await _billRepository.GetBillsDetails(channelId, customerId, start, end, SettlementCompany);

            var data = _excel.OutDataAsByte<OutDataInfo, View_FinanceBill2>(list);
            return data;
        }

        public string IncidentalTypesKey => "ALL-IncidentalType";

        public async Task<List<Finance_IncidentalType>> CacheGetIncidentalTypes()
        {
            //全局缓存失效触发器（每个缓存方法中都应该添加） 
            return await _cache.GetAsync<List<Finance_IncidentalType>>(IncidentalTypesKey,
                 async () =>
                {
                    return (await _incidentalTypeRepository.QueryAsync()).ToList();
                });
        }

        public async Task RefreshIncidentalTypesCache()
        {
            await _cache.RemoveAsync(IncidentalTypesKey);
        }

        async Task<decimal> AddIncidentals(int id, List<Finance_Incidental> IncidentalFees, decimal Weight, int Pieces)
        {
            decimal sumIncidentalFee = 0;
            var types = await CacheGetIncidentalTypes();
            foreach (var incidentalFee in IncidentalFees)
            {
                var t = types.First(x => x.Id == incidentalFee.IncidentalType);
                if (t.CalculationMethod == CalculationMethodEnum.固定)
                    sumIncidentalFee += incidentalFee.IncidentalFee;
                else if (t.CalculationMethod == CalculationMethodEnum.按KG数)
                    sumIncidentalFee += incidentalFee.IncidentalFee * Weight;
                else
                    sumIncidentalFee += incidentalFee.IncidentalFee * Pieces;
                incidentalFee.LadingBillId = id;
                incidentalFee.CreateTime = DateTime.Now;
            }

            IncidentalFees.ForEach(x => x.LadingBillId = id);
            await _financeIncidentalRepository.BulkToDBAsync(IncidentalFees);
            return sumIncidentalFee;
        }

        public async Task StartFrist(FinanceLadingBillDto dto)
        {
            if (await _billRepository.IsExistsAsync(x => x.BillNumber == dto.BillNumber && x.BillType == dto.BillType && x.DataBindRole == dto.DataBindRole))
            {
                throw new Exception("已存在提单帐单" + dto.BillNumber + "不允许创建新的提单帐单");
            }
            else
            {
                var model = new Finance_Logistics_LadingBill
                {
                    BillNumber = dto.BillNumber,
                    BoxQty = dto.BoxQty,
                    OverseasClearCurreny = null,
                    DomesticClearFee = 0,
                    DomesticClearFileUrl = null,
                    PaymentDomesticClearFee = 0,
                    FristFee = 0,
                    PaymentFristFee = 0,
                    FristFileUrl = dto.FristFileUrl,
                    Pieces = dto.Pieces,
                    Weight = dto.Weight,
                    _Destination = dto._Destination,
                    FristServiceName = dto.FristServiceName,
                    Departure = dto.Departure,
                    CreateTime = DateTime.Now,
                    BillType = dto.BillType,
                    CustomerName = dto.CustomerName,
                    ChannelId = dto.ChannelId,
                    CustomerBillTime = dto.CustomerBillTime,
                    DomesticClearBillTime = dto.CustomerBillTime,
                    FristBillTime = dto.CustomerBillTime,
                    OverseasClearBillTime = dto.CustomerBillTime,
                    CollectionBillStatus = dto.CollectionBillStatus,
                    ShipRoute = dto.ShipRoute,
                    Salesman = dto.Salesman,
                    Airline = dto.Airline,
                    ClearanceNote = dto.ClearanceNote,
                    FlightNumber = dto.FlightNumber,
                    DeliveryWeight = dto.DeliveryWeight,
                    DeliveryVolume = dto.DeliveryVolume,
                    PoundWeight = dto.PoundWeight,
                    BookedOffTime = dto.BookedOffTime,
                    ActualBookedOffTime = dto.ActualBookedOffTime,
                    CustomerMonitoringRemarks = dto.CustomerMonitoringRemarks,
                    DataBindRole = dto.DataBindRole
                };
                int id = (int)(await _billRepository.InsertAsync(model));
                decimal sumFee = await AddIncidentals(id, dto.IncidentalFees, dto.Weight, dto.Pieces);
                await _billRepository.UpdateByPrimaryKeyAsync(id, "FristFee", sumFee);
            }

        }

        public async Task<List<Finance_Incidental>> GetIncidentals(int billId, int type)
        {
            string sql = $@"select * from [dbo].[Finance_Incidental](nolock) a join Finance_IncidentalType(nolock) b on a.IncidentalType=b.Id
                                        where b.FeeType = {type} and a.LadingBillId ={billId} and isnull(a.IsDeleted,0)=0";
            return (await _financeIncidentalRepository.QueryAsync(sql)).ToList();
        }

        public async Task DeleteBill(int billId)
        {
            var dbModle = _billRepository.GetAsync(billId).Result;
            //if (dbModle.CusetomerChequesStatus > PaymentStatus.待结款)
            //throw new Exception("非待结款状态，不能删除帐单");

            //进行扣费处理
            await _customerladingBillFeeService.OnlyRepayCharges(billId);
            await _billRepository.DeleteByIdAsync(billId);

        }

        public async Task<List<EFFinanceBill>> GetEFFinanceBillGroup(DateTime start, DateTime end, int channelId, int customerId)
        {
            return await _cache.GetAsync("GetEFFinanceBillGroup"
                + start.ToString_yyyyMMdd() + "-" + end.ToString_yyyyMMdd() + "-" + channelId + "-" + customerId,
              async () =>
              {
                  var group = await _billRepository.GetEFFinanceBillGroup(start, end, channelId, customerId);
                  return group;
              });
        }

        public async Task<List<EFFinanceGroupBill>> GetEFFinanceBillGroupAsChannel(DateTime start, DateTime end)
        {
            return await _cache.GetAsync("GetEFFinanceBillGroupAsChannel"
                + start.ToString_yyyyMMdd() + "-" + end.ToString_yyyyMMdd() + "-",
              async () =>
              {
                  return await _billRepository.GetEFFinanceBillGroupAsChannel(start, end);
              });
        }

        public async Task<List<EFFinanceGroupBill>> GetEFFinanceBillGroupAsCustomer(DateTime start, DateTime end)
        {
            return await _cache.GetAsync("GetEFFinanceBillGroupAsCustomer"
                + start.ToString_yyyyMMdd() + "-" + end.ToString_yyyyMMdd() + "-",
              async () =>
              {
                  return await _billRepository.GetEFFinanceBillGroupAsCustomer(start, end);
              });
        }

        public async Task<byte[]> GetEFFinanceBillDetails(DateTime start, DateTime end, int channelId, int customerId)
        {
            var list = await _billRepository.GetEFFinanceBillDetails(start, end, channelId, customerId);

            var data = _excel.OutDataAsByte<OutDataInfo, View_FinanceBill2>(list);
            return data;
        }


        public async Task<List<EFFinanceBill>> GetFinanceBillGroup(DateTime start, DateTime end, int channelId, int customerId)
        {
            return await _cache.GetAsync("GetFinanceBillGroup"
                + start.ToString_yyyyMMdd() + "-" + end.ToString_yyyyMMdd() + "-" + channelId + "-" + customerId,
              async () =>
              {
                  var group = await _billRepository.GetFinanceBillGroup(start, end, channelId, customerId);
                  return group;
              });
        }

        public async Task<List<EFFinanceGroupBill>> GetFinanceBillGroupAsChannel(DateTime start, DateTime end)
        {
            return await _cache.GetAsync("GetFinanceBillGroupAsChannel"
                + start.ToString_yyyyMMdd() + "-" + end.ToString_yyyyMMdd() + "-",
              async () =>
              {
                  return await _billRepository.GetFinanceBillGroupAsChannel(start, end);
              });
        }

        public async Task<List<EFFinanceGroupBill>> GetFinanceBillGroupAsCustomer(DateTime start, DateTime end)
        {
            return await _cache.GetAsync("GetFinanceBillGroupAsCustomer"
                + start.ToString_yyyyMMdd() + "-" + end.ToString_yyyyMMdd() + "-",
              async () =>
              {
                  return await _billRepository.GetFinanceBillGroupAsCustomer(start, end);
              });
        }

        public async Task<byte[]> GetFinanceBillDetails(DateTime start, DateTime end, int channelId, int customerId)
        {
            var list = await _billRepository.GetFinanceBillDetails(start, end, channelId, customerId);

            var data = _excel.OutDataAsByte<OutDataInfo, View_FinanceBill2>(list);
            return data;
        }

        public async Task<byte[]> DownFinanceBranchProfitReport(SearchFinanceReportParam param)
        {
            var list = await _billRepository.GetFinanceSimpleReportDetails(param.ReceiveTimeStart, param.ReceiveTimeEnd, param.CreateOrderChannelId, param.CustomerId, param.BranchCompanyId, param.TrackingNumbers, param.TransferNumbers, param.LadingBillNumbers);

            var data = _excel.OutDataAsByte<FinanceSimpleReportMapping, View_FinanceBill_WithBranchCompany>(list);
            return data;
        }

        public async Task<byte[]> DownFinanceReport(SearchFinanceReportParam param)
        {

            var list = await _billRepository.GetFinanceReportDetails(param.ReceiveTimeStart, param.ReceiveTimeEnd, param.CreateOrderChannelId, param.CustomerId, param.BranchCompanyId, param.TrackingNumbers, param.TransferNumbers, param.LadingBillNumbers);

            var data = _excel.OutDataAsByte<FinanceReportMapping, View_FinanceBill_WithBranchCompany>(list);
            return data;
        }

        public async Task<PageResult<View_FinanceBill_WithBranchCompany>> QueryFinanceReport(QueryModel queryModel)
        {
            var list = await _billRepository.QueryFinanceReportDetailPage(queryModel);
            return list;
        }


        public async Task<List<CompletionRate>> GetCompletionRate(DateTime start, DateTime end, int channelId, int customerId)
        {
            return await _cache.GetAsync("GetCompletionRate"
                + start.ToString_yyyyMMdd() + "-" + end.ToString_yyyyMMdd() + "-" + channelId + "-" + customerId,
              async () =>
              {
                  var group = await _billRepository.GetCompletionRate(start, end, channelId, customerId);
                  return group;
              });
        }

        public async Task<FinanceBillDetailWeightDifferenceGroup> GetFinanceBillDetailWeightDifferenceGroup(DateTime startDate, DateTime endDate, int channelId, int customerId)
        {
            var list1 = await _billRepository.GetEFFinanceBillDetails(startDate, endDate, channelId, customerId);
            var list2 = await _billRepository.GetFinanceBillDetails(startDate, endDate, channelId, customerId);
            var diff = from f1 in list1
                       join f2 in list2 on f1.跟踪号 equals f2.跟踪号 into temp
                       from tt in temp.DefaultIfEmpty()
                       select new FinanceBillDetailWeightDifference
                       {
                           跟踪号 = "",
                           一级中转差异 = f1.一级中转 - tt.一级中转,
                           二级中转差异 = f1.二级中转 - tt.二级中转,
                           关税差异 = f1.关税 - tt.关税,
                           出口报关差异 = f1.出口报关 - tt.出口报关,
                           末端派送差异 = f1.末端派送 - tt.末端派送,
                           海外中转差异 = f1.海外中转 - tt.海外中转,
                           海外清关差异 = f1.海外清关 - tt.海外清关,
                           空运成本差异 = f1.空运成本 - tt.空运成本,
                           营运成本差异 = f1.营运成本 - tt.营运成本,
                           补贴差异 = f1.补贴 - tt.补贴,
                           称重重量 = (decimal)f1.称重重量 / 1000.0m,
                           一级中转 = tt.一级中转,
                           二级中转 = tt.二级中转,
                           关税 = tt.关税,
                           出口报关 = tt.出口报关,
                           末端派送 = tt.末端派送,
                           海外中转 = tt.海外中转,
                           海外清关 = tt.海外清关,
                           空运成本 = tt.空运成本,
                           营运成本 = tt.营运成本,
                           补贴 = tt.补贴
                       };

            var q2 = from t in diff
                     group t by t.跟踪号 into g
                     select new FinanceBillDetailWeightDifferenceGroup
                     {
                         一级中转差异_KG = g.Sum(x => x.一级中转差异) / (g.Sum(x => x.称重重量)),
                         二级中转差异_KG = g.Sum(x => x.二级中转差异) / (g.Sum(x => x.称重重量)),
                         关税差异_KG = g.Sum(x => x.关税差异) / (g.Sum(x => x.称重重量)),
                         出口报关差异_KG = g.Sum(x => x.出口报关差异) / (g.Sum(x => x.称重重量)),
                         末端派送差异_KG = g.Sum(x => x.末端派送差异) / (g.Sum(x => x.称重重量)),
                         海外中转差异_KG = g.Sum(x => x.海外中转差异) / (g.Sum(x => x.称重重量)),
                         海外清关差异_KG = g.Sum(x => x.海外清关差异) / (g.Sum(x => x.称重重量)),
                         空运成本差异_KG = g.Sum(x => x.空运成本差异) / (g.Sum(x => x.称重重量)),
                         营运成本差异_KG = g.Sum(x => x.营运成本差异) / (g.Sum(x => x.称重重量)),
                         补贴差异_KG = g.Sum(x => x.补贴差异) / (g.Sum(x => x.称重重量)),

                         一级中转差异_票 = g.Average(x => x.一级中转差异),
                         二级中转差异_票 = g.Average(x => x.二级中转差异),
                         关税差异_票 = g.Average(x => x.关税差异),
                         出口报关差异_票 = g.Average(x => x.出口报关差异),
                         末端派送差异_票 = g.Average(x => x.末端派送差异),
                         海外中转差异_票 = g.Average(x => x.海外中转差异),
                         海外清关差异_票 = g.Average(x => x.海外清关差异),
                         空运成本差异_票 = g.Average(x => x.空运成本差异),
                         营运成本差异_票 = g.Average(x => x.营运成本差异),
                         补贴差异_票 = g.Average(x => x.补贴差异),

                         一级中转差异_比例 = g.Sum(x => x.一级中转) == 0 ? 1 : g.Sum(x => x.一级中转差异) / g.Sum(x => x.一级中转),
                         二级中转差异_比例 = g.Sum(x => x.二级中转) == 0 ? 1 : g.Sum(x => x.二级中转差异) / g.Sum(x => x.二级中转),
                         关税差异_比例 = g.Sum(x => x.关税) == 0 ? 1 : g.Sum(x => x.关税差异) / g.Sum(x => x.关税),
                         出口报关差异_比例 = g.Sum(x => x.出口报关) == 0 ? 1 : g.Sum(x => x.出口报关差异) / g.Sum(x => x.出口报关),
                         末端派送差异_比例 = g.Sum(x => x.末端派送) == 0 ? 1 : g.Sum(x => x.末端派送差异) / g.Sum(x => x.末端派送),
                         海外中转差异_比例 = g.Sum(x => x.海外中转) == 0 ? 1 : g.Sum(x => x.海外中转差异) / g.Sum(x => x.海外中转),
                         海外清关差异_比例 = g.Sum(x => x.海外清关) == 0 ? 1 : g.Sum(x => x.海外清关差异) / g.Sum(x => x.海外清关),
                         空运成本差异_比例 = g.Sum(x => x.空运成本) == 0 ? 1 : g.Sum(x => x.空运成本差异) / g.Sum(x => x.空运成本),
                         营运成本差异_比例 = g.Sum(x => x.营运成本) == 0 ? 1 : g.Sum(x => x.营运成本差异) / g.Sum(x => x.营运成本),
                         补贴差异_比例 = g.Sum(x => x.补贴) == 0 ? 1 : g.Sum(x => x.补贴差异) / g.Sum(x => x.补贴),
                     };
            return q2.FirstOrDefault();
        }

        public async Task<byte[]> OutFinanceBillDetailWeightDifferenceDetails(DateTime startDate, DateTime endDate, int channelId, int customerId)
        {
            var list1 = await _billRepository.GetEFFinanceBillDetails(startDate, endDate, channelId, customerId);
            var list2 = await _billRepository.GetFinanceBillDetails(startDate, endDate, channelId, customerId);
            var diff = from f1 in list1
                       join f2 in list2 on f1.跟踪号 equals f2.跟踪号 into temp
                       from tt in temp.DefaultIfEmpty()
                       select new FinanceBillDetailWeightDifference
                       {
                           跟踪号 = f1.跟踪号,
                           称重时间 = DateTime.Parse(f1.称重时间),
                           称重重量 = f1.称重重量,
                           一级中转 = tt.一级中转,
                           二级中转 = tt.二级中转,
                           一级中转差异 = f1.一级中转 - tt.一级中转,
                           二级中转差异 = f1.二级中转 - tt.二级中转,
                           关税 = tt.关税,
                           关税差异 = f1.关税 - tt.关税,
                           出口报关 = tt.出口报关,
                           出口报关差异 = f1.出口报关 - tt.出口报关,
                           渠道名称 = f1.渠道名称,
                           所属客户 = f1.所属客户,
                           末端派送 = tt.末端派送,
                           末端派送差异 = f1.末端派送 - tt.末端派送,
                           收入 = 0,
                           实际渠道 = f1.实际渠道,
                           毛利 = tt.毛利,
                           毛利差异 = f1.毛利 - tt.毛利,
                           海外中转 = tt.海外中转,
                           海外中转差异 = f1.海外中转 - tt.海外中转,
                           海外清关 = tt.海外清关,
                           海外清关差异 = f1.海外清关 - tt.海外清关,
                           空运成本 = tt.空运成本,
                           空运成本差异 = f1.空运成本 - tt.空运成本,
                           营运成本 = tt.营运成本,
                           营运成本差异 = f1.营运成本 - tt.营运成本,
                           补贴 = tt.补贴,
                           补贴差异 = f1.补贴 - tt.补贴,
                           预估一级中转 = f1.一级中转,
                           预估二级中转 = f1.二级中转,
                           预估关税 = f1.关税,
                           预估出口报关 = f1.出口报关,
                           预估末端派送 = f1.末端派送,
                           预估毛利 = f1.毛利,
                           预估海外中转 = f1.海外中转,
                           预估海外清关 = f1.海外清关,
                           预估空运成本 = f1.空运成本,
                           预估营运成本 = f1.营运成本,
                           预估补贴 = f1.补贴
                       };

            var data = _excel.OutDataAsByte(diff.ToList(), new List<MSExcelClassMapping<FinanceBillDetailWeightDifference>>
            {
                new  OutOriginalInfo(),
                new OutEstimateInfo(),
                new OutDifferenceInfo()
            });
            return data;
        }

        private string getTempFilePath()
        {
            string basePath = System.IO.Path.Combine(System.AppContext.BaseDirectory, "temp");
            if (!System.IO.Directory.Exists(basePath))
                System.IO.Directory.CreateDirectory(basePath);
            return System.IO.Path.Combine(basePath, Guid.NewGuid().ToString() + ".xlsx");
        }


        public class LoadingBatchInputDtoInputMapping : MSExcelClassMapping<LoadingBatchInputDto>
        {
            public LoadingBatchInputDtoInputMapping()
            {
                Map(x => x.LoadingNumber).Name("提单");
                Map(x => x.ServiceName).Name("服务商");
                Map(x => x._Destination).Name("目的地口岸");
                Map(x => x.Departure).Name("始发地口岸");
                Map(x => x.BillTime).Name("账单时间");
                Map(x => x.Currency).Name("币种");
                Map(x => x.Poll).Name("票数");
                Map(x => x.Weight).Name("重量");
                Map(x => x.Weight).Name("计费重量");
                Map(x => x.GrossWeight).Name("毛重");
                Map(x => x.CustomerName).Name("客户");
            }
        }

        public async Task<List<LoadingBatchInputDto>> ConvertLoadingBatchInputDto(byte[] data, FinanceIncidentalTypeEnum type)
        {
            var its = await _incidentalTypeRepository.QueryBySqlAsync("select * from Finance_IncidentalType(nolock) where FeeType = " + type.GetValue());
            var list = new List<LoadingBatchInputDto>();
            string fileName = getTempFilePath();
            System.IO.File.WriteAllBytes(fileName, data);
            Application app = new Application();
            app.Visible = false; //不显示EXCEL
            app.DisplayAlerts = false; //不提示信息
            app.ScreenUpdating = false; //停止更新屏幕，加快速度
            Workbooks wbs = app.Workbooks; //获取工作薄
            _Workbook wb = wbs.Add(fileName);
            Microsoft.Office.Interop.Excel.Range range;

            //读取第1个对象
            Microsoft.Office.Interop.Excel.Worksheet sh = (Worksheet)wb.Sheets[1];
            range = sh.get_Range("A1", Missing.Value);
            var rowCount = range.get_End(XlDirection.xlDown).Row;
            var colCount = range.get_End(XlDirection.xlToRight).Column;
            var mapping = new LoadingBatchInputDtoInputMapping();
            if (rowCount > 0)
            {
                range = range.get_Resize(rowCount, colCount);
                object[,] value22 = (object[,])range.Value2;

                ///获取Map与列序号的映射关系
                Dictionary<int, int> keyValuePairs = new Dictionary<int, int>();
                Dictionary<int, string> FeeList = new Dictionary<int, string>();
                //杂费从帐单时间后开始
                int start = 0;
                for (int i = 0; i < mapping.Items.Count; i++)
                {
                    for (int j = 0; j < colCount; j++)
                    {
                        if (mapping.Items[i].ColumnName == value22[1, j + 1].ToString())
                        {
                            if (mapping.Items[i].ColumnName == "账单时间")
                            {
                                start = j;
                            }
                            keyValuePairs.Add(i, j + 1);
                            continue;
                        }
                    }
                }
                for (int j = start + 1; j < colCount; j++)
                {
                    //杂费列头 
                    FeeList.Add(j + 1, value22[1, j + 1].ToString());
                }

                string notFind = string.Join(',', FeeList.Where(x => !its.Any(y => y.Name == x.Value)).Select(x => x.Value));
                if (!string.IsNullOrEmpty(notFind))
                    throw new Exception("未事先配置以下计费项类型，请配置完成后再进行导入:" + notFind);

                for (int iRow = 1; iRow < rowCount; iRow++)
                {
                    try
                    {
                        var item = new LoadingBatchInputDto();
                        for (int iCol = 0; iCol < mapping.Items.Count; iCol++)
                        {
                            if (keyValuePairs.ContainsKey(iCol))
                            {
                                var value = value22[iRow + 1, keyValuePairs[iCol]];
                                if (value != null)
                                {
                                    var c = mapping.Items[iCol].PropertyInfo;
                                    if (c.PropertyType == typeof(int))
                                    {
                                        c.SetValue(item, Convert.ToInt32((double)value));
                                    }
                                    else if (c.PropertyType == typeof(DateTime) || c.PropertyType == typeof(DateTime?))
                                    {
                                        c.SetValue(item, DateTime.FromOADate((double)value));
                                    }
                                    else if (c.PropertyType == typeof(decimal))
                                    {
                                        c.SetValue(item, Convert.ToDecimal((double)value));
                                    }
                                    else if (c.PropertyType == typeof(string))
                                    {
                                        c.SetValue(item, value.ToString());
                                    }
                                    else
                                    {
                                        c.SetValue(item, value);
                                    }
                                }
                            }
                        }
                        item.Fees = new Dictionary<string, decimal>();
                        for (int icol = start + 2; icol <= colCount; icol++)
                        {
                            var value = value22[iRow + 1, icol];
                            if (value != null)
                                try
                                {
                                    item.Fees.Add(FeeList[icol], Convert.ToDecimal((double)value));
                                }
                                catch (Exception ex)
                                {
                                    throw new Exception("提单号:" + item.LoadingNumber + ",列:" + FeeList[icol] + "数据转换失败，列内不可包含非数字内容，无值时请留空！");
                                }

                        }
                        list.Add(item);
                    }
                    catch (Exception ex)
                    {

                    }
                }

            }
            foreach (var item in list)
            {
                var f = (await _billRepository.QueryAsync(x => x.BillNumber == item.LoadingNumber));
                if (f.Count() == 0)
                {
                    throw new Exception("帐单提单" + item.LoadingNumber + "不存在系统内");
                }
            }
            foreach (var item in list)
            {
                await AddData(type, its, item);
            }
            return list;
        }

        private async Task AddData(FinanceIncidentalTypeEnum type, IEnumerable<Finance_IncidentalType> its, LoadingBatchInputDto item)
        {
            try
            {


                var f = (await _billRepository.QueryAsync(x => x.BillNumber == item.LoadingNumber)).FirstOrDefault();
                if (f == null && type != FinanceIncidentalTypeEnum.头程杂费)
                {
                    throw new Exception("提单不存在，请确认是否导入头程杂费");
                }
                FinanceLadingBillDto fbd = f.Copy<FinanceLadingBillDto>();
                fbd.Type = type;
                switch (type)
                {
                    case FinanceIncidentalTypeEnum.头程杂费:
                        fbd.FristBillTime = item.BillTime;
                        break;

                    case FinanceIncidentalTypeEnum.国内清关杂费:
                        fbd.DomesticClearBillTime = item.BillTime;
                        break;
                    case FinanceIncidentalTypeEnum.一级中转:
                        fbd.FirstTransferBillTime = item.BillTime;
                        break;
                    case FinanceIncidentalTypeEnum.二级中转:
                        fbd.SecondTransferBillTime = item.BillTime;

                        break;
                    case FinanceIncidentalTypeEnum.关税成本:
                        fbd.TaxBillTime = item.BillTime;
                        fbd.TaxFeeCurrency = item.Currency;
                        break;
                    case FinanceIncidentalTypeEnum.国外清关杂费:
                        fbd.OverseasClearBillTime = item.BillTime;
                        fbd.OverseasClearCurreny = item.Currency;
                        break;
                    case FinanceIncidentalTypeEnum.海外中转:
                        fbd.OverSeaTransferBillTime = item.BillTime;
                        fbd.OverSeaTransferFeeCurrency = item.Currency;
                        break;
                    case FinanceIncidentalTypeEnum.补贴:
                        fbd.SubsidyBillTime = item.BillTime;
                        fbd.SubsidyCurrency = item.Currency;
                        break;
                }

                ////头程模板时允许修改基本信息
                if (type == FinanceIncidentalTypeEnum.头程杂费)
                {
                    fbd.Departure = item.Departure ?? fbd.Departure;
                    fbd._Destination = item._Destination ?? fbd._Destination;
                    fbd.FristServiceName = item.ServiceName ?? fbd.FristServiceName;
                    fbd.Weight = item.Weight > 0 ? item.Weight : fbd.Weight;
                    fbd.Pieces = item.Poll > 0 ? item.Poll : fbd.Pieces;
                }
                fbd.GrossWeight = item.GrossWeight;
                fbd.CustomerName = item.CustomerName;
                fbd.IncidentalFees = new List<Finance_Incidental>();
                foreach (var ifee in item.Fees)
                {
                    var itId = its.First(x => x.Name == ifee.Key).Id;
                    fbd.IncidentalFees.Add(new Finance_Incidental
                    {
                        LadingBillId = f.Id,
                        IncidentalFee = ifee.Value,
                        IncidentalType = itId,
                        IsDeleted = false
                    });
                }
                await Update(fbd);
            }
            catch (Exception ex)
            {
                throw new Exception("提单" + item.LoadingNumber + "导入失败" + ex.Message);
            }
        }

        public class OutEstimateInfo : MSExcelClassMapping<FinanceBillDetailWeightDifference>
        {
            public OutEstimateInfo()
            {
                Map(x => x.跟踪号).Name("跟踪号");
                Map(x => x.渠道名称).Name("渠道名称");
                Map(x => x.实际渠道).Name("实际渠道");
                Map(x => x.所属客户).Name("所属客户");
                Map(x => x.称重重量).Name("称重重量");
                Map(x => x.预估末端派送).Name("预估末端派送");
                Map(x => x.预估营运成本).Name("预估营运成本");
                Map(x => x.预估一级中转).Name("预估一级中转");
                Map(x => x.预估出口报关).Name("预估出口报关");
                Map(x => x.预估出口报关).Name("预估出口报关");
                Map(x => x.预估空运成本).Name("预估空运成本");
                Map(x => x.预估海外清关).Name("预估海外清关");
                Map(x => x.关税).Name("预估关税");
                Map(x => x.预估海外中转).Name("预估海外中转");
                Map(x => x.预估补贴).Name("预估补贴");
                Map(x => x.预估毛利).Name("预估毛利");
                Map(x => x.称重时间).Name("称重时间");
            }
        }


        public class OutDifferenceInfo : MSExcelClassMapping<FinanceBillDetailWeightDifference>
        {
            public OutDifferenceInfo()
            {
                Map(x => x.跟踪号).Name("跟踪号");
                Map(x => x.渠道名称).Name("渠道名称");
                Map(x => x.实际渠道).Name("实际渠道");
                Map(x => x.所属客户).Name("所属客户");
                Map(x => x.称重重量).Name("称重重量");
                Map(x => x.末端派送差异).Name("末端派送差异");
                Map(x => x.营运成本差异).Name("营运成本差异");
                Map(x => x.一级中转差异).Name("一级中转差异");
                Map(x => x.二级中转差异).Name("二级中转差异");
                Map(x => x.出口报关差异).Name("出口报关差异");
                Map(x => x.空运成本差异).Name("空运成本差异");
                Map(x => x.海外清关差异).Name("海外清关差异");
                Map(x => x.关税差异).Name("关税差异");
                Map(x => x.海外中转差异).Name("海外中转差异");
                Map(x => x.补贴差异).Name("补贴差异");
                Map(x => x.毛利差异).Name("毛利差异");
                Map(x => x.称重时间).Name("称重时间");
            }
        }


        public class OutOriginalInfo : MSExcelClassMapping<FinanceBillDetailWeightDifference>
        {
            public OutOriginalInfo()
            {
                Map(x => x.跟踪号).Name("跟踪号");
                Map(x => x.渠道名称).Name("渠道名称");
                Map(x => x.实际渠道).Name("实际渠道");
                Map(x => x.所属客户).Name("所属客户");
                Map(x => x.称重重量).Name("称重重量");
                Map(x => x.末端派送).Name("末端派送");
                Map(x => x.营运成本).Name("营运成本");
                Map(x => x.一级中转).Name("一级中转");
                Map(x => x.二级中转).Name("二级中转");
                Map(x => x.出口报关).Name("出口报关");
                Map(x => x.空运成本).Name("空运成本");
                Map(x => x.海外清关).Name("海外清关");
                Map(x => x.关税).Name("关税");
                Map(x => x.海外中转).Name("海外中转");
                Map(x => x.补贴).Name("补贴");
                Map(x => x.毛利).Name("毛利");
                Map(x => x.称重时间).Name("称重时间");
            }
        }


        public class OutDataInfo : MSExcelClassMapping<View_FinanceBill2>
        {
            public OutDataInfo()
            {
                Map(x => x.跟踪号).Name("跟踪号");
                Map(x => x.渠道名称).Name("渠道名称");
                Map(x => x.发货渠道).Name("发货渠道");
                Map(x => x.分区).Name("分区");
                Map(x => x.提单号).Name("提单号");
                Map(x => x.所属客户).Name("所属客户");
                Map(x => x.称重重量).Name("称重重量");
                Map(x => x.收入).Name("收入");
                Map(x => x.末端派送).Name("末端派送");
                Map(x => x.营运成本).Name("营运成本");
                Map(x => x.一级中转).Name("一级中转");
                Map(x => x.二级中转).Name("二级中转");
                Map(x => x.出口报关).Name("出口报关");
                Map(x => x.空运成本).Name("空运成本");
                Map(x => x.海外清关).Name("海外清关");
                Map(x => x.关税).Name("关税");
                Map(x => x.海外中转).Name("海外中转");
                Map(x => x.补贴).Name("补贴");
                Map(x => x.总成本).Name("总成本");
                Map(x => x.毛利).Name("毛利");
                Map(x => x.称重时间).Name("称重时间");
            }
        }
        /// <summary>
        /// 帐单结算更新头程帐单
        /// </summary>
        /// <param name="CustomerId"></param>
        /// <param name="billList"></param>
        /// <returns></returns>
        public async Task<bool> PassRemittanceForFirstBill(int CustomerId, IEnumerable<Finance_CustomerDeliveryBill> billList)
        {
            bool result = false;
            if (billList == null || billList.Count() == 0) { return result; }
            try
            {
                #region 已还清
                var payOff = billList.Where(x => x.Status == FiannceServiceBillStatus.已还清).ToList();
                if (payOff != null && payOff.Count > 0)
                {
                    await _billRepository.CompleteFirstBillCusetomerChequesStatus(CustomerId, payOff.Max(x => x.EndTime).AddDays(1));
                }
                #endregion
                #region  部分还清
                var partPayOff = billList.Where(x => x.Status == FiannceServiceBillStatus.结算中 && x.Payment > 0).ToList();
                if (partPayOff != null && partPayOff.Count > 0)
                {
                    foreach (var item in partPayOff)
                    {
                        var tempData = _billRepository.GetLadingBillByChargesDetail(item.EndTime.AddDays(1), CustomerId).Result;
                        List<Finance_Logistics_LadingBill> toDBData = new List<Finance_Logistics_LadingBill>();
                        decimal tempAmountToBeRepaid = item.AmountToBeRepaid;
                        //待还款与欠款一致，下一个订单
                        if (tempAmountToBeRepaid == tempData.Sum(x => x.CusetomerFee - x.CusetomerCheques)) { continue; }
                        foreach (var itemChild in tempData)
                        {
                            decimal waitPay = itemChild.CusetomerFee - itemChild.CusetomerCheques;//欠款
                            //帐单欠款与提单未付款保持一致
                            if (tempAmountToBeRepaid - waitPay > 0) { tempAmountToBeRepaid -= waitPay; continue; }
                            else if (tempAmountToBeRepaid == 0) { itemChild.CusetomerCheques = itemChild.CusetomerFee; itemChild.CusetomerChequesStatus = PaymentStatus.结款结束; }
                            else if (tempAmountToBeRepaid - waitPay <= 0)
                            {
                                itemChild.CusetomerCheques = itemChild.CusetomerFee - tempAmountToBeRepaid; tempAmountToBeRepaid = 0;
                                if (itemChild.CusetomerCheques == itemChild.CusetomerFee) { itemChild.CusetomerChequesStatus = PaymentStatus.结款结束; }
                            }
                            await _billRepository.UpdateAsync(itemChild);
                        }
                    }
                }
                #endregion
                result = true;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            return result;

        }

        public async Task<byte[]> OutFinanceBillCustomerMonitoring(QueryModel queryModel)
        {
            queryModel.PageSize = int.MaxValue;//不做分页
            var list = await GetData(queryModel);
            List<int> billIds = list.Result.Select(x => x.Id).ToList();
            var Incidentals = await GetIncidentals(billIds);
            var resultList = list.Result.ToList();
            resultList.ForEach(x =>
            {
                var tempIncidentals = Incidentals.Where(y => y.LadingBillId == x.Id);
                var tempCustomerQuotation = tempIncidentals?.Where(y => y.IncidentalType == 36)?.FirstOrDefault();//写死判断
                var tempCustomerQuotationNote = tempIncidentals?.Where(y => y.IncidentalFeeType == (int)FinanceIncidentalTypeEnum.头程杂费 && y.IncidentalType != 36 && y.IncidentalFee > 0)?.ToList();

                var tempQuotation = tempIncidentals?.Where(y => y.IncidentalType == 65)?.FirstOrDefault();//写死判断
                var tempQuotationNote = tempIncidentals?.Where(y => y.IncidentalFeeType == (int)FinanceIncidentalTypeEnum.收款 && y.IncidentalType != 65 && y.IncidentalFee > 0)?.ToList();

                x.CustomerQuotation = (tempQuotation?.IncidentalFee).ToString();
                x.CustomerQuotationNote = string.Join(";", tempQuotationNote?.Select(y => y.IncidentalTypeName = y.IncidentalTypeName + ":" + y.IncidentalFee));

                x.AgencyQuotation = (tempCustomerQuotation?.IncidentalFee).ToString();
                x.AgencyQuotationNote = string.Join(";", tempCustomerQuotationNote?.Select(y => y.IncidentalTypeName = y.IncidentalTypeName + ":" + y.IncidentalFee));
            });
            var data = _excel.OutDataAsByte<BillCustomerMonitoringMapping, View_Finance_Logistics_LadingBill>(resultList);
            return data;

        }
        private async Task<List<Finance_Incidental>> GetIncidentals(List<int> billIds)
        {
            string sql = $@"select a.*,b.Name as IncidentalTypeName,b.FeeType IncidentalFeeType from [dbo].[Finance_Incidental](nolock) a left join Finance_IncidentalType(nolock) b on a.IncidentalType=b.Id
                                        where a.LadingBillId in ({string.Join(',', billIds)}) and isnull(a.IsDeleted,0)=0";
            return (await _financeIncidentalRepository.QueryAsync(sql)).ToList();
        }

        public async Task<List<FinanceOrderChargesGroup>> GetIncidentalGroupData(QueryModel queryModel)
        {
            var mode = queryModel.QueryParamer.FirstOrDefault(x => x.Filed == "Mode");
            string groupBy = "";
            if (mode == null)
            {
                throw new Exception("必须选择一个查询维度");
            }
            if (mode.Value == "1")
            {
                groupBy = "分公司名称";
            }
            else if (mode.Value == "2")
            {
                groupBy = "业务员";
            }
            else if (mode.Value == "3")
            {
                groupBy = "所属客户";
            }
            else if (mode.Value == "4")
            {
                groupBy = "渠道名称";
            }
            queryModel.QueryParamer.Remove(mode);

            var customerFiled = queryModel.QueryParamer.FirstOrDefault(x => x.Filed == "CustomerId");
            if (customerFiled != null)
            {
                customerFiled.Filed = "fb.CustomerId";
            }

            string where = _billRepository.GetWhere(queryModel.QueryParamer);
            if (string.IsNullOrEmpty(where))
            {
                throw new Exception("至少选择一个搜索条件");
            }


            string sql = $@"                
                        select {groupBy} as [Key],Count(0)as 收货单量,sum(称重重量)/1000.0 as 收货重量,  sum(isnull(bc.Profit,0)) as 毛利,
                                                           sum(isnull(mc.ShippingFee,0)+isnull(mc.EUTariff,0)+isnull(mc.AttachFee,0))收入,
                                                           sum(isnull(bc.ShippingFee,0)+isnull(bc.EUTariff,0)+isnull(bc.AttachFee,0))成本,
                                case  when sum(isnull(mc.ShippingFee,0)+isnull(mc.EUTariff,0)+isnull(mc.AttachFee,0))=0 
                                   then 0 else sum(isnull(bc.Profit,0))/ sum(isnull(mc.ShippingFee,0)+isnull(mc.EUTariff,0)+isnull(mc.AttachFee,0))end 毛利占比     from BaseOrderInfo fb   
                        left join Finance_Order_Charges(nolock) bc on fb.BranchCompanyId=bc.CustomerId and fb.系统单号=bc.SystemNo and bc.IncomeOrESxpense='支出' and bc.ChargeTarget=2 and bc.Offset=0  
                        left join Finance_Order_Charges(nolock) mc on fb.CustomerId=mc.CustomerId and fb.系统单号=mc.SystemNo and mc.IncomeOrESxpense='支出' and mc.ChargeTarget=1 and mc.Offset=0

                         where   PublicChannelId not in(8,9,15,16,21,32,35,38,39,40,42,43,54,55,56,63,64,65) and fb.CustomerId not in(227,294)  and bc.ShippingFee >0 and fb.订单状态 in('待发货','已发货') 
                          {where} 
                  group by {groupBy}";

            return (await _unitOfWork.QueryBySqlAsync<FinanceOrderChargesGroup>(sql, 60 * 1000, null)).OrderByDescending(x => x.收入).ToList();

        }



        public async Task<Dictionary<int, string>> GetIncidentalGroup()
        {
            return new Dictionary<int, string> {
                 {1,"分公司" }
                ,{2,"销售员" }
                ,{3,"客户" }
                ,{4,"线路" }
            };
        }

        public class BillCustomerMonitoringMapping : MSExcelClassMapping<View_Finance_Logistics_LadingBill>
        {
            public BillCustomerMonitoringMapping()
            {
                Map(x => x.FristBillTime).Name("出库时间");
                Map(x => x.CreateUserName).Name("操作");
                Map(x => x.ShipRoute).Name("航线");
                Map(x => x.Salesman).Name("销售");
                Map(x => x.CustomerName).Name("客户");
                Map(x => x.CustomerQuotation).Name("客户报价");
                Map(x => x.CustomerQuotationNote).Name("客户报价备注");
                Map(x => x.AgencyQuotation).Name("代理报价");
                Map(x => x.AgencyQuotationNote).Name("代理报价备注");
                Map(x => x.Departure).Name("起飞港");
                Map(x => x._Destination).Name("目的港");
                Map(x => x.FristServiceName).Name("空运代理");
                Map(x => x.ClearanceNote).Name("报关备注");
                Map(x => x.Airline).Name("航司");
                Map(x => x.FlightNumber).Name("航班号");
                Map(x => x.BillNumber).Name("主单号");
                Map(x => x.BoxQty).Name("件数");
                Map(x => x.Pieces).Name("票数");
                Map(x => x.DeliveryWeight).Name("出库重量");
                Map(x => x.DeliveryVolume).Name("出库体积");
                Map(x => x.PoundWeight).Name("磅重");
                Map(x => x.GrossWeight).Name("提单毛重");
                Map(x => x.Weight).Name("计费重");
                Map(x => x.VolumeWeight).Name("提单体积");
                Map(x => x.TypeWeight).Name("货型重量");
                Map(x => x.CusetomerFee).Name("实收客户计费");
                Map(x => x.BookedOffTime).Name("订仓起飞时间");
                Map(x => x.ActualBookedOffTime).Name("实际起飞时间");
                Map(x => x.IsForecast).Name("预报");
                Map(x => x.CustomerMonitoringRemarks).Name("备注");
            }
        }
    }
}
