Exemplo n.º 1
0
        private ReceiptMaster ReceiveOrder(IList<OrderDetail> orderDetailList, bool isCheckKitTraceItem, ProductLineMap productLineMap, DateTime effectiveDate, string ipNo)
        {
            #region 判断是否全0收货
            if (orderDetailList == null || orderDetailList.Count == 0)
            {
                throw new BusinessException(Resources.ORD.OrderMaster.Errors_ReceiveDetailIsEmpty);
            }

            IList<OrderDetail> nonZeroOrderDetailList = orderDetailList.Where(o => o.ReceiveQtyInput != 0 || o.ScrapQtyInput != 0).ToList();

            if (nonZeroOrderDetailList.Count == 0)
            {
                throw new BusinessException(Resources.ORD.OrderMaster.Errors_ReceiveDetailIsEmpty);
            }
            #endregion

            #region 查询订单头对象
            IList<OrderMaster> orderMasterList = LoadOrderMasters(nonZeroOrderDetailList.Select(p => p.OrderNo).Distinct(), true);
            #endregion

            #region 获取收货订单类型
            IList<com.Sconit.CodeMaster.OrderType> orderTypeList = (from orderMaster in orderMasterList
                                                                    group orderMaster by orderMaster.Type into result
                                                                    select result.Key).ToList();

            if (orderTypeList.Count > 1)
            {
                throw new BusinessException(Resources.ORD.OrderMaster.Errors_CannotMixOrderTypeReceive);
            }

            com.Sconit.CodeMaster.OrderType orderType = orderTypeList.First();
            #endregion

            #region 计划协议不能按收货校验
            if (orderType == CodeMaster.OrderType.ScheduleLine)
            {
                throw new BusinessException("计划协议不能按订单收货。");
            }
            #endregion

            #region 排序单不能按订单收货校验
            if (orderMasterList.Where(o => o.OrderStrategy == CodeMaster.FlowStrategy.SEQ).Count() > 0)
            {
                throw new BusinessException("排序单不能按订单收货。");
            }
            #endregion

            #region 循环订单头检查
            foreach (OrderMaster orderMaster in orderMasterList)
            {
                //if (!Utility.SecurityHelper.HasPermission(orderMaster))
                //{
                //    throw new BusinessException("没有此订单{0}的操作权限。", orderMaster.OrderNo);
                //}

                orderMaster.OrderDetails = nonZeroOrderDetailList.Where(det => det.OrderNo == orderMaster.OrderNo).ToList();

                //如果非生产,把Submit状态改为InProcess
                if (orderMaster.Status == com.Sconit.CodeMaster.OrderStatus.Submit
                    && orderMaster.Type != com.Sconit.CodeMaster.OrderType.Production
                    && orderMaster.Type != com.Sconit.CodeMaster.OrderType.SubContract)
                {
                    UpdateOrderMasterStatus2InProcess(orderMaster);
                }

                //判断OrderHead状态
                if (orderMaster.Status != com.Sconit.CodeMaster.OrderStatus.InProcess)
                {
                    throw new BusinessException(Resources.ORD.OrderMaster.Errors_StatusErrorWhenReceive,
                            orderMaster.OrderNo, systemMgr.GetCodeDetailDescription(com.Sconit.CodeMaster.CodeMaster.OrderStatus, ((int)orderMaster.Status).ToString()));
                }

                #region 订单、生产线暂停检查
                if (orderMaster.IsPause)
                {
                    if (orderMaster.Type == CodeMaster.OrderType.Production)
                    {
                        throw new BusinessException("生产单{0}已经暂停,不能收货。", orderMaster.OrderNo);
                    }
                    else if (orderMaster.OrderStrategy == CodeMaster.FlowStrategy.KIT)
                    {
                        throw new BusinessException("KIT单{0}已经暂停,不能收货。", orderMaster.OrderNo);
                    }
                    else if (orderMaster.OrderStrategy == CodeMaster.FlowStrategy.SEQ)
                    {
                        throw new BusinessException("排序单{0}已经暂停,不能收货。", orderMaster.OrderNo);
                    }
                    else
                    {
                        throw new BusinessException("订单{0}已经暂停,不能收货。", orderMaster.OrderNo);
                    }
                }

                //if ((orderMaster.Type == CodeMaster.OrderType.Production
                //    || orderMaster.Type == CodeMaster.OrderType.SubContract
                //    //生产线暂停可以收货
                //    //|| orderMaster.OrderStrategy == CodeMaster.FlowStrategy.KIT
                //    //|| orderMaster.OrderStrategy == CodeMaster.FlowStrategy.SEQ
                //    )
                //    && !string.IsNullOrWhiteSpace(orderMaster.Flow))
                //{
                //    FlowMaster flowMaster = this.genericMgr.FindById<FlowMaster>(orderMaster.Flow);
                //    if (flowMaster.IsPause)
                //    {
                //        throw new BusinessException("生产线{0}已经暂停,不能收货。", orderMaster.Flow);
                //    }
                //}
                #endregion

                #region 整包装收货判断,快速的不要判断
                if (orderMaster.IsReceiveFulfillUC
                    && orderMaster.SubType == com.Sconit.CodeMaster.OrderSubType.Normal
                    && !(orderMaster.IsAutoRelease && orderMaster.IsAutoStart))
                {
                    foreach (OrderDetail orderDetail in orderMaster.OrderDetails)
                    {
                        //不合格品不作为收货数
                        //if (orderDetail.ReceiveQualifiedQtyInput % orderDetail.UnitCount != 0)
                        if (orderDetail.ReceiveQtyInput % orderDetail.UnitCount != 0)
                        {
                            //不是整包装
                            throw new BusinessException(Resources.ORD.OrderMaster.Errors_ReceiveQtyNotFulfillUnitCount, orderDetail.Item);
                        }
                    }
                }
                #endregion

                #region 是否过量发货判断,未发货即收货也要判断是否过量发货
                foreach (OrderDetail orderDetail in orderMaster.OrderDetails)
                {
                    if (!orderMaster.IsOpenOrder
                        && orderMaster.Type != com.Sconit.CodeMaster.OrderType.Production   //生产和委外不需要判断
                        && orderMaster.Type != com.Sconit.CodeMaster.OrderType.SubContract)
                    {
                        if (Math.Abs(orderDetail.ShippedQty) > Math.Abs(orderDetail.OrderedQty))
                        {
                            //订单的发货数已经大于等于订单数
                            throw new BusinessException(Resources.ORD.OrderMaster.Errors_ShipQtyExcceedOrderQty, orderDetail.OrderNo, orderDetail.Item);
                        }
                        else if (!orderMaster.IsShipExceed
                            && Math.Abs(orderDetail.ShippedQty + orderDetail.ReceiveQtyInput) > Math.Abs(orderDetail.OrderedQty))   //不允许过量收货
                        {
                            //订单的发货数 + 本次发货数大于订单数
                            throw new BusinessException(Resources.ORD.OrderMaster.Errors_ShipQtyExcceedOrderQty, orderDetail.OrderNo, orderDetail.Item);
                        }
                    }
                }
                #endregion

                #region 是否过量收货判断
                foreach (OrderDetail orderDetail in orderMaster.OrderDetails)
                {
                    if (!orderMaster.IsOpenOrder)
                    {
                        var orderDeviationQty = decimal.MaxValue;
                        if (!orderMaster.IsReceiveExceed)
                        {
                            orderDeviationQty = Math.Abs(orderDetail.OrderedQty);
                        }
                        else
                        {
                            if (orderMaster.CurrentFlowMaster.OrderDeviation > 0)
                            {
                                orderDeviationQty = Math.Abs(orderDetail.OrderedQty * (((decimal)orderMaster.CurrentFlowMaster.OrderDeviation / 100) + 1));
                            }
                        }
                        //订单的收货数已经大于等于订单数
                        if (Math.Abs(orderDetail.ReceivedQty) >= Math.Abs(orderDetail.OrderedQty))
                        {
                            throw new BusinessException(Resources.ORD.OrderMaster.Errors_ReceiveQtyExcceedOrderQty, orderDetail.OrderNo, orderDetail.Item);
                        }
                        else if (Math.Abs(orderDetail.ReceivedQty + orderDetail.RejectedQty + orderDetail.ScrapQty + orderDetail.ReceiveQtyInput + orderDetail.ScrapQtyInput) > orderDeviationQty)   //不允许过量收货
                        {
                            //订单的收货数 + 本次收货数大于订单数
                            throw new BusinessException(Resources.ORD.OrderMaster.Errors_ReceiveQtyExcceedOrderQty, orderDetail.OrderNo, orderDetail.Item);
                        }
                    }
                }
                #endregion

                #region KIT单收货判断
                if (orderMaster.OrderStrategy == CodeMaster.FlowStrategy.KIT)
                {
                    CheckKitOrderDetail(orderMaster, isCheckKitTraceItem, false);
                }
                #endregion
            }
            #endregion

            #region 校验发货先进先出
            CheckShipFiFo(orderMasterList);
            #endregion

            #region 循环更新订单明细
            foreach (OrderDetail orderDetail in nonZeroOrderDetailList)
            {
                //未发货直接收货需要累加已发货数量
                if (orderDetail.OrderType != com.Sconit.CodeMaster.OrderType.Production
                    && orderDetail.OrderType != com.Sconit.CodeMaster.OrderType.SubContract)
                {
                    orderDetail.ShippedQty += orderDetail.ReceiveQtyInput;
                }

                if (orderDetail.OrderType != com.Sconit.CodeMaster.OrderType.Production
                    && orderDetail.OrderType != com.Sconit.CodeMaster.OrderType.SubContract)
                {
                    //orderDetail.ReceivedQty += orderDetail.ReceiveQualifiedQtyInput;
                    orderDetail.ReceivedQty += orderDetail.ReceiveQtyInput;
                }
                else
                {
                    //生产收货更新合格数和不合格数量
                    //orderDetail.ReceivedQty += orderDetail.ReceiveQualifiedQtyInput;
                    orderDetail.ReceivedQty += orderDetail.ReceiveQtyInput;
                    orderDetail.ScrapQty += orderDetail.ScrapQtyInput;
                }
                genericMgr.Update(orderDetail);
            }
            #endregion

            #region 发货
            #region OrderDetailInput赋发货数量
            foreach (OrderDetail orderDetail in nonZeroOrderDetailList)
            {
                foreach (OrderDetailInput orderDetailInput in orderDetail.OrderDetailInputs)
                {
                    orderDetailInput.ShipQty = orderDetailInput.ReceiveQty;
                }
            }
            #endregion

            IpMaster ipMaster = null;
            var subType = orderMasterList.First().SubType;
            if ((orderType == com.Sconit.CodeMaster.OrderType.Production || orderType == com.Sconit.CodeMaster.OrderType.SubContract)
                && subType != CodeMaster.OrderSubType.Return)
            {
                //生产和委外的非退货单 
            }
            else
            {
                //物流单 生产和委外的退货单也要创建Ip
                ipMaster = this.ipMgr.TransferOrder2Ip(orderMasterList);
                #region 循环发货
                foreach (IpDetail ipDetail in ipMaster.IpDetails)
                {
                    ipDetail.CurrentPartyFrom = ipMaster.PartyFrom;  //为了记录库存事务
                    ipDetail.CurrentPartyFromName = ipMaster.PartyFromName;  //为了记录库存事务
                    ipDetail.CurrentPartyTo = ipMaster.PartyTo;      //为了记录库存事务
                    ipDetail.CurrentPartyToName = ipMaster.PartyToName;      //为了记录库存事务
                    //ipDetail.CurrentOccupyType = com.Sconit.CodeMaster.OccupyType.None; //todo-默认出库未占用库存,除非捡货或检验的出库

                    IList<InventoryTransaction> inventoryTransactionList = this.locationDetailMgr.InventoryOut(ipDetail, effectiveDate);

                    #region 建立发货库明细和IpDetailInput的关系
                    if (inventoryTransactionList != null && inventoryTransactionList.Count > 0)
                    {
                        ipDetail.IpLocationDetails = (from trans in inventoryTransactionList
                                                      group trans by new
                                                      {
                                                          HuId = trans.HuId,
                                                          LotNo = trans.LotNo,
                                                          IsCreatePlanBill = trans.IsCreatePlanBill,
                                                          IsConsignment = trans.IsConsignment,
                                                          PlanBill = trans.PlanBill,
                                                          ActingBill = trans.ActingBill,
                                                          QualityType = trans.QualityType,
                                                          IsFreeze = trans.IsFreeze,
                                                          IsATP = trans.IsATP,
                                                          OccupyType = trans.OccupyType,
                                                          OccupyReferenceNo = trans.OccupyReferenceNo
                                                      } into g
                                                      select new IpLocationDetail
                                                      {
                                                          HuId = g.Key.HuId,
                                                          LotNo = g.Key.LotNo,
                                                          IsCreatePlanBill = g.Key.IsCreatePlanBill,
                                                          IsConsignment = g.Key.IsConsignment,
                                                          PlanBill = g.Key.PlanBill,
                                                          ActingBill = g.Key.ActingBill,
                                                          QualityType = g.Key.QualityType,
                                                          IsFreeze = g.Key.IsFreeze,
                                                          IsATP = g.Key.IsATP,
                                                          OccupyType = g.Key.OccupyType,
                                                          OccupyReferenceNo = g.Key.OccupyReferenceNo,
                                                          Qty = g.Sum(t => -t.Qty),                      //发货的库存事务为负数,转为收货数应该取负数
                                                          //PlanBillQty = g.Sum(t=>-t.PlanBillQty),
                                                          //ActingBillQty = g.Sum(t=>-t.ActingBillQty)
                                                      }).ToList();
                    }
                    #endregion
                }
                #endregion

                #region 生成收货的IpInput
                foreach (OrderDetail orderDetail in nonZeroOrderDetailList)
                {
                    OrderMaster orderMaster = orderMasterList.Where(o => o.OrderNo == orderDetail.OrderNo).Single();
                    //订单收货一定是一条订单明细对应一条发货单明细
                    IpDetail ipDetail = ipMaster.IpDetails.Where(det => det.OrderDetailId == orderDetail.Id).Single();
                    ipDetail.IpDetailInputs = null;  //清空Ip的发货数据,准备添加收货数据

                    foreach (OrderDetailInput orderDetailInput in orderDetail.OrderDetailInputs)
                    {
                        IpDetailInput ipDetailInput = new IpDetailInput();
                        ipDetailInput.ReceiveQty = orderDetailInput.ShipQty;
                        if (orderMaster.IsReceiveScanHu || orderMaster.OrderStrategy == CodeMaster.FlowStrategy.KIT)
                        {
                            ipDetailInput.HuId = orderDetailInput.HuId;
                            ipDetailInput.LotNo = orderDetailInput.LotNo;
                        }

                        ipDetail.AddIpDetailInput(ipDetailInput);
                    }
                }

                if (orderMasterList.Where(o => o.OrderStrategy == CodeMaster.FlowStrategy.KIT).Count() > 0)
                {
                    #region Kit单生成收货Input
                    foreach (IpDetail ipDetail in ipMaster.IpDetails)
                    {
                        foreach (IpDetailInput ipDetailInput in ipDetail.IpDetailInputs)
                        {
                            if (!string.IsNullOrEmpty(ipDetailInput.HuId))
                            {
                                #region 按条码匹配
                                IpLocationDetail matchedIpLocationDetail = ipDetail.IpLocationDetails.Where(locDet => locDet.HuId == ipDetailInput.HuId).SingleOrDefault();
                                matchedIpLocationDetail.ReceivedQty = matchedIpLocationDetail.Qty;
                                if (matchedIpLocationDetail != null)
                                {
                                    ipDetailInput.AddReceivedIpLocationDetail(matchedIpLocationDetail);
                                }
                                #endregion
                            }
                            else
                            {
                                #region 按数量匹配
                                IpDetail gapIpDetail = new IpDetail();
                                MatchIpDetailInput(ipDetail, ipDetailInput, ipDetail.IpLocationDetails, ref gapIpDetail);
                                #endregion
                            }
                        }
                    }
                    #endregion
                }
                else
                {
                    #region 其它订单生成收货Input
                    if (ipMaster.IsShipScanHu && ipMaster.IsReceiveScanHu)
                    {
                        #region 按条码匹配
                        foreach (IpDetail ipDetail in ipMaster.IpDetails)
                        {
                            foreach (IpDetailInput ipDetailInput in ipDetail.IpDetailInputs)
                            {
                                IpLocationDetail matchedIpLocationDetail = ipDetail.IpLocationDetails.Where(locDet => locDet.HuId == ipDetailInput.HuId).SingleOrDefault();
                                matchedIpLocationDetail.ReceivedQty = matchedIpLocationDetail.Qty;
                                if (matchedIpLocationDetail != null)
                                {
                                    ipDetailInput.AddReceivedIpLocationDetail(matchedIpLocationDetail);
                                }
                            }
                        }
                        #endregion
                    }
                    else
                    {
                        #region 按数量匹配
                        foreach (IpDetail ipDetail in ipMaster.IpDetails)
                        {
                            CycleMatchIpDetailInput(ipDetail, ipDetail.IpDetailInputs, ipDetail.IpLocationDetails);
                        }
                        #endregion
                    }
                    #endregion
                }
                #endregion
            }
            #endregion

            #region 收货 生产和委外退货的逻辑在CreateReceipt中实现
            ReceiptMaster receiptMaster = null;
            if (subType != CodeMaster.OrderSubType.Return &&
               (orderType == com.Sconit.CodeMaster.OrderType.Production || orderType == com.Sconit.CodeMaster.OrderType.SubContract))
            {
                #region 生产和委外正常收货 消耗原材料,收成品
                if (orderMasterList.Count > 1 && orderType == com.Sconit.CodeMaster.OrderType.Production)
                {
                    throw new TechnicalException("生产单不能合并收货。");
                }

                foreach (OrderMaster orderMaster in orderMasterList)
                {
                    orderMaster.IpNo = ipNo;
                    receiptMaster = this.receiptMgr.TransferOrder2Receipt(orderMaster);
                    this.receiptMgr.CreateReceipt(receiptMaster);

                    #region 回冲物料
                    if (productLineMap != null)
                    {
                        #region 整车
                        BackflushVan(productLineMap, nonZeroOrderDetailList, receiptMaster, orderMaster);
                        #endregion
                    }
                    else
                    {
                        #region 非整车
                        foreach (OrderDetail orderDetail in nonZeroOrderDetailList)
                        {
                            //OrderDetailInput orderDetailInput = orderDetail.OrderDetailInputs[0];
                            foreach (var orderDetailInput in orderDetail.OrderDetailInputs)
                            {
                                orderDetailInput.ReceiptDetails = receiptMaster.ReceiptDetails.Where(r => r.OrderDetailId == orderDetail.Id).ToList();
                            }
                        }
                        this.productionLineMgr.BackflushProductOrder(nonZeroOrderDetailList, orderMaster, DateTime.Now);
                        #endregion
                    }
                    #endregion
                }
                #endregion
            }
            else
            {
                #region 物流收货
                receiptMaster = this.receiptMgr.TransferIp2Receipt(ipMaster);
                if (orderMasterList.Where(o => o.OrderStrategy == CodeMaster.FlowStrategy.KIT).Count() > 0)
                {
                    //kit收货特殊处理
                    this.receiptMgr.CreateReceipt(receiptMaster, true, effectiveDate);
                }
                else
                {
                    this.receiptMgr.CreateReceipt(receiptMaster, false, effectiveDate);
                }
                #endregion
            }
            #endregion

            #region 尝试关闭订单
            foreach (OrderMaster orderMaster in orderMasterList)
            {
                if (orderMaster.Type == CodeMaster.OrderType.Production)
                {
                    #region 生产
                    if (productLineMap != null && productLineMap.ProductLine == orderMaster.Flow)
                    {
                        #region 总装生产单
                        CloseVanOrder(orderMaster, productLineMap);
                        #endregion
                    }
                    else if (productLineMap != null && (productLineMap.CabFlow == orderMaster.Flow || productLineMap.ChassisFlow == orderMaster.Flow))
                    {
                        #region  驾驶室和底盘
                        //驾驶室和底盘下线完工订单,总装下线后一起关闭
                        CompleteVanSubOrder(orderMaster);
                        #endregion
                    }
                    else
                    {
                        #region  非整车
                        TryCloseOrder(orderMaster);
                        #endregion
                    }
                    #endregion
                }
                else
                {
                    #region 物流
                    TryCloseOrder(orderMaster);
                    #endregion
                }
            }
            #endregion

            return receiptMaster;
        }
Exemplo n.º 2
0
        private void MatchIpDetailInput(IpDetail ipDetail, IpDetailInput ipDetailInput, IList<IpLocationDetail> ipLocationDetailList, ref IpDetail gapIpDetail)
        {
            decimal remainQty = ipDetailInput.ReceiveQty * ipDetail.UnitQty;  //转为库存单位
            foreach (IpLocationDetail ipLocationDetail in ipLocationDetailList)
            {
                if (ipLocationDetail.IsClose)
                {
                    continue;
                }

                //iplocationdet只可能为正数
                if (ipLocationDetail.RemainReceiveQty >= remainQty)
                {
                    //收货明细匹配完
                    #region 添加收货记录和IpLocationDetail的映射关系
                    IpLocationDetail receivedIpLocationDetail = Mapper.Map<IpLocationDetail, IpLocationDetail>(ipLocationDetail);
                    receivedIpLocationDetail.ReceivedQty = remainQty;
                    ipDetailInput.AddReceivedIpLocationDetail(receivedIpLocationDetail);
                    #endregion

                    ipLocationDetail.ReceivedQty += remainQty;
                    remainQty = 0;
                    if (ipLocationDetail.Qty == ipLocationDetail.ReceivedQty)
                    {
                        ipLocationDetail.IsClose = true;
                    }
                }
                else
                {
                    //收货明细未匹配完
                    #region 添加收货记录和IpLocationDetail的映射关系
                    IpLocationDetail receivedIpLocationDetail = Mapper.Map<IpLocationDetail, IpLocationDetail>(ipLocationDetail);
                    receivedIpLocationDetail.ReceivedQty = ipLocationDetail.RemainReceiveQty;
                    ipDetailInput.AddReceivedIpLocationDetail(receivedIpLocationDetail);
                    #endregion

                    remainQty -= ipLocationDetail.RemainReceiveQty;
                    ipLocationDetail.ReceivedQty = ipLocationDetail.Qty;
                    ipLocationDetail.IsClose = true;
                }

                //更新
                if (ipLocationDetail.Id > 0)
                {
                    genericMgr.Update(ipLocationDetail);
                }

                if (remainQty == 0)
                {
                    //匹配完,跳出循环
                    break;
                }
            }

            //超收,还有未匹配完的数量
            if (remainQty > 0)
            {
                #region 记录差异
                if (gapIpDetail == null || !gapIpDetail.GapIpDetailId.HasValue)
                {
                    gapIpDetail = Mapper.Map<IpDetail, IpDetail>(ipDetail);
                    gapIpDetail.Type = com.Sconit.CodeMaster.IpDetailType.Gap;
                    gapIpDetail.GapReceiptNo = string.Empty;
                    gapIpDetail.ReceivedQty = 0;
                    gapIpDetail.IsClose = false;
                    gapIpDetail.GapIpDetailId = ipDetail.Id;
                }

                gapIpDetail.Qty += -(remainQty / ipDetail.UnitQty);          //多收,数量为负,转为订单单位

                IpLocationDetail gapIpLocationDetail = new IpLocationDetail();
                gapIpLocationDetail.IpNo = ipDetail.IpNo;
                gapIpLocationDetail.OrderType = ipDetail.OrderType;
                gapIpLocationDetail.OrderDetailId = ipDetail.OrderDetailId;
                gapIpLocationDetail.Item = ipDetail.Item;
                gapIpLocationDetail.HuId = null;  //收货未匹配产生的差异全部为数量(除了条码匹配条码)
                gapIpLocationDetail.LotNo = null;
                gapIpLocationDetail.IsCreatePlanBill = false;
                gapIpLocationDetail.PlanBill = null;
                gapIpLocationDetail.ActingBill = null;
                gapIpLocationDetail.IsFreeze = false;
                gapIpLocationDetail.IsATP = false;          //差异不能进行MRP运算
                gapIpLocationDetail.QualityType = ipDetail.QualityType;
                gapIpLocationDetail.OccupyType = com.Sconit.CodeMaster.OccupyType.None;
                gapIpLocationDetail.OccupyReferenceNo = null;
                gapIpLocationDetail.Qty = -remainQty;   //多收,产生负数的差异
                gapIpLocationDetail.ReceivedQty = 0;
                gapIpLocationDetail.IsClose = false;

                gapIpDetail.AddIpLocationDetail(gapIpLocationDetail);
                #endregion
            }
        }
Exemplo n.º 3
0
        public ReceiptMaster ReceiveOrder(IList<OrderDetail> orderDetailList, DateTime effectiveDate)
        {
            #region 判断是否全0收货
            if (orderDetailList == null || orderDetailList.Count == 0)
            {
                throw new BusinessException(Resources.ORD.OrderMaster.Errors_ReceiveDetailIsEmpty);
            }

            IList<OrderDetail> nonZeroOrderDetailList = orderDetailList.Where(o => o.ReceiveQtyInput != 0 || o.ScrapQtyInput != 0).ToList();

            if (nonZeroOrderDetailList.Count == 0)
            {
                throw new BusinessException(Resources.ORD.OrderMaster.Errors_ReceiveDetailIsEmpty);
            }
            #endregion

            #region 查询订单头对象
            IList<OrderMaster> orderMasterList = LoadOrderMasters((from det in nonZeroOrderDetailList
                                                                   //where !string.IsNullOrWhiteSpace(det.OrderNo)   todo支持无订单收货
                                                                   select det.OrderNo).Distinct().ToArray());
            #endregion

            foreach (var oMaster in orderMasterList)
            {
                if (oMaster.Type == com.Sconit.CodeMaster.OrderType.Transfer)
                {
                    CheckInventory(orderDetailList.Where(ol => ol.OrderNo == oMaster.OrderNo).ToList(), oMaster);
                }
            }

            //#region 按订单明细汇总发货数,按条码发货一条订单明细会对应多条发货记录
            //var summaryOrderDet = from det in orderDetailList
            //                      group det by new { Id = det.Id, OrderNo = det.OrderNo } into g
            //                      select new
            //                      {
            //                          Id = g.Key.Id,
            //                          OrderNo = g.Key.OrderNo,
            //                          ReceiveQty = g.Sum(det => det.CurrentReceiveQty),
            //                          RejectQty = g.Sum(det => det.CurrentRejectQty)
            //                      };
            //#endregion

            #region 获取收货订单类型
            IList<com.Sconit.CodeMaster.OrderType> orderTypeList = (from orderMaster in orderMasterList
                                                                    group orderMaster by orderMaster.Type into result
                                                                    select result.Key).ToList();

            if (orderTypeList.Count > 1)
            {
                throw new BusinessException(Resources.ORD.OrderMaster.Errors_CannotMixOrderTypeReceive);
            }

            com.Sconit.CodeMaster.OrderType orderType = orderTypeList.First();
            #endregion

            #region 计划协议不能按收货校验
            if (orderType == CodeMaster.OrderType.ScheduleLine)
            {
                throw new BusinessException("计划协议不能按订单收货。");
            }
            #endregion

            #region 循环订单头检查
            foreach (OrderMaster orderMaster in orderMasterList)
            {
                orderMaster.OrderDetails = nonZeroOrderDetailList.Where(det => det.OrderNo == orderMaster.OrderNo).ToList();

                //如果非生产,把Submit状态改为InProcess
                if (orderMaster.Status == com.Sconit.CodeMaster.OrderStatus.Submit
                    && orderMaster.Type != com.Sconit.CodeMaster.OrderType.Production
                    && orderMaster.Type != com.Sconit.CodeMaster.OrderType.SubContract)
                {
                    UpdateOrderMasterStatus2InProcess(orderMaster);
                }

                //判断OrderHead状态
                if (orderMaster.Status != com.Sconit.CodeMaster.OrderStatus.InProcess)
                {
                    throw new BusinessException(Resources.ORD.OrderMaster.Errors_StatusErrorWhenReceive,
                            orderMaster.OrderNo, systemMgr.GetCodeDetailDescription(com.Sconit.CodeMaster.CodeMaster.OrderStatus, ((int)orderMaster.Status).ToString()));
                }

                #region 订单、生产线暂停检查
                if (orderMaster.PauseStatus == CodeMaster.PauseStatus.Paused)
                {
                    if (orderMaster.Type == CodeMaster.OrderType.Production)
                    {
                        throw new BusinessException("生产单{0}已经暂停,不能收货。", orderMaster.OrderNo);
                    }
                    else
                    {
                        throw new BusinessException("订单{0}已经暂停,不能收货。", orderMaster.OrderNo);
                    }
                }

                if ((orderMaster.Type == CodeMaster.OrderType.Production
                    || orderMaster.Type == CodeMaster.OrderType.SubContract
                    )
                    && !string.IsNullOrWhiteSpace(orderMaster.Flow))
                {
                    FlowMaster flowMaster = this.genericMgr.FindById<FlowMaster>(orderMaster.Flow);
                    if (flowMaster.IsPause)
                    {
                        throw new BusinessException("生产线{0}已经暂停,不能收货。", orderMaster.Flow);
                    }
                }
                #endregion

                #region 整包装收货判断,快速的不要判断
                if (orderMaster.IsReceiveFulfillUC
                    && orderMaster.SubType == com.Sconit.CodeMaster.OrderSubType.Normal
                    && !(orderMaster.IsAutoRelease && orderMaster.IsAutoStart))
                {
                    foreach (OrderDetail orderDetail in orderMaster.OrderDetails)
                    {
                        //不合格品不作为收货数
                        //if (orderDetail.ReceiveQualifiedQtyInput % orderDetail.UnitCount != 0)
                        if (orderDetail.ReceiveQtyInput % orderDetail.UnitCount != 0)
                        {
                            //不是整包装
                            throw new BusinessException(Resources.ORD.OrderMaster.Errors_ReceiveQtyNotFulfillUnitCount, orderDetail.Item);
                        }
                    }
                }
                #endregion

                #region 是否过量发货判断,未发货即收货也要判断是否过量发货
                foreach (OrderDetail orderDetail in orderMaster.OrderDetails)
                {
                    if (!orderMaster.IsOpenOrder)
                    {
                        if (Math.Abs(orderDetail.ShippedQty) > Math.Abs(orderDetail.OrderedQty))
                        {
                            //订单的发货数已经大于等于订单数
                            throw new BusinessException(Resources.ORD.OrderMaster.Errors_ShipQtyExcceedOrderQty, orderDetail.OrderNo, orderDetail.Item);
                        }
                        else if (orderMaster.Type != com.Sconit.CodeMaster.OrderType.Production   //生产和委外不需要判断
                           && orderMaster.Type != com.Sconit.CodeMaster.OrderType.SubContract
                           && !orderMaster.IsShipExceed
                            && Math.Abs(orderDetail.ShippedQty + orderDetail.ReceiveQtyInput) > Math.Abs(orderDetail.OrderedQty))   //不允许过量收货
                        {
                            //订单的发货数 + 本次发货数大于订单数
                            throw new BusinessException(Resources.ORD.OrderMaster.Errors_ShipQtyExcceedOrderQty, orderDetail.OrderNo, orderDetail.Item);
                        }
                    }
                }
                #endregion

                #region 是否过量收货判断
                foreach (OrderDetail orderDetail in orderMaster.OrderDetails)
                {
                    if (!orderMaster.IsOpenOrder)
                    {
                        //订单的收货数已经大于等于订单数
                        if (Math.Abs(orderDetail.ReceivedQty) >= Math.Abs(orderDetail.OrderedQty))
                        {
                            throw new BusinessException(Resources.ORD.OrderMaster.Errors_ReceiveQtyExcceedOrderQty, orderDetail.OrderNo, orderDetail.Item);
                        }
                        //sih要求,废品数和不合格品数不占用入库数量
                        else if (!orderMaster.IsReceiveExceed && Math.Abs(orderDetail.ReceivedQty + orderDetail.ReceiveQtyInput) > Math.Abs(orderDetail.OrderedQty))   //不允许过量收货
                        {
                            //订单的收货数 + 本次收货数大于订单数
                            throw new BusinessException(Resources.ORD.OrderMaster.Errors_ReceiveQtyExcceedOrderQty, orderDetail.OrderNo, orderDetail.Item);
                        }
                        //else if (!orderMaster.IsReceiveExceed && Math.Abs(orderDetail.ReceivedQty + orderDetail.RejectedQty + orderDetail.ScrapQty + orderDetail.ReceiveQtyInput + orderDetail.ScrapQtyInput) > Math.Abs(orderDetail.OrderedQty))   //不允许过量收货
                        //{
                        //    //订单的收货数 + 本次收货数大于订单数
                        //    throw new BusinessException(Resources.ORD.OrderMaster.Errors_ReceiveQtyExcceedOrderQty, orderDetail.OrderNo, orderDetail.Item);
                        //}
                    }
                }
                #endregion

                #region 采购收货是否有价格单判断
                //if (orderHead.Type == BusinessConstants.CODE_MASTER_ORDER_TYPE_VALUE_PROCUREMENT
                //    && !bool.Parse(entityPreference.Value))
                //{
                //    if (orderDetail.UnitPrice == Decimal.Zero)
                //    {
                //        //重新查找一次价格
                //        PriceListDetail priceListDetail = priceListDetailMgrE.GetLastestPriceListDetail(
                //            orderDetail.DefaultPriceList,
                //            orderDetail.Item,
                //            orderHead.StartTime,
                //            orderHead.Currency,
                //            orderDetail.Uom);

                //        if (priceListDetail != null)
                //        {
                //            orderDetail.UnitPrice = priceListDetail.UnitPrice;
                //            orderDetail.IsProvisionalEstimate = priceListDetail.IsProvisionalEstimate;
                //            orderDetail.IsIncludeTax = priceListDetail.IsIncludeTax;
                //            orderDetail.TaxCode = priceListDetail.TaxCode;
                //        }
                //        else
                //        {
                //            throw new BusinessErrorException("Order.Error.NoPriceListReceipt", orderDetail.Item.Code);
                //        }
                //    }
                //}
                #endregion

                #region 采购收货是否有计划协议行或PO号
                if (orderMaster.Type == com.Sconit.CodeMaster.OrderType.Procurement)
                {
                    foreach (OrderDetail orderDetail in orderMaster.OrderDetails)
                    {
                        if (string.IsNullOrWhiteSpace(orderDetail.ExternalOrderNo)
                            || string.IsNullOrWhiteSpace(orderDetail.ExternalSequence))
                        {
                            throw new BusinessException("供应商直供要货单{0}物料号{1}的计划协议号或PO号不能为空。", orderDetail.OrderNo, orderDetail.Item);
                        }
                    }
                }
                #endregion
            }
            #endregion

            #region 循环更新订单明细
            foreach (OrderDetail orderDetail in nonZeroOrderDetailList)
            {
                //未发货直接收货需要累加已发货数量
                if (orderDetail.OrderType != com.Sconit.CodeMaster.OrderType.Production
                    && orderDetail.OrderType != com.Sconit.CodeMaster.OrderType.SubContract)
                {
                    orderDetail.ShippedQty += orderDetail.ReceiveQtyInput;
                }

                if (orderDetail.OrderType != com.Sconit.CodeMaster.OrderType.Production
                    && orderDetail.OrderType != com.Sconit.CodeMaster.OrderType.SubContract)
                {
                    //orderDetail.ReceivedQty += orderDetail.ReceiveQualifiedQtyInput;
                    orderDetail.ReceivedQty += orderDetail.ReceiveQtyInput;
                }
                else
                {
                    //生产收货更新合格数和不合格数量
                    //orderDetail.ReceivedQty += orderDetail.ReceiveQualifiedQtyInput;
                    orderDetail.ReceivedQty += orderDetail.ReceiveQtyInput;
                    orderDetail.ScrapQty += orderDetail.ScrapQtyInput;
                }
                genericMgr.Update(orderDetail);
            }
            #endregion

            #region 发货
            #region OrderDetailInput赋发货数量
            foreach (OrderDetail orderDetail in nonZeroOrderDetailList)
            {
                foreach (OrderDetailInput orderDetailInput in orderDetail.OrderDetailInputs)
                {
                    orderDetailInput.ShipQty = orderDetailInput.ReceiveQty;
                }
            }
            #endregion

            IpMaster ipMaster = null;
            if (orderType != com.Sconit.CodeMaster.OrderType.Production
                && orderType != com.Sconit.CodeMaster.OrderType.SubContract)
            {
                ipMaster = this.ipMgr.TransferOrder2Ip(orderMasterList);

                #region 循环发货
                foreach (IpDetail ipDetail in ipMaster.IpDetails)
                {
                    ipDetail.CurrentPartyFrom = ipMaster.PartyFrom;  //为了记录库存事务
                    ipDetail.CurrentPartyFromName = ipMaster.PartyFromName;  //为了记录库存事务
                    ipDetail.CurrentPartyTo = ipMaster.PartyTo;      //为了记录库存事务
                    ipDetail.CurrentPartyToName = ipMaster.PartyToName;      //为了记录库存事务
                    //ipDetail.CurrentOccupyType = com.Sconit.CodeMaster.OccupyType.None; //todo-默认出库未占用库存,除非捡货或检验的出库

                    IList<InventoryTransaction> inventoryTransactionList = this.locationDetailMgr.InventoryOut(ipDetail, effectiveDate);

                    #region 建立发货库明细和IpDetailInput的关系
                    if (inventoryTransactionList != null && inventoryTransactionList.Count > 0)
                    {
                        ipDetail.IpLocationDetails = (from trans in inventoryTransactionList
                                                      group trans by new
                                                      {
                                                          HuId = trans.HuId,
                                                          LotNo = trans.LotNo,
                                                          IsCreatePlanBill = trans.IsCreatePlanBill,
                                                          IsConsignment = trans.IsConsignment,
                                                          PlanBill = trans.PlanBill,
                                                          ActingBill = trans.ActingBill,
                                                          QualityType = trans.QualityType,
                                                          IsFreeze = trans.IsFreeze,
                                                          IsATP = trans.IsATP,
                                                          OccupyType = trans.OccupyType,
                                                          OccupyReferenceNo = trans.OccupyReferenceNo
                                                      } into g
                                                      select new IpLocationDetail
                                                      {
                                                          HuId = g.Key.HuId,
                                                          LotNo = g.Key.LotNo,
                                                          IsCreatePlanBill = g.Key.IsCreatePlanBill,
                                                          IsConsignment = g.Key.IsConsignment,
                                                          PlanBill = g.Key.PlanBill,
                                                          ActingBill = g.Key.ActingBill,
                                                          QualityType = g.Key.QualityType,
                                                          IsFreeze = g.Key.IsFreeze,
                                                          IsATP = g.Key.IsATP,
                                                          OccupyType = g.Key.OccupyType,
                                                          OccupyReferenceNo = g.Key.OccupyReferenceNo,
                                                          Qty = g.Sum(t => -t.Qty),                      //发货的库存事务为负数,转为收货数应该取负数
                                                          //PlanBillQty = g.Sum(t=>-t.PlanBillQty),
                                                          //ActingBillQty = g.Sum(t=>-t.ActingBillQty)
                                                      }).ToList();
                    }
                    #endregion
                }
                #endregion

                #region 生成收货的IpInput
                foreach (OrderDetail orderDetail in nonZeroOrderDetailList)
                {
                    OrderMaster orderMaster = orderMasterList.Where(o => o.OrderNo == orderDetail.OrderNo).Single();
                    //订单收货一定是一条订单明细对应一条发货单明细
                    IpDetail ipDetail = ipMaster.IpDetails.Where(det => det.OrderDetailId == orderDetail.Id).Single();
                    ipDetail.IpDetailInputs = null;  //清空Ip的发货数据,准备添加收货数据

                    foreach (OrderDetailInput orderDetailInput in orderDetail.OrderDetailInputs)
                    {
                        IpDetailInput ipDetailInput = new IpDetailInput();
                        ipDetailInput.ReceiveQty = orderDetailInput.ShipQty;
                        if (orderMaster.IsReceiveScanHu)
                        {
                            ipDetailInput.HuId = orderDetailInput.HuId;
                            ipDetailInput.LotNo = orderDetailInput.LotNo;
                        }

                        ipDetail.AddIpDetailInput(ipDetailInput);
                    }
                }

                #region 订单生成收货Input
                if (ipMaster.IsShipScanHu && ipMaster.IsReceiveScanHu)
                {
                    #region 按条码匹配
                    foreach (IpDetail ipDetail in ipMaster.IpDetails)
                    {
                        foreach (IpDetailInput ipDetailInput in ipDetail.IpDetailInputs)
                        {
                            IpLocationDetail matchedIpLocationDetail = ipDetail.IpLocationDetails.Where(locDet => locDet.HuId == ipDetailInput.HuId).SingleOrDefault();
                            matchedIpLocationDetail.ReceivedQty = matchedIpLocationDetail.Qty;
                            if (matchedIpLocationDetail != null)
                            {
                                ipDetailInput.AddReceivedIpLocationDetail(matchedIpLocationDetail);
                            }
                        }
                    }
                    #endregion
                }
                else
                {
                    #region 按数量匹配
                    foreach (IpDetail ipDetail in ipMaster.IpDetails)
                    {
                        CycleMatchIpDetailInput(ipDetail, ipDetail.IpDetailInputs, ipDetail.IpLocationDetails);
                    }
                    #endregion
                }
                #endregion
                #endregion
            }
            #endregion

            #region 收货
            ReceiptMaster receiptMaster = null;
            if (orderType == com.Sconit.CodeMaster.OrderType.Production
               || orderType == com.Sconit.CodeMaster.OrderType.SubContract)
            {
                #region 生产收货
                if (orderMasterList.Count > 1)
                {
                    throw new TechnicalException("生产单不能合并收货。");
                }

                foreach (OrderMaster orderMaster in orderMasterList)
                {
                    receiptMaster = this.receiptMgr.TransferOrder2Receipt(orderMaster);
                    this.receiptMgr.CreateReceipt(receiptMaster);

                    //在报工的时候反冲物料,收货时不反冲
                    //foreach (OrderDetail orderDetail in nonZeroOrderDetailList)
                    //{
                    //    OrderDetailInput orderDetailInput = orderDetail.OrderDetailInputs[0];
                    //    orderDetailInput.ReceiptDetail = receiptMaster.ReceiptDetails.Where(r => r.OrderDetailId == orderDetail.Id).Single();
                    //}
                    //this.productionLineMgr.BackflushProductOrder(nonZeroOrderDetailList);
                }
                #endregion
            }
            else if (orderType != com.Sconit.CodeMaster.OrderType.Production
                && orderType != com.Sconit.CodeMaster.OrderType.SubContract)
            {
                #region 物流收货
                receiptMaster = this.receiptMgr.TransferIp2Receipt(ipMaster);
                this.receiptMgr.CreateReceipt(receiptMaster, false, effectiveDate);
                #endregion
            }
            #endregion

            #region 尝试关闭订单
            foreach (OrderMaster orderMaster in orderMasterList)
            {
                if (orderMaster.Type == CodeMaster.OrderType.Production)
                {
                    #region 生产
                    TryCloseOrder(orderMaster);
                    #endregion
                }
                else
                {
                    #region 物流
                    TryCloseOrder(orderMaster);
                    #endregion
                }
            }
            #endregion

            return receiptMaster;
        }