using Hh.Mes.Common.log;
using Hh.Mes.POJO.Entity;
using Hh.Mes.POJO.EnumEntitys;
using Hh.Mes.POJO.Response;
using Hh.Mes.POJO.ViewModel;
using Hh.Mes.Service.Repository;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;

namespace Hh.Mes.Service.Material
{
    /// <summary>
    /// 套料计算
    /// </summary>
    public class CutPlanCalculateService : RepositorySqlSugar<dynamic>
    {
        #region 属性

        /// <summary>
        /// 同步锁,套料要避免同步并发
        /// </summary>
        public static object LockNesting { get; set; } = new object();

        //套料结果
        public TotalData totalData { get; set; } = new TotalData();


        /// <summary>
        /// 获取字典的废料长度
        /// </summary>
        public decimal CutPlanLength
        {
            get
            {
                var CutPlan = GetDictionaryDictValue("CuttingWasteLength", "CutConfig");
                if (CutPlan == null)
                    CutPlan = "250";

                return decimal.Parse(CutPlan);
            }
        }

        /// <summary>
        /// 获取字典的管材长度
        /// </summary>
        public decimal PipeLength
        {
            get
            {
                var PipeLength = GetDictionaryDictValue("PipeLengthConfig", "CutConfig");
                if (PipeLength == null)
                    PipeLength = "5950";

                return decimal.Parse(PipeLength);
            }
        }

        /// <summary>
        /// 获取字典的切割损耗
        /// </summary>
        public decimal CutFlanLength
        {
            get
            {
                var cutFlan = GetDictionaryDictValue("CutFlanConfig", "CutConfig");
                if (cutFlan == null)
                    cutFlan = "0";

                return decimal.Parse(cutFlan);
            }
        }

        /// <summary>
        /// 登陆用户
        /// </summary>
        private string SysUser
        {
            get
            {
                return sysWebUser?.Account;
            }
        }
        #endregion

        #region 套料相关

        /// <summary>
        /// 套料计算
        /// </summary>
        /// <param name="cutHeadIds">套料指定的工单头表ID</param>
        /// <returns></returns>
        public dynamic Calculation(string cutHeadIds)
        {
            var response = new Response();
            try
            {
                lock (LockNesting)
                {
                    #region  套料计算

                    if (string.IsNullOrWhiteSpace(cutHeadIds))
                    {
                        return response.ResponseError($"请选择工单!");
                    }

                    List<int> cutHeadList = cutHeadIds.Split(',').Select(t => int.Parse(t)).ToList();

                    //工单
                    var workOrderHeadQueryable = Context.Queryable<bus_workOrder_head>()
                                                       .Where(x => cutHeadList.Contains(x.id) && !x.isScrap && x.nowOprSequenceCode == EnumoprSequenceCode.套料).ToList();

                    if (workOrderHeadQueryable.Count == 0)
                    {
                        return response.ResponseError($"没有状态为【套料】工序的工单,不能套料!");
                    }

                    var headKeysList = workOrderHeadQueryable.Select(x => x.keys).Distinct().ToList();

                    //工单明细
                    var workOrderDetailQueryable = Context.Queryable<bus_workOrder_detail>()
                                                       .Where(x => headKeysList.Contains(x.headKeys) && x.state == (int)EnumOrderBodyStatus.初始化 && x.workCenterCode == EnumoprSequenceCode.套料).ToList();
                    if (workOrderDetailQueryable.Count == 0)
                    {
                        return response.ResponseError($"没有状态为【初始】的工单明细,不能套料!");
                    }

                    //物料分组
                    var cutMaterCodeList = workOrderDetailQueryable.Select(t => t.cutMaterCode).ToList().Distinct().ToList();

                    //单管的管段明细,按照物料类型分组暂存到List
                    var spoolList = new List<List<bus_workOrder_detail>>();

                    #region 数据筛选  通过切割工单明细物料,从小到大排序,然后套料 
                    foreach (var materCode in cutMaterCodeList)
                    {
                        var cutDetailTemp = workOrderDetailQueryable.Where(x => x.cutMaterCode == materCode).ToList();
                        cutDetailTemp = cutDetailTemp.OrderBy(x => x.cuttingLength).ToList();
                        spoolList.Add(cutDetailTemp);
                    }

                    foreach (var partList in spoolList)
                    {
                        //管段匹配的最大的管材长度
                        var pipeLengthMax = PipeLength;
                        //单根管段匹配的最小长度
                        var pipeLength = pipeLengthMax - CutPlanLength;

                        //1.找出管段长度大于"单根管段匹配的最小长度"小于"管段匹配的最大的管材长度"的管段,进行整个单管套料
                        var partList1 = partList.Where(x => x.cuttingLength >= pipeLength && x.cuttingLength <= pipeLengthMax).ToList();

                        //整根套料,添加套料方案
                        if (partList1.Count > 0)
                            AddScheme(workOrderHeadQueryable, partList1);

                        //2.找出管段长度小于"单根管段匹配的最小长度"的管段,进行多管段套料
                        var partList2 = partList.Where(x => x.cuttingLength < pipeLength).ToList();
                        if (partList2.Count > 0)
                            PartCalculation(workOrderHeadQueryable, partList2);

                        //记录未套料工单明细
                        var partList3 = partList.Where(x => x.cuttingLength > pipeLengthMax).ToList();
                        partList3.ForEach(x => totalData.notWorkOrderDetailList.Add(x));
                        //记录未套料工单
                        var headKeyList = partList3.Select(x => x.headKeys).ToList().Distinct().ToList();
                        var notworkOrderHeadList = workOrderHeadQueryable.Where(x => headKeyList.Contains(x.keys)).ToList();
                        notworkOrderHeadList.ForEach(x => totalData.notWorkOrderheadList.Add(x));

                        //移除不能套料工单(已经把可以套料的管段都进行了套料,剩下的就是不能套料的管段,把不能套料的明细关联的工单头移除,剩下的工单都是已经套料完的)
                        workOrderHeadQueryable.RemoveAll(x => notworkOrderHeadList.Exists(y => y.keys == x.keys));
                    }

                    //记录工单
                    totalData.workOrderheadList = workOrderHeadQueryable;
                    #endregion

                    response.Message = "计算成功!";
                    return response;

                    #endregion
                }
            }
            catch (Exception ex)
            {
                return response.ResponseError($"套料计算发生异常,原因:{ex.Message}");
            }
        }

        /// <summary>
        /// 对管段进行套料计算,按照最大利用来套料,可能出现一个工单的管段分散在多个管材上
        /// </summary>
        private void PartCalculation(List<bus_workOrder_head> workOrderHeadList, List<bus_workOrder_detail> workOrderDetailList)
        {
            #region 循环套料

            //循环套料
            while (workOrderDetailList.Count > 0)
            {
                //管段组
                var detailGroup = new List<bus_workOrder_detail>();
                //损耗
                decimal loss = 0;
                //配置的管材长度
                var pipeLength = PipeLength;
                //配置的废料长度
                var cutPlanLength = CutPlanLength;
                //配置的切割余量
                var cutFlanLength = CutFlanLength;

                var Detail = new List<bus_workOrder_detail>();
                foreach (var part in workOrderDetailList)
                {
                    //"管段+废料长度+切割余量+损耗"小于管材长度,就可用
                    if (pipeLength >= part.cuttingLength + cutPlanLength + cutFlanLength + loss)
                    {
                        detailGroup.Add(part);
                        loss = loss + part.cuttingLength + cutFlanLength;
                        Detail.Add(part);
                    }
                }

                // 移除已经套料管段
                workOrderDetailList.RemoveAll(x => Detail.Exists(y => y.bodyKeys == x.bodyKeys));

                if (detailGroup.Count > 0)
                    AddScheme(workOrderHeadList, detailGroup);
            }

            #endregion
        }

        /// <summary>
        /// 添加套料方案
        /// </summary>
        /// <param name="workOrderHeadList">工单头表</param>
        /// <param name="workOrderDetailList">工单明细表</param>
        private void AddScheme(List<bus_workOrder_head> workOrderHeadList, List<bus_workOrder_detail> workOrderDetailList)
        {
            #region 添加套料方案

            TotalModel totalModel = new TotalModel();

            var loss = workOrderDetailList.Select(x => x.cuttingLength);

            // 总切割长度 = 总损耗长度 + 总管段长度
            var sumProducts = workOrderDetailList.Sum(x => x.cuttingLength + CutFlanLength);
            //利用率 = 总切割长度 / 管材长度
            var percentage = sumProducts / PipeLength;

            //表头Key
            var keys = Guid.NewGuid();

            //余料码
            var oddmentsCode = GetOddmentsCode(PipeLength - sumProducts, workOrderDetailList[0].id);

            //套料方案头
            var cutplanHead = new bus_cutplan_head();
            cutplanHead.keys = keys;
            cutplanHead.materialCode = workOrderDetailList[0].cutMaterCode;
            cutplanHead.pipeLength = PipeLength;
            cutplanHead.lossCount = percentage;
            cutplanHead.oddmentsCode = oddmentsCode;
            cutplanHead.oddmentsLength = PipeLength - sumProducts;
            //cutplanHead.lineCode = "线体";
            cutplanHead.planStartTime = DateTime.Now.ToString("yyyy-MM-dd");
            cutplanHead.level = 1;
            cutplanHead.state = (int)EnumCutPlanHeadStatus.初始;
            cutplanHead.createTime = DateTime.Now.ToString();
            cutplanHead.createBy = SysUser;

            //套料明细
            List<bus_cutplan_detail> detaillis = new List<bus_cutplan_detail>();

            //切割优先级
            var Level = workOrderDetailList.Count;

            foreach (var item in workOrderDetailList)
            {
                //明细对应头表
                var cutplan = workOrderHeadList.Where(x => x.keys == item.headKeys).First();
                //追踪码
                //var barCode = GetBarCode(item.id);

                var bodyKeys = Guid.NewGuid();

                var cutplanDetail = new bus_cutplan_detail();
                cutplanDetail.id = item.id;
                cutplanDetail.bodyKeys = bodyKeys;
                cutplanDetail.headKeys = keys;
                cutplanDetail.workOrderHeadKeys = cutplan.keys;
                cutplanDetail.workOrderDetailKeys = item.bodyKeys;
                cutplanDetail.iwpNo = cutplan.workOrderCode;
                cutplanDetail.barCode = item.barCode;
                cutplanDetail.cuttingLength = item.cuttingLength;
                cutplanDetail.cutFlanConfig = CutFlanLength;
                cutplanDetail.cutState = (int)EnumCutPlanDetailStatus.初始;
                cutplanDetail.cutLevel = Level;
                cutplanDetail.isendproduct = item.isEndProduct;
                cutplanDetail.createTime = DateTime.Now;
                cutplanDetail.createBy = SysUser;
                //页面展示使用
                cutplanDetail.parentTypeId = keys;
                cutplanDetail.keys = bodyKeys;

                detaillis.Add(cutplanDetail);

                //工单明细记录追踪码,套料保存时使用
                //item.barCode = barCode;
                item.state = (int)EnumOrderBodyStatus.已完成;
                item.actualEndTime = DateTime.Now;
                item.updateBy = SysUser;
                item.updateTime = DateTime.Now;
                totalData.workOrderDetailList.Add(item);

                Level--;
            }

            //记录套料
            totalModel.cutplanHead = cutplanHead;
            totalModel.planDetailList = detaillis;
            totalModel.Percentage = percentage.ToString("0.00%");

            totalData.totalModel.Add(totalModel);

            #endregion
        }

        /// <summary>
        /// 生成余料编码
        /// </summary>
        /// <returns></returns>
        private string GetOddmentsCode(decimal Length, int ID)
        {
            //码前缀
            string prefix = "Y";
            //废料长度
            var cutPlanLength = CutPlanLength;

            if (cutPlanLength > Length)
            {
                prefix = "F";
            }

            string Code = DateTime.Now.ToString("yyMMdd");

            return prefix + Code + ID.ToString();
        }

        /// <summary>
        /// 生成追踪码
        /// </summary>
        /// <returns></returns>
        //private string GetBarCode(int ID)
        //{
        //    return (100000 + ID).ToString();
        //}

        /// <summary>
        /// 查询可套料工单
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public dynamic GetCutterInfo(string time)
        {
            var response = new Response();
            try
            {
                #region  查询 工单头、明细

                List<bus_workOrder_detail> cutList = new List<bus_workOrder_detail>();

                if (string.IsNullOrWhiteSpace(time))
                {
                    return response.ResponseError($"请选择日期!");
                }

                //工单
                var workOrderHeadQueryable = Context.Queryable<bus_workOrder_head>()
                                                   .Where(x => SqlSugar.SqlFunc.DateIsSame(x.planStartTime, DateTime.Parse(time))
                                                   && x.nowOprSequenceCode == EnumoprSequenceCode.套料).ToList();

                if (workOrderHeadQueryable.Count == 0)
                {
                    return response.ResponseError($"未查询到可以【套料】的工单。条件:计划时间是【{time}】当前工序【{EnumoprSequenceCode.套料}】!");
                }

                //工单明细
                foreach (var item in workOrderHeadQueryable)
                {
                    var detailList = Context.Queryable<bus_workOrder_detail>()
                                                   .Where(x => x.headKeys == item.keys && x.state == (int)EnumOrderBodyStatus.初始化 && x.workCenterCode == EnumoprSequenceCode.套料).ToList();

                    detailList.ForEach(x => { x.parentTypeId = x.headKeys; x.keys = x.bodyKeys; });

                    //添加一个父对象,页面展示需要
                    bus_workOrder_detail workOrderDetail = new bus_workOrder_detail();
                    workOrderDetail.id = item.id;
                    workOrderDetail.keys = item.keys;
                    workOrderDetail.workOrderCode = item.workOrderCode;
                    workOrderDetail.parentTypeId = Guid.Parse("00000000-0000-0000-0000-000000000000");

                    cutList.Add(workOrderDetail);

                    detailList.ForEach(x => cutList.Add(x));
                }

                response.Code = 200;
                response.Result = cutList;
                return response;

                #endregion
            }
            catch (Exception ex)
            {
                return response.ResponseError($"查询发生异常,原因:{ex.Message}");
            }
        }

        /// <summary>
        /// 页面套料计算
        /// </summary>
        /// <param name="cutHeadIds">套料指定的工单头表ID</param>
        /// <returns></returns>
        public dynamic GteCalculation(string cutHeadIds)
        {
            var response = new Response();
            try
            {
                lock (LockNesting)
                {
                    #region 页面套料计算
                    if (string.IsNullOrWhiteSpace(cutHeadIds))
                    {
                        return response.ResponseError($"请选择工单!");
                    }
                    var result = Calculation(cutHeadIds);
                    if (result.Code != 200) return result;

                    #region 处理数据,转换为页面使用格式

                    /// 套料结果
                    List<TotalModel> totalModel = totalData.totalModel;
                    List<bus_cutplan_detail> cutplanDetail = new List<bus_cutplan_detail>();
                    foreach (var item in totalModel)
                    {
                        bus_cutplan_detail model = new bus_cutplan_detail();
                        model.keys = item.cutplanHead.keys;
                        model.workOrderHeadKeys = item.cutplanHead.keys;
                        model.parentTypeId = Guid.Parse("00000000-0000-0000-0000-000000000000");
                        model.materialCode = item.cutplanHead.materialCode;
                        model.lossCount = item.cutplanHead.lossCount;
                        model.pipeLength = item.cutplanHead.pipeLength;
                        model.oddmentsLength = item.cutplanHead.oddmentsLength;

                        cutplanDetail.Add(model);

                        item.planDetailList.ForEach(x =>
                        {

                            x.parentTypeId = item.cutplanHead.keys;

                            cutplanDetail.Add(x);

                        });
                    }

                    // 未套料工单头表
                    List<bus_workOrder_head> notWorkOrderheadList = totalData.notWorkOrderheadList;
                    // 未套料工单明细
                    List<bus_workOrder_detail> notWorkOrderDetailList = totalData.notWorkOrderDetailList;

                    //返回结果处理
                    List<bus_workOrder_detail> returnNotWorkOrderDetailList = new List<bus_workOrder_detail>();

                    foreach (var item in notWorkOrderheadList)
                    {
                        //添加一个父对象,页面展示需要
                        bus_workOrder_detail workOrderDetail = new bus_workOrder_detail();
                        workOrderDetail.id = item.id;
                        workOrderDetail.keys = item.keys;
                        workOrderDetail.workOrderCode = item.workOrderCode;
                        workOrderDetail.parentTypeId = Guid.Parse("00000000-0000-0000-0000-000000000000");
                        returnNotWorkOrderDetailList.Add(workOrderDetail);

                        var DetailList = notWorkOrderDetailList.Where(x => x.headKeys == item.keys).ToList();
                        if (DetailList.Count > 0)
                        {
                            DetailList.ForEach(x =>
                            {
                                x.keys = Guid.NewGuid();
                                x.parentTypeId = item.keys;
                                returnNotWorkOrderDetailList.Add(x);
                            });
                        }
                    }

                    response.Message = "计算成功!";
                    response.Result = new
                    {
                        cutplanList = cutplanDetail,
                        notWorkOrderList = returnNotWorkOrderDetailList
                    };

                    return response;

                    #endregion
                    #endregion
                }
            }
            catch (Exception ex)
            {
                return response.ResponseError($"套料计算发生异常,原因:{ex.Message}");
            }
        }

        /// <summary>
        /// 套料并且保存
        /// </summary>
        /// <param name="cutHeadIds">套料指定的工单头表ID</param>
        /// <returns></returns>
        public dynamic SaveCutPlan(string cutHeadIds)
        {
            var response = new Response();
            try
            {
                lock (LockNesting)
                {
                    #region 套料保存
                    if (string.IsNullOrWhiteSpace(cutHeadIds))
                    {
                        return response.ResponseError($"请选择工单!");
                    }
                    var result = Calculation(cutHeadIds);
                    if (result.Code != 200) return result;

                    if (totalData.totalModel.Count <= 0)
                    {
                        return response.ResponseError($"没有可以保存的套料方案!");
                    }

                    //工单头
                    List<bus_workOrder_head> workOrderHeadList = totalData.workOrderheadList;

                    workOrderHeadList.ForEach(x =>
                    {
                        x.nowOprSequenceCode = EnumoprSequenceCode.切割坡口;
                        x.nowStationCode = GetStation(EnumoprSequenceCode.切割坡口);
                        x.updateBy = SysUser;
                        x.updateTime = DateTime.Now;
                    });

                    //更新工单头
                    Context.Updateable(workOrderHeadList).UpdateColumns(t => new { t.nowOprSequenceCode, t.nowStationCode, t.updateBy, t.updateTime }).AddQueue();

                    //工单明细
                    List<bus_workOrder_detail> workOrderDetailList = totalData.workOrderDetailList;
                    //更新工单明细
                    Context.Updateable(workOrderDetailList).UpdateColumns(t => new { t.state,t.actualEndTime, t.updateBy, t.updateTime }).AddQueue();

                    //套料结果
                    List<TotalModel> totalModel = totalData.totalModel;
                    foreach (var item in totalModel)
                    {
                        //添加套料结果
                        Context.Insertable(item.cutplanHead).AddQueue();
                        Context.Insertable(item.planDetailList).AddQueue();
                    }

                    var updateCount = ExecuteQueues(Context);
                    if (updateCount == 0)
                    {
                        return response.ResponseError($"套料方案方案保存数据库失败!");
                    }
                    else {
                        //套料完工反馈
                        CutWeldService cutWeldService = new CutWeldService();

                        foreach (var item1 in totalModel)
                        {
                            foreach (var item2 in item1.planDetailList)
                            {
                                //工序完工反馈
                                cutWeldService.SendIWPTechnologylineProcess(item2.barCode, (int)EnumCutHeadState.已套料);
                            } 
                        }
                    }

                    response.Message = "保存成功!";
                    return response;

                    #endregion
                }
            }
            catch (Exception ex)
            {
                return response.ResponseError($"套料保存发生异常,原因:{ex.Message}");
            }
        }

        /// <summary>
        /// 工位查询
        /// </summary>
        /// <param name="workCenterCode"></param>
        /// <returns></returns>
        public string GetStation(string workCenterCode)
        {
            return Context.Queryable<base_work_center_station_rel>().Where(x => x.workCenterCode == workCenterCode).First()?.workStationCode;
        }

        /// <summary>
        /// 手动完成套料方案,并且发送完工状态
        /// </summary>
        /// <param name="ID">ID</param>
        /// <returns></returns>
        public dynamic CompleteExecute(int ID)
        {
            var response = new Response();
            try
            {
                lock (LockNesting)
                {
                    #region 手动完成套料方案

                    //获取套料方案头表
                    var cutPlanHead = Context.Queryable<bus_cutplan_head>().Where(t => t.id == ID).First();
                    if (cutPlanHead == null)
                    {
                        return response.ResponseError($"没有套料方案,请核对!");
                    }
                    if (cutPlanHead.state > (int)EnumCutPlanHeadStatus.初始)
                    {
                        return response.ResponseError($"已经开始执行或执行完成,不需要再次确认完成!");
                    }
                    //获取套料方案明细表
                    var cutPlanDetails = Context.Queryable<bus_cutplan_detail>().Where(t => t.headKeys == cutPlanHead.keys).ToList();
                    if (cutPlanDetails.Count == 0)
                    {
                        return response.ResponseError($"没有方案明细,请核对!");
                    }

                    #region 套料状态-手动完成

                    //把套料方案头改为 手动完成
                    cutPlanHead.state = (int)EnumCutPlanHeadStatus.手动完成;
                    cutPlanHead.actualEndTime = DateTime.Now.ToString();
                    cutPlanHead.cutEndTime = DateTime.Now.ToString();
                    cutPlanHead.updateBy = SysUser;
                    cutPlanHead.updateTime = DateTime.Now.ToString();
                    Context.Updateable(cutPlanHead).UpdateColumns(t => new { t.state, t.actualEndTime, t.cutEndTime, t.updateBy, t.updateTime }).AddQueue();

                    //把套料方案明细改为 切割完成
                    Context.Updateable<bus_cutplan_detail>()
                           .SetColumns(t => t.cutState == (int)EnumCutPlanDetailStatus.切割完成)
                           .SetColumns(t => t.cutEndTime == DateTime.Now.ToString())
                           .SetColumns(t => t.updateTime == DateTime.Now.ToString())
                           .SetColumns(t => t.updateBy == SysUser)
                           .Where(t => t.headKeys == cutPlanHead.keys)
                           .AddQueue();

                    #endregion

                    #region 工单切割工序完成

                    //获取工单头表,如果工单头对应的明细实体都切割完毕,需要更新工单下一工序
                    var workOrderHeadList = cutPlanDetails.Select(x => x.workOrderHeadKeys).ToList().Distinct().ToList();
                    //本次完成的工单明细keys
                    var workOrderDetailList = cutPlanDetails.Select(x => x.workOrderDetailKeys).ToList().Distinct().ToList();

                    //分工单处理
                    foreach (var item in workOrderHeadList)
                    {
                        #region 更新工单切割工序明细为完成

                        //套料工序工单明细
                        var workOrderDetail = Context.Queryable<bus_workOrder_detail>().Where(x => x.headKeys == item && workOrderDetailList.Contains(x.bodyKeys)).ToList();
                        //已经套料工单明细barCode
                        var barCodeList = workOrderDetail.Select(x => x.barCode).ToList().Distinct().ToList();

                        //更新工单切割工序为完成
                        Context.Updateable<bus_workOrder_detail>()
                           .SetColumns(t => t.state == (int)EnumOrderBodyStatus.已完成)
                           .SetColumns(t => t.actualStartTime == DateTime.Now)
                           .SetColumns(t => t.updateTime == DateTime.Now)
                           .SetColumns(t => t.updateBy == SysUser)
                           .Where(t => t.headKeys == item&& barCodeList.Contains(t.barCode)&&t.oprSequenceCode== EnumoprSequenceCode.切割坡口)
                           .AddQueue();
                        #endregion

                        #region 更新工单头是否到下一个工序
                        //套料工单头
                        var workOrderHead = Context.Queryable<bus_workOrder_head>().Where(x => x.keys == item && x.nowOprSequenceCode == EnumoprSequenceCode.切割坡口).First();
                        //排除本次完成的切割工序明细
                        var cutplanDetail = Context.Queryable<bus_workOrder_detail>().Where(x => x.headKeys == item 
                                                                                            && !barCodeList.Contains(x.barCode) 
                                                                                            && x.state < (int)EnumOrderBodyStatus.已完成
                                                                                            &&x.oprSequenceCode== EnumoprSequenceCode.切割坡口).ToList();

                        //排除本次完成的明细,切割工序都已经完成,就需要更新工单工序到下一工序
                        if (workOrderHead != null && cutplanDetail==null)
                        {
                            workOrderHead.nowOprSequenceCode = EnumoprSequenceCode.打磨;
                            workOrderHead.nowStationCode = GetStation(EnumoprSequenceCode.打磨);
                            workOrderHead.updateBy = SysUser;
                            workOrderHead.updateTime = DateTime.Now;

                            Context.Updateable(workOrderHead).UpdateColumns(t => new { t.nowOprSequenceCode, t.nowStationCode, t.updateBy, t.updateTime }).AddQueue();
                        }
                        #endregion
                    }

                    #endregion

                    //打包执行处理
                    if (ExecuteQueues(Context) > 0)
                    {
                        //给上游完工反馈
                        CutWeldService cutWeldService = new CutWeldService();
                        cutPlanDetails.ForEach(x =>
                            cutWeldService.SendIWPTechnologylineProcess(x.barCode, (int)EnumCutHeadState.切割完成)
                        ) ;

                        return response;

                    }
                    else
                    {
                        return response.ResponseError($"手动完成套料方案数据库失败!");
                    }

                    #endregion
                }
            }
            catch (Exception ex)
            {
                return response.ResponseError($"手动完成发生异常,原因:{ex.Message}");
            }
        }

        /// <summary>
        /// 手动取消套料方案
        /// </summary>
        /// <param name="ID"></param>
        /// <returns></returns>
        public dynamic CancelPlan(int ID)
        {
            var response = new Response();
            try
            {
                lock (LockNesting)
                {
                    #region 手动取消套料方案
                    //获取套料方案头表
                    var cutPlanHead = Context.Queryable<bus_cutplan_head>().Where(t => t.id == ID).First();
                    if (cutPlanHead == null)
                    {
                        return response.ResponseError($"没有套料方案,请核对!");
                    }
                    if (cutPlanHead.state > (int)EnumCutPlanHeadStatus.初始)
                    {
                        return response.ResponseError($"已经开始执行或执行完成,不能取消!");
                    }
                    //获取套料方案明细表
                    var cutPlanDetails = Context.Queryable<bus_cutplan_detail>().Where(t => t.headKeys == cutPlanHead.keys).ToList();
                    if (cutPlanDetails.Count == 0)
                    {
                        return response.ResponseError($"没有方案明细,请核对!");
                    }

                    //删除套料方案头
                    Context.Deleteable<bus_cutplan_head>().Where(t => t.id == ID).AddQueue();
                    //删除套料方案明细
                    Context.Deleteable<bus_cutplan_detail>().Where(t => t.headKeys == cutPlanHead.keys).AddQueue();

                    //获取工单头表
                    var workOrderHead = cutPlanDetails.Select(x => x.workOrderHeadKeys).ToList().Distinct().ToList();

                    //把工单改为套料工序
                    Context.Updateable<bus_workOrder_head>()
                           .SetColumns(t => t.nowOprSequenceCode == EnumoprSequenceCode.套料)
                           .SetColumns(t => t.nowStationCode == GetStation(EnumoprSequenceCode.套料))
                           .SetColumns(t => t.updateTime == DateTime.Now)
                           .SetColumns(t => t.updateBy == SysUser)
                           .Where(t => workOrderHead.Contains(t.keys))
                           .AddQueue();

                    //工单套料工序明细状态改为初始
                    var workOrderDetails = cutPlanDetails.Select(x => x.workOrderDetailKeys).ToList();
                    Context.Updateable<bus_workOrder_detail>()
                           .SetColumns(t => t.state == (int)EnumOrderBodyStatus.初始化)
                           .SetColumns(t => t.updateTime == DateTime.Now)
                            .SetColumns(t => t.updateBy == SysUser)
                           .Where(t => workOrderDetails.Contains(t.bodyKeys))
                           .AddQueue();

                    //打包执行处理
                    if (ExecuteQueues(Context) > 0)
                    {
                        //反馈上游套料取消

                        return response;
                    }
                    else
                    {
                        return response.ResponseError($"手动完成套料方案数据库失败!");
                    }
                    #endregion
                }
            }
            catch (Exception ex)
            {
                return response.ResponseError($"手动取消发生异常,原因:{ex.Message}");
            }
        }

        #endregion
    }

}