private InventoryTransaction CreateInventoryTransaction(InventoryIO inventoryIO, decimal qty, LocationLotDetail backFlushLocLotDet, SettleBillTransaction billTransaction)
        {
            InventoryTransaction inventoryTransaction = new InventoryTransaction();
            inventoryTransaction.LocationLotDetailId = backFlushLocLotDet.Id;
            inventoryTransaction.Location = inventoryIO.Location;
            inventoryTransaction.Bin = inventoryIO.Bin;
            inventoryTransaction.Item = inventoryIO.Item;
            inventoryTransaction.HuId = inventoryIO.HuId;
            inventoryTransaction.LotNo = inventoryIO.LotNo;
            inventoryTransaction.IsCreatePlanBill = inventoryIO.IsCreatePlanBill;
            inventoryTransaction.IsConsignment = inventoryIO.IsConsignment;
            inventoryTransaction.PlanBill = inventoryIO.PlanBill;
            if (inventoryIO.IsConsignment)
            {
                //寄售库存
                inventoryTransaction.PlanBillQty = qty;
            }
            if (billTransaction != null)   //发生了结算,记录结算数量
            {
                inventoryTransaction.BillTransactionId = billTransaction.Id;
                inventoryTransaction.IsConsignment = false;
                inventoryTransaction.ActingBill = billTransaction.ActingBill;
                inventoryTransaction.ActingBillQty = qty;             //基本单位
                inventoryTransaction.PlanBillQty = inventoryIO.Qty - qty;
            }
            inventoryTransaction.Qty = qty;
            inventoryTransaction.QualityType = inventoryIO.QualityType;
            inventoryTransaction.IsATP = inventoryIO.IsATP;
            inventoryTransaction.IsFreeze = inventoryIO.IsFreeze;
            inventoryTransaction.OccupyType = inventoryIO.OccupyType;
            inventoryTransaction.OccupyReferenceNo = inventoryIO.OccupyReferenceNo;

            return inventoryTransaction;
        }
        public IList<InventoryTransaction> InventoryIn(ReceiptDetail receiptDetail, DateTime effectiveDate)
        {
            List<InventoryTransaction> inventoryTransactionList = new List<InventoryTransaction>();
            com.Sconit.CodeMaster.TransactionType? transType = GetTransactionType(receiptDetail);
            if (transType.HasValue)
            {
                #region 收货冲销,如果一个条码对应多条receiptDetailInput,需要先拆箱
                if (receiptDetail.IsVoid)
                {
                    var groupedHuIdList = from det in receiptDetail.ReceiptDetailInputs
                                          where !string.IsNullOrWhiteSpace(det.HuId)
                                          group det by det.HuId into gj
                                          select new
                                          {
                                              HuId = gj.Key,
                                              ReceiptDetailInputList = gj.ToList()
                                          };

                    if (groupedHuIdList != null && groupedHuIdList.Count() > 0)
                    {
                        //已知Bug,如果收货时不结算,两条不同的PlanBill生成条码会强制结算。但是在冲销时不会反结算。
                        #region 循环拆箱
                        foreach (var groupedHuId in groupedHuIdList.Where(g => g.ReceiptDetailInputList.Count() > 1))
                        {
                            InventoryUnPack inventoryUnPack = new InventoryUnPack();

                            inventoryUnPack.HuId = groupedHuId.HuId;
                            inventoryUnPack.CurrentHu = this.huMgr.GetHuStatus(groupedHuId.HuId);
                            IList<InventoryUnPack> inventoryUnPackList = new List<InventoryUnPack>();
                            inventoryUnPackList.Add(inventoryUnPack);
                            this.InventoryUnPack(inventoryUnPackList, effectiveDate);

                            foreach (ReceiptDetailInput receiptDetailInput in groupedHuId.ReceiptDetailInputList)
                            {
                                //把ReceiptDetailInput的HuId和LotNo至空,按数量出库。
                                receiptDetailInput.HuId = null;
                                receiptDetailInput.LotNo = null;
                                receiptDetailInput.IsConsignment = false;
                                receiptDetailInput.PlanBill = null;
                            }
                        }
                        #endregion

                        this.genericMgr.FlushSession();
                    }
                }
                #endregion

                foreach (ReceiptDetailInput receiptDetailInput in receiptDetail.ReceiptDetailInputs)
                {
                    if (receiptDetailInput.ReceivedIpLocationDetailList != null && receiptDetailInput.ReceivedIpLocationDetailList.Count > 0)
                    {
                        List<InventoryTransaction> currentReceiptDetailInputInventoryTransactionList = new List<InventoryTransaction>();
                        #region 基于Ip收货,零件的寄售信息都在IpLocationDetail上面
                        foreach (IpLocationDetail receivedIpLocationDetail in receiptDetailInput.ReceivedIpLocationDetailList)
                        {
                            ReceiptDetailInput thisReceiptDetailInput = Mapper.Map<ReceiptDetailInput, ReceiptDetailInput>(receiptDetailInput);
                            thisReceiptDetailInput.ReceiveQty = (decimal)receivedIpLocationDetail.ReceivedQty / receiptDetail.UnitQty;
                            if (receiptDetail.CurrentIsReceiveScanHu && !string.IsNullOrWhiteSpace(receivedIpLocationDetail.HuId))
                            {
                                thisReceiptDetailInput.HuId = receivedIpLocationDetail.HuId;
                                thisReceiptDetailInput.LotNo = receivedIpLocationDetail.LotNo;
                            }

                            InventoryIO inventoryIO = new InventoryIO();

                            inventoryIO.Location = receiptDetail.LocationTo;
                            inventoryIO.Item = receiptDetail.Item;
                            if (receiptDetail.CurrentIsReceiveScanHu && receiptDetailInput.ReceivedIpLocationDetailList.Count == 1)
                            {
                                //如果收货扫描条码,并且只有一条发货库存明细,可以直接收为条码
                                //要用收货Input上指定的条码
                                inventoryIO.HuId = thisReceiptDetailInput.HuId;
                                inventoryIO.LotNo = thisReceiptDetailInput.LotNo;
                            }
                            inventoryIO.Qty = receivedIpLocationDetail.ReceivedQty;             //库存单位
                            inventoryIO.QualityType = receivedIpLocationDetail.QualityType;     //不合格品的ATP状态一定是false,合格品的状态一定是true,质检不采用ASN发货这里不可能出现
                            inventoryIO.IsATP = receivedIpLocationDetail.QualityType == com.Sconit.CodeMaster.QualityType.Qualified;
                            inventoryIO.IsFreeze = false;                       //可能指定移库冻结的零件?
                            inventoryIO.IsCreatePlanBill = receivedIpLocationDetail.IsCreatePlanBill;
                            inventoryIO.IsConsignment = receivedIpLocationDetail.IsConsignment;
                            inventoryIO.PlanBill = receivedIpLocationDetail.PlanBill;
                            inventoryIO.ActingBill = receivedIpLocationDetail.ActingBill;
                            inventoryIO.TransactionType = transType.Value;
                            //if (receivedIpLocationDetail.OccupyType == CodeMaster.OccupyType.Inspect)   //只有检验的收货要保留占用,其它收货不用保留
                            //{
                            inventoryIO.OccupyType = receivedIpLocationDetail.OccupyType;
                            inventoryIO.OccupyReferenceNo = receivedIpLocationDetail.OccupyReferenceNo;
                            //}
                            //inventoryIO.IsVoid = receiptDetail.IsVoid;
                            inventoryIO.EffectiveDate = effectiveDate;

                            #region 寄售处理
                            if (!receiptDetail.IsVoid &&
                                (((receiptDetail.OrderType == com.Sconit.CodeMaster.OrderType.Procurement
                                || receiptDetail.OrderType == com.Sconit.CodeMaster.OrderType.ScheduleLine)
                                && receiptDetail.OrderSubType == com.Sconit.CodeMaster.OrderSubType.Normal)
                               || (receiptDetail.OrderType == com.Sconit.CodeMaster.OrderType.Distribution
                                    && transType != CodeMaster.TransactionType.RCT_TR)  //差异调整至发货方,不用产生结算
                               || receiptDetail.OrderType == com.Sconit.CodeMaster.OrderType.SubContract))
                            {
                                if (receivedIpLocationDetail.IsConsignment && receivedIpLocationDetail.PlanBill.HasValue)
                                {
                                    throw new TechnicalException("Can't create new planbill when receiptDetailInput aready has unsettled planbill.");
                                }
                                else
                                {
                                    #region 记录待结算
                                    PlanBill planBill = this.billMgr.CreatePlanBill(receiptDetail, thisReceiptDetailInput, effectiveDate);

                                    inventoryIO.IsConsignment = true;
                                    inventoryIO.IsCreatePlanBill = true;
                                    inventoryIO.PlanBill = planBill.Id;
                                    inventoryIO.CurrentPlanBill = planBill;

                                    thisReceiptDetailInput.IsConsignment = true;
                                    thisReceiptDetailInput.IsCreatePlanBill = true;
                                    thisReceiptDetailInput.PlanBill = planBill.Id;
                                    #endregion
                                }
                            }
                            #endregion

                            IList<InventoryTransaction> currentInventoryTransactionList = RecordInventory(inventoryIO);
                            #region 记录HuId,LotNo和WMS发货单行号
                            foreach (InventoryTransaction currentInventoryTransaction in currentInventoryTransactionList)
                            {
                                if (receiptDetail.CurrentIsReceiveScanHu && receiptDetailInput.ReceivedIpLocationDetailList.Count > 1
                                    && !string.IsNullOrWhiteSpace(receiptDetailInput.HuId))
                                {
                                    Hu hu = this.genericMgr.FindById<Hu>(receiptDetailInput.HuId);
                                    currentInventoryTransaction.HuId = hu.HuId;
                                    currentInventoryTransaction.LotNo = hu.LotNo;
                                }
                                currentInventoryTransaction.WMSRecSeq = receiptDetailInput.WMSRecSeq;
                            }
                            #endregion

                            RecordLocationTransaction(receiptDetail, thisReceiptDetailInput, effectiveDate, transType.Value, currentInventoryTransactionList);
                            inventoryTransactionList.AddRange(currentInventoryTransactionList);
                            currentReceiptDetailInputInventoryTransactionList.AddRange(currentInventoryTransactionList);
                        }

                        #region 收货扫描条码,需要装箱创建条码
                        if (receiptDetail.CurrentIsReceiveScanHu && receiptDetailInput.ReceivedIpLocationDetailList.Count > 1
                            && !string.IsNullOrWhiteSpace(receiptDetailInput.HuId))
                        {
                            #region 装箱
                            IList<InventoryPack> inventoryPackList = new List<InventoryPack>();
                            InventoryPack inventoryPack = new InventoryPack();
                            inventoryPack.Location = receiptDetail.LocationTo;
                            inventoryPack.HuId = receiptDetailInput.HuId;
                            inventoryPack.LocationLotDetailIdList = currentReceiptDetailInputInventoryTransactionList.Select(inv => inv.LocationLotDetailId).ToList();

                            inventoryPackList.Add(inventoryPack);
                            this.InventoryPack(inventoryPackList, effectiveDate);
                            #endregion
                        }
                        #endregion
                        #endregion
                    }
                    else
                    {
                        #region 基于ReceiptDetailInput收货
                        InventoryIO inventoryIO = new InventoryIO();

                        inventoryIO.Location = receiptDetail.LocationTo;
                        inventoryIO.Item = receiptDetail.Item;
                        inventoryIO.HuId = receiptDetailInput.HuId;
                        inventoryIO.LotNo = receiptDetailInput.LotNo;
                        inventoryIO.Qty = receiptDetailInput.ReceiveQty * receiptDetail.UnitQty;  //转换为库存单位
                        inventoryIO.QualityType = receiptDetailInput.QualityType;     //不合格品的ATP状态一定是false,合格品的状态一定是true,质检不采用ASN发货这里不可能出现
                        inventoryIO.IsATP = receiptDetailInput.QualityType == com.Sconit.CodeMaster.QualityType.Qualified;
                        inventoryIO.IsFreeze = false;                       //可能指定移库冻结的零件?
                        inventoryIO.IsCreatePlanBill = receiptDetailInput.IsCreatePlanBill;
                        inventoryIO.IsConsignment = receiptDetailInput.IsConsignment;
                        inventoryIO.PlanBill = receiptDetailInput.PlanBill;
                        inventoryIO.ActingBill = receiptDetailInput.ActingBill;
                        inventoryIO.TransactionType = transType.Value;
                        inventoryIO.OccupyType = receiptDetailInput.OccupyType;
                        inventoryIO.OccupyReferenceNo = receiptDetailInput.OccupyReferenceNo;
                        inventoryIO.IsVoid = receiptDetail.IsVoid;
                        inventoryIO.EffectiveDate = effectiveDate;
                        //inventoryIO.ManufactureParty = ;

                        #region 寄售处理
                        if (!receiptDetail.IsVoid &&
                            (((receiptDetail.OrderType == com.Sconit.CodeMaster.OrderType.Procurement
                            || receiptDetail.OrderType == com.Sconit.CodeMaster.OrderType.ScheduleLine)
                            && receiptDetail.OrderSubType == com.Sconit.CodeMaster.OrderSubType.Normal)
                           || (receiptDetail.OrderType == com.Sconit.CodeMaster.OrderType.Distribution
                                && transType != CodeMaster.TransactionType.RCT_TR)  //差异调整至发货方,不用产生结算
                           || receiptDetail.OrderType == com.Sconit.CodeMaster.OrderType.SubContract))
                        {
                            if (receiptDetailInput.IsConsignment && receiptDetailInput.PlanBill.HasValue)
                            {
                                throw new TechnicalException("Can't create new planbill when receiptDetailInput aready has unsettled planbill.");
                            }

                            #region 记录待结算
                            PlanBill planBill = this.billMgr.CreatePlanBill(receiptDetail, receiptDetailInput, effectiveDate);

                            inventoryIO.IsConsignment = true;
                            inventoryIO.IsCreatePlanBill = true;
                            inventoryIO.PlanBill = planBill.Id;
                            inventoryIO.CurrentPlanBill = planBill;

                            receiptDetailInput.IsConsignment = true;
                            receiptDetailInput.IsCreatePlanBill = true;
                            receiptDetailInput.PlanBill = planBill.Id;
                            #endregion

                            #region 判断是否立即结算
                            //if (receiptDetail.OrderType == com.Sconit.CodeMaster.OrderType.SubContract)   //委外加工立即结算
                            //{
                            //    isBillSettle = true;
                            //}
                            //else if (receiptDetail.ReceivedQty < 0)  // 判断寄售负库存是否立即结算
                            //{
                            //    isBillSettle = true;
                            //}
                            //else if (string.IsNullOrWhiteSpace(receiptDetail.LocationTo) == null
                            //    && receiptDetail.BillTerm == com.Sconit.CodeMaster.OrderBillTerm.ReceivingSettlement) //判断目的库位为空的立即结算,如销售收货结算
                            //{
                            //    isBillSettle = true;
                            //}

                            //if (isBillSettle)
                            //{
                            //    //结算
                            //    planBill.CurrentActingQty = planBill.PlanQty;
                            //    BillTransaction billTransaction = this.billMgr.SettleBill(planBill, effectiveDate);
                            //    inventoryIO.IsConsignment = false;
                            //    receiptDetailInput.IsConsignment = false;
                            //}
                            #endregion
                        }
                        #endregion

                        IList<InventoryTransaction> currentInventoryTransactionList = RecordInventory(inventoryIO);
                        #region 记录WMS发货单行号
                        foreach (InventoryTransaction currentInventoryTransaction in currentInventoryTransactionList)
                        {
                            currentInventoryTransaction.WMSRecSeq = receiptDetailInput.WMSRecSeq;
                        }
                        #endregion
                        RecordLocationTransaction(receiptDetail, receiptDetailInput, effectiveDate, transType.Value, currentInventoryTransactionList);
                        inventoryTransactionList.AddRange(currentInventoryTransactionList);
                        #endregion
                    }
                }

                return inventoryTransactionList;
            }
            else if ((receiptDetail.OrderType == com.Sconit.CodeMaster.OrderType.Procurement
                    || receiptDetail.OrderType == com.Sconit.CodeMaster.OrderType.ScheduleLine
                    || receiptDetail.OrderType == com.Sconit.CodeMaster.OrderType.SubContract)
                  && receiptDetail.OrderSubType == com.Sconit.CodeMaster.OrderSubType.Return)
            {
                #region 采购退货收货
                if (!receiptDetail.IsVoid)
                {
                    foreach (ReceiptDetailInput receiptDetailInput in receiptDetail.ReceiptDetailInputs)
                    {
                        foreach (IpLocationDetail receivedIpLocationDetail in receiptDetailInput.ReceivedIpLocationDetailList)
                        {
                            InventoryTransaction inventoryTransaction = new InventoryTransaction();
                            inventoryTransaction.Item = receiptDetail.Item;
                            inventoryTransaction.HuId = receiptDetailInput.HuId;
                            inventoryTransaction.LotNo = receiptDetailInput.LotNo;
                            inventoryTransaction.IsConsignment = receivedIpLocationDetail.IsConsignment;
                            //inventoryTransaction.IsCreatePlanBill = receiptDetailInput.IsCreatePlanBill;
                            inventoryTransaction.PlanBill = receivedIpLocationDetail.PlanBill;
                            if (receivedIpLocationDetail.IsConsignment && receivedIpLocationDetail.PlanBill.HasValue)
                            {
                                inventoryTransaction.PlanBillQty = receivedIpLocationDetail.ReceivedQty;  //转换为库存单位
                            }
                            //inventoryTransaction.ActingBill = receiptDetailInput.ActingBill;
                            //inventoryTransaction.ActingBillQty = ;
                            inventoryTransaction.Qty = receivedIpLocationDetail.ReceivedQty;  //转换为库存单位,入库位正数
                            inventoryTransaction.QualityType = receiptDetailInput.QualityType;
                            inventoryTransaction.IsATP = receiptDetailInput.QualityType == com.Sconit.CodeMaster.QualityType.Qualified;
                            inventoryTransaction.IsFreeze = false;
                            inventoryTransaction.OccupyType = receiptDetailInput.OccupyType;
                            inventoryTransaction.OccupyReferenceNo = receiptDetailInput.OccupyReferenceNo;

                            #region 退货收货
                            if (receivedIpLocationDetail.IsConsignment && receivedIpLocationDetail.PlanBill.HasValue)
                            {
                                //如果寄售库存,冲销PlanBill。
                                PlanBill planBill = this.genericMgr.FindById<PlanBill>(receivedIpLocationDetail.PlanBill.Value);
                                planBill.CurrentVoidQty = receivedIpLocationDetail.ReceivedQty / receiptDetail.UnitQty;  //订单单位
                                this.billMgr.VoidPlanBill(planBill);

                                //inventoryTransaction.IsConsignment = false;
                                //inventoryTransaction.PlanBill = null;
                            }
                            else
                            {
                                //非寄售库存产生负数PlanBill,立即结算。
                                ReceiptDetailInput thisReceiptDetailInput = Mapper.Map<ReceiptDetailInput, ReceiptDetailInput>(receiptDetailInput);
                                thisReceiptDetailInput.ReceiveQty = receivedIpLocationDetail.ReceivedQty / receiptDetail.UnitQty;   //订单单位

                                PlanBill planBill = this.billMgr.CreatePlanBill(receiptDetail, thisReceiptDetailInput, effectiveDate);
                                planBill.CurrentActingQty = planBill.PlanQty;
                                planBill.CurrentLocation = inventoryTransaction.Location;
                                SettleBillTransaction billTransaction = this.billMgr.SettleBill(planBill, effectiveDate);

                                inventoryTransaction.IsConsignment = false;
                                inventoryTransaction.IsCreatePlanBill = true;
                                inventoryTransaction.PlanBill = planBill.Id;
                                inventoryTransaction.PlanBillQty = 0;
                                inventoryTransaction.ActingBill = billTransaction.ActingBill;
                                inventoryTransaction.ActingBillQty = receiptDetailInput.ReceiveQty * receiptDetail.UnitQty;
                            }
                            #endregion

                            inventoryTransactionList.Add(inventoryTransaction);
                        }
                    }
                }
                #endregion

                #region 采购退货收货冲销
                else
                {
                    #region 采购退货收货冲销
                    foreach (ReceiptLocationDetail receiptLocationDetail in receiptDetail.ReceiptLocationDetails)
                    {
                        InventoryTransaction inventoryTransaction = new InventoryTransaction();
                        inventoryTransaction.Item = receiptDetail.Item;
                        inventoryTransaction.HuId = receiptLocationDetail.HuId;
                        inventoryTransaction.LotNo = receiptLocationDetail.LotNo;
                        inventoryTransaction.IsConsignment = receiptLocationDetail.IsConsignment;
                        //inventoryTransaction.IsCreatePlanBill = receiptDetailInput.IsCreatePlanBill;
                        inventoryTransaction.PlanBill = receiptLocationDetail.PlanBill;
                        if (receiptLocationDetail.IsConsignment && receiptLocationDetail.PlanBill.HasValue)
                        {
                            inventoryTransaction.PlanBillQty = receiptLocationDetail.Qty;  //转换为库存单位
                        }
                        //inventoryTransaction.ActingBill = receiptDetailInput.ActingBill;
                        //inventoryTransaction.ActingBillQty = ;
                        inventoryTransaction.Qty = receiptLocationDetail.Qty;  //转换为库存单位,入库位正数
                        inventoryTransaction.QualityType = receiptLocationDetail.QualityType;
                        inventoryTransaction.IsATP = receiptLocationDetail.QualityType == com.Sconit.CodeMaster.QualityType.Qualified;
                        inventoryTransaction.IsFreeze = false;
                        inventoryTransaction.OccupyType = receiptLocationDetail.OccupyType;
                        inventoryTransaction.OccupyReferenceNo = receiptLocationDetail.OccupyReferenceNo;

                        if (receiptLocationDetail.IsConsignment && receiptLocationDetail.PlanBill.HasValue)
                        {
                            PlanBill planBill = this.genericMgr.FindById<PlanBill>(receiptLocationDetail.PlanBill);
                            planBill.CurrentVoidQty = -receiptLocationDetail.Qty / receiptDetail.UnitQty;  //退货收货冲销,要反冲销PlanQty。转为订单单位
                            this.billMgr.VoidPlanBill(planBill);
                        }

                        if (receiptLocationDetail.ActingBill.HasValue)
                        {
                            ActingBill actingBill = this.genericMgr.FindById<ActingBill>(receiptLocationDetail.ActingBill);
                            PlanBill planBill = this.genericMgr.FindById<PlanBill>(receiptLocationDetail.PlanBill);
                            actingBill.CurrentVoidQty = -receiptLocationDetail.Qty / receiptDetail.UnitQty;   //转为订单单位
                            this.billMgr.VoidSettleBill(actingBill, planBill, receiptLocationDetail.IsCreatePlanBill);
                        }

                        inventoryTransactionList.Add(inventoryTransaction);
                    }
                    #endregion
                }
                #endregion

                return inventoryTransactionList;
            }
            else if ((receiptDetail.OrderType == com.Sconit.CodeMaster.OrderType.Procurement
                        || receiptDetail.OrderType == com.Sconit.CodeMaster.OrderType.ScheduleLine
                        || receiptDetail.OrderType == com.Sconit.CodeMaster.OrderType.SubContract)
                    && receiptDetail.IpDetailType == CodeMaster.IpDetailType.Gap
                    && receiptDetail.IpGapAdjustOption == CodeMaster.IpGapAdjustOption.GI)
            {
                #region 差异收货调整至供应商
                foreach (ReceiptDetailInput receiptDetailInput in receiptDetail.ReceiptDetailInputs)
                {
                    InventoryTransaction inventoryTransaction = new InventoryTransaction();
                    inventoryTransaction.Item = receiptDetail.Item;
                    inventoryTransaction.HuId = receiptDetailInput.HuId;
                    inventoryTransaction.LotNo = receiptDetailInput.LotNo;
                    inventoryTransaction.IsConsignment = false;
                    inventoryTransaction.IsCreatePlanBill = false;
                    //inventoryTransaction.PlanBill = receiptDetailInput.PlanBill;
                    //inventoryTransaction.PlanBillQty = receiptDetailInput.ReceiveQty * receiptDetail.UnitQty;  //转换为库存单位
                    //inventoryTransaction.ActingBill = receiptDetailInput.ActingBill;
                    //inventoryTransaction.ActingBillQty = ;
                    inventoryTransaction.Qty = receiptDetailInput.ReceiveQty * receiptDetail.UnitQty;  //转换为库存单位,入库位正数
                    inventoryTransaction.QualityType = receiptDetailInput.QualityType;
                    inventoryTransaction.IsATP = receiptDetailInput.QualityType == com.Sconit.CodeMaster.QualityType.Qualified;
                    inventoryTransaction.IsFreeze = false;
                    //inventoryTransaction.OccupyType = receiptDetailInput.OccupyType;
                    //inventoryTransaction.OccupyReferenceNo = receiptDetailInput.OccupyReferenceNo;

                    inventoryTransactionList.Add(inventoryTransaction);
                }
                #endregion
            }
            else if (receiptDetail.OrderType == com.Sconit.CodeMaster.OrderType.Production
                && receiptDetail.OrderSubType == com.Sconit.CodeMaster.OrderSubType.Return)
            {
                #region 原材料回用
                foreach (ReceiptDetailInput receiptDetailInput in receiptDetail.ReceiptDetailInputs)
                {
                    InventoryTransaction inventoryTransaction = new InventoryTransaction();
                    inventoryTransaction.Item = receiptDetail.Item;
                    inventoryTransaction.HuId = receiptDetailInput.HuId;
                    inventoryTransaction.LotNo = receiptDetailInput.LotNo;
                    inventoryTransaction.IsConsignment = false;
                    inventoryTransaction.IsCreatePlanBill = false;
                    //inventoryTransaction.PlanBill = receiptDetailInput.PlanBill;
                    //inventoryTransaction.PlanBillQty = receiptDetailInput.ReceiveQty * receiptDetail.UnitQty;  //转换为库存单位
                    //inventoryTransaction.ActingBill = receiptDetailInput.ActingBill;
                    //inventoryTransaction.ActingBillQty = ;
                    inventoryTransaction.Qty = receiptDetailInput.ReceiveQty * receiptDetail.UnitQty;  //转换为库存单位,入库位正数
                    inventoryTransaction.QualityType = receiptDetailInput.QualityType;
                    inventoryTransaction.IsATP = receiptDetailInput.QualityType == com.Sconit.CodeMaster.QualityType.Qualified;
                    inventoryTransaction.IsFreeze = false;
                    //inventoryTransaction.OccupyType = receiptDetailInput.OccupyType;
                    //inventoryTransaction.OccupyReferenceNo = receiptDetailInput.OccupyReferenceNo;

                    inventoryTransactionList.Add(inventoryTransaction);
                }
                #endregion
            }
            else if (receiptDetail.OrderType == com.Sconit.CodeMaster.OrderType.Distribution
                  && receiptDetail.OrderSubType == com.Sconit.CodeMaster.OrderSubType.Normal)
            {
                #region 销售收货
                foreach (ReceiptDetailInput receiptDetailInput in receiptDetail.ReceiptDetailInputs)
                {
                    InventoryTransaction inventoryTransaction = new InventoryTransaction();
                    inventoryTransaction.Item = receiptDetail.Item;
                    inventoryTransaction.HuId = receiptDetailInput.HuId;
                    inventoryTransaction.LotNo = receiptDetailInput.LotNo;
                    //inventoryTransaction.IsConsignment = receiptDetailInput.IsConsignment;
                    //inventoryTransaction.IsCreatePlanBill = receiptDetailInput.IsCreatePlanBill;
                    //inventoryTransaction.PlanBill = receiptDetailInput.PlanBill;
                    //inventoryTransaction.ActingBill = receiptDetailInput.ActingBill;
                    inventoryTransaction.Qty = receiptDetailInput.ReceiveQty * receiptDetail.UnitQty;  //转换为库存单位,入库位正数
                    inventoryTransaction.QualityType = receiptDetailInput.QualityType;
                    inventoryTransaction.IsATP = receiptDetailInput.QualityType == com.Sconit.CodeMaster.QualityType.Qualified;
                    inventoryTransaction.IsFreeze = false;
                    inventoryTransaction.OccupyType = receiptDetailInput.OccupyType;
                    inventoryTransaction.OccupyReferenceNo = receiptDetailInput.OccupyReferenceNo;

                    if (!receiptDetail.IsVoid)
                    {
                        #region 收货
                        PlanBill planBill = this.billMgr.CreatePlanBill(receiptDetail, receiptDetailInput, effectiveDate);
                        inventoryTransaction.IsConsignment = true;
                        inventoryTransaction.IsCreatePlanBill = true;
                        inventoryTransaction.PlanBill = planBill.Id;

                        if (receiptDetail.BillTerm == com.Sconit.CodeMaster.OrderBillTerm.ReceivingSettlement)
                        {
                            planBill.CurrentActingQty = planBill.PlanQty;
                            planBill.CurrentLocation = planBill.LocationFrom;
                            SettleBillTransaction billTransaction = this.billMgr.SettleBill(planBill, effectiveDate);

                            inventoryTransaction.IsConsignment = false;
                            inventoryTransaction.PlanBillQty = 0;
                            inventoryTransaction.ActingBill = billTransaction.ActingBill;
                            inventoryTransaction.ActingBillQty = receiptDetailInput.ReceiveQty * receiptDetail.UnitQty;
                        }
                        #endregion
                    }
                    else
                    {
                        #region 收货冲销
                        if (receiptDetailInput.ActingBill.HasValue)
                        {
                            ActingBill actingBill = this.genericMgr.FindById<ActingBill>(receiptDetailInput.ActingBill);
                            PlanBill planBill = this.genericMgr.FindById<PlanBill>(receiptDetailInput.PlanBill);
                            actingBill.CurrentVoidQty = -receiptDetailInput.ReceiveQty;
                            this.billMgr.VoidSettleBill(actingBill, planBill, receiptDetailInput.IsCreatePlanBill);
                        }
                        else if (receiptDetailInput.IsCreatePlanBill)
                        {
                            PlanBill planBill = this.genericMgr.FindById<PlanBill>(receiptDetailInput.PlanBill);
                            planBill.CurrentVoidQty = -receiptDetailInput.ReceiveQty;
                            this.billMgr.VoidPlanBill(planBill);
                        }
                        #endregion
                    }

                    inventoryTransactionList.Add(inventoryTransaction);
                }
                #endregion
            }
            else
            {
                throw new TechnicalException("未知情况,需要跟踪。");
            }

            return inventoryTransactionList;
        }
        private InventoryTransaction CreateInventoryTransaction(LocationLotDetail locationLotDetail, decimal qty, bool isCreatePlanBill, SettleBillTransaction billTransaction)
        {
            InventoryTransaction inventoryTransaction = new InventoryTransaction();
            inventoryTransaction.LocationLotDetailId = locationLotDetail.Id;
            inventoryTransaction.Location = locationLotDetail.Location;
            inventoryTransaction.Bin = locationLotDetail.Bin;
            inventoryTransaction.Item = locationLotDetail.Item;
            inventoryTransaction.HuId = locationLotDetail.HuId;
            inventoryTransaction.LotNo = locationLotDetail.LotNo;
            inventoryTransaction.IsConsignment = locationLotDetail.IsConsignment;
            inventoryTransaction.IsCreatePlanBill = isCreatePlanBill;
            inventoryTransaction.PlanBill = locationLotDetail.PlanBill;
            if (locationLotDetail.IsConsignment)
            {
                //寄售库存
                inventoryTransaction.PlanBillQty = qty;
            }
            if (billTransaction != null)   //发生了结算,记录结算数量
            {
                inventoryTransaction.BillTransactionId = billTransaction.Id;
                //inventoryTransaction.IsConsignment = false;
                inventoryTransaction.ActingBill = billTransaction.ActingBill;
                inventoryTransaction.ActingBillQty = qty;
                inventoryTransaction.PlanBillQty = 0;
            }
            inventoryTransaction.Qty = qty;
            inventoryTransaction.QualityType = locationLotDetail.QualityType;
            inventoryTransaction.IsATP = locationLotDetail.IsATP;
            inventoryTransaction.IsFreeze = locationLotDetail.IsFreeze;
            inventoryTransaction.OccupyType = locationLotDetail.OccupyType;
            inventoryTransaction.OccupyReferenceNo = locationLotDetail.OccupyReferenceNo;

            return inventoryTransaction;
        }
        public IList<InventoryTransaction> InventoryOut(IpDetail ipDetail, DateTime effectiveDate)
        {
            List<InventoryTransaction> inventoryTransactionList = new List<InventoryTransaction>();
            com.Sconit.CodeMaster.TransactionType? transType = GetTransactionType(ipDetail);
            if (transType.HasValue)
            {
                foreach (IpDetailInput ipDetailInput in ipDetail.IpDetailInputs)
                {
                    InventoryIO inventoryIO = new InventoryIO();

                    inventoryIO.Location = ipDetail.LocationFrom;
                    inventoryIO.Item = ipDetail.Item;
                    inventoryIO.HuId = ipDetailInput.HuId;
                    inventoryIO.Qty = -ipDetailInput.ShipQty * ipDetail.UnitQty;  //转换为库存单位,发货为负数
                    inventoryIO.LotNo = ipDetailInput.LotNo;
                    inventoryIO.QualityType = ipDetail.QualityType;     //不合格品的ATP状态一定是false,合格品的状态一定是true,质检不采用ASN发货这里不可能出现
                    inventoryIO.IsATP = ipDetail.QualityType == com.Sconit.CodeMaster.QualityType.Qualified;
                    inventoryIO.IsFreeze = false;                       //可能指定移库冻结的零件?
                    inventoryIO.IsCreatePlanBill = ipDetailInput.IsCreatePlanBill;
                    inventoryIO.IsConsignment = ipDetailInput.IsConsignment;
                    inventoryIO.PlanBill = ipDetailInput.PlanBill;
                    inventoryIO.ActingBill = ipDetailInput.ActingBill;
                    inventoryIO.TransactionType = transType.Value;
                    //if (ipDetail.CurrentOccupyType == com.Sconit.CodeMaster.OccupyType.Pick)
                    //{
                    //    //发货不能发捡货单占用的零件
                    //    throw new TechnicalException("Can't ship material occupied by picklist.");
                    //}
                    //else if (ipDetail.CurrentOccupyType == com.Sconit.CodeMaster.OccupyType.Inspect
                    //    && (transType.Value != com.Sconit.CodeMaster.TransactionType.ISS_TR
                    //    || transType.Value != com.Sconit.CodeMaster.TransactionType.ISS_TR_VOID))
                    //{
                    //    //检验、不合格品占用的零件只能做移库及移库冲销
                    //    throw new TechnicalException("Can't ship material occupied by inspect order.");
                    //}
                    inventoryIO.OccupyType = ipDetailInput.OccupyType;
                    inventoryIO.OccupyReferenceNo = ipDetailInput.OccupyReferenceNo;
                    inventoryIO.IsVoid = ipDetail.IsVoid;
                    inventoryIO.EffectiveDate = effectiveDate;
                    inventoryIO.ManufactureParty = ipDetailInput.ManufactureParty;

                    IList<InventoryTransaction> currentInventoryTransactionList = RecordInventory(inventoryIO);
                    #region 记录WMS发货单行号
                    foreach (InventoryTransaction currentInventoryTransaction in currentInventoryTransactionList)
                    {
                        currentInventoryTransaction.WMSIpSeq = ipDetailInput.WMSIpSeq;
                    }
                    #endregion
                    RecordLocationTransaction(ipDetail, ipDetailInput, effectiveDate, transType.Value, currentInventoryTransactionList);
                    inventoryTransactionList.AddRange(currentInventoryTransactionList);
                }
            }
            //else if (ipDetail.OrderType == com.Sconit.CodeMaster.OrderType.Procurement
            //    && ipDetail.OrderSubType == com.Sconit.CodeMaster.OrderSubType.Normal)
            //{
            //    #region 采购发货为供应商生成在途寄售物料
            //    foreach (IpDetailInput ipDetailInput in ipDetail.IpDetailInputs)
            //    {
            //        inventoryTransactionList = new List<InventoryTransaction>();

            //        InventoryTransaction inventoryTransaction = new InventoryTransaction();
            //        inventoryTransaction.Item = ipDetail.Item;
            //        inventoryTransaction.HuId = ipDetailInput.HuId;
            //        inventoryTransaction.LotNo = ipDetailInput.LotNo;
            //        inventoryTransaction.IsConsignment = true;
            //        inventoryTransaction.IsCreatePlanBill = true;
            //        PlanBill planBill = this.billMgr.CreatePlanBill(ipDetail, ipDetailInput, effectiveDate);
            //        inventoryTransaction.PlanBill = planBill.Id;
            //        inventoryTransaction.Qty = ipDetailInput.ShipQty;
            //        inventoryTransaction.QualityType = ipDetail.QualityType;
            //        inventoryTransaction.IsATP = ipDetail.QualityType == com.Sconit.CodeMaster.QualityType.Qualified;
            //        inventoryTransaction.IsFreeze = false;
            //        inventoryTransaction.OccupyType = com.Sconit.CodeMaster.OccupyType.None;
            //        inventoryTransactionList.Add(inventoryTransaction);
            //    }
            //    #endregion
            //}
            else if (((ipDetail.OrderType == com.Sconit.CodeMaster.OrderType.Procurement    //采购发货
                        || ipDetail.OrderType == com.Sconit.CodeMaster.OrderType.ScheduleLine        //计划协议
                        || ipDetail.OrderType == com.Sconit.CodeMaster.OrderType.CustomerGoods)      //客供品发货
                        && ipDetail.OrderSubType == com.Sconit.CodeMaster.OrderSubType.Normal)
                || (ipDetail.OrderType == com.Sconit.CodeMaster.OrderType.Distribution
                && ipDetail.OrderSubType == com.Sconit.CodeMaster.OrderSubType.Return)//销售退货发货
                        || ipDetail.OrderType == com.Sconit.CodeMaster.OrderType.SubContract   //委外
                        || ipDetail.OrderType == com.Sconit.CodeMaster.OrderType.Production     //生产
                )
            {
                #region 生成在途非寄售物料
                inventoryTransactionList = new List<InventoryTransaction>();
                foreach (IpDetailInput ipDetailInput in ipDetail.IpDetailInputs)
                {
                    InventoryTransaction inventoryTransaction = new InventoryTransaction();

                    inventoryTransaction.Item = ipDetail.Item;
                    inventoryTransaction.HuId = ipDetailInput.HuId;
                    inventoryTransaction.LotNo = ipDetailInput.LotNo;
                    inventoryTransaction.IsConsignment = false;
                    inventoryTransaction.IsCreatePlanBill = false;
                    inventoryTransaction.Qty = -ipDetailInput.ShipQty * ipDetail.UnitQty;  //转换为库存单位,出库位负数
                    inventoryTransaction.QualityType = ipDetail.QualityType;
                    inventoryTransaction.IsATP = ipDetail.QualityType == com.Sconit.CodeMaster.QualityType.Qualified;
                    inventoryTransaction.IsFreeze = false;
                    inventoryTransaction.OccupyType = com.Sconit.CodeMaster.OccupyType.None;

                    inventoryTransactionList.Add(inventoryTransaction);
                }
                #endregion
            }
            else
            {
                throw new TechnicalException("未知情况,需要跟踪。");
            }

            return inventoryTransactionList;
        }
        private IList<InventoryTransaction> BackflushProductLineLocationDetail(BackflushInput backflushInput, DateTime effectiveDate)
        {
            IList<InventoryTransaction> inventoryTransactionList = new List<InventoryTransaction>();

            if (backflushInput.ProductLineLocationDetailList != null && backflushInput.ProductLineLocationDetailList.Count > 0)
            {
                decimal remainQty = backflushInput.Qty * backflushInput.UnitQty;
                foreach (ProductLineLocationDetail productLineLocationDetail in backflushInput.ProductLineLocationDetailList)
                {
                    if (productLineLocationDetail.RemainBackFlushQty == 0)
                    {
                        continue;
                    }

                    if (remainQty <= 0)
                    {
                        break;
                    }
                    SettleBillTransaction billTransaction = null;
                    if (productLineLocationDetail.IsConsignment && productLineLocationDetail.PlanBill.HasValue)
                    {
                        var planBill = this.genericMgr.FindById<PlanBill>(productLineLocationDetail.PlanBill.Value);
                        planBill.CurrentLocation = productLineLocationDetail.LocationFrom;
                        billTransaction = this.billMgr.SettleBill(planBill, effectiveDate);
                    }
                    InventoryTransaction inventoryTransaction = new InventoryTransaction();
                    inventoryTransaction.LocationLotDetailId = productLineLocationDetail.Id;
                    inventoryTransaction.Location = productLineLocationDetail.ProductLine;
                    inventoryTransaction.Bin = productLineLocationDetail.ProductLineFacility;
                    inventoryTransaction.Item = productLineLocationDetail.Item;
                    inventoryTransaction.HuId = productLineLocationDetail.HuId;
                    inventoryTransaction.LotNo = productLineLocationDetail.LotNo;
                    if (remainQty >= productLineLocationDetail.RemainBackFlushQty)
                    {
                        remainQty -= productLineLocationDetail.RemainBackFlushQty;
                        inventoryTransaction.Qty = -productLineLocationDetail.RemainBackFlushQty;
                        productLineLocationDetail.BackFlushQty += productLineLocationDetail.RemainBackFlushQty;
                        productLineLocationDetail.IsClose = true;
                    }
                    else
                    {
                        inventoryTransaction.Qty = -remainQty;
                        productLineLocationDetail.BackFlushQty += remainQty;
                        remainQty = 0;
                        if (productLineLocationDetail.RemainBackFlushQty == 0)
                        {
                            productLineLocationDetail.IsClose = true;
                        }
                    }
                    this.genericMgr.Update(productLineLocationDetail);
                    inventoryTransaction.IsCreatePlanBill = false;
                    inventoryTransaction.IsConsignment = false;
                    inventoryTransaction.PlanBill = productLineLocationDetail.PlanBill;
                    inventoryTransaction.PlanBillQty = 0;
                    if (billTransaction != null)
                    {
                        inventoryTransaction.ActingBill = billTransaction.ActingBill;
                        inventoryTransaction.ActingBillQty = billTransaction.BillQty;
                        inventoryTransaction.BillTransactionId = billTransaction.Id;
                    }
                    inventoryTransaction.QualityType = productLineLocationDetail.QualityType;
                    inventoryTransaction.IsFreeze = false;
                    inventoryTransaction.IsATP = productLineLocationDetail.QualityType == com.Sconit.CodeMaster.QualityType.Qualified;
                    inventoryTransaction.OccupyType = CodeMaster.OccupyType.None;
                    inventoryTransaction.OccupyReferenceNo = null;
                    inventoryTransaction.Operation = productLineLocationDetail.Operation;
                    inventoryTransaction.OpReference = productLineLocationDetail.OpReference;
                    inventoryTransaction.OrgLocation = productLineLocationDetail.LocationFrom;
                    inventoryTransaction.ReserveNo = productLineLocationDetail.ReserveNo;
                    inventoryTransaction.ReserveLine = productLineLocationDetail.ReserveLine;
                    inventoryTransaction.AUFNR = productLineLocationDetail.AUFNR;
                    inventoryTransaction.BWART = productLineLocationDetail.BWART;
                    inventoryTransaction.ICHARG = productLineLocationDetail.ICHARG;
                    inventoryTransaction.NotReport = productLineLocationDetail.NotReport;

                    inventoryTransactionList.Add(inventoryTransaction);
                }
            }
            return inventoryTransactionList;
        }
        public IList<InventoryTransaction> BackflushProductWeightAverageRawMaterial(IList<WeightAverageBackflushInput> backflushInputList, DateTime effectiveDate)
        {
            var productLine = (from input in backflushInputList
                               group input by new { ProductLine = input.ProductLine, ProductLineFacility = input.ProductLineFacility } into result
                               select result.Key).Single();

            #region 查询生产线投料明细和待回冲明细
            string selectProductLineLocationDetailStatement = "from ProductLineLocationDetail where ProductLine = ? and IsClose = False";
            string selectPlanBackflushStatement = "from PlanBackflush where ProductLine = ? and IsClose = False";

            IList<object> para = new List<object>();
            para.Add(productLine.ProductLine);
            if (!string.IsNullOrWhiteSpace(productLine.ProductLineFacility))
            {
                selectProductLineLocationDetailStatement += " and ProductLineFacility = ?";
                selectPlanBackflushStatement += " and ProductLineFacility = ?";
                para.Add(productLine.ProductLineFacility);
            }

            string itemStatement = string.Empty;
            foreach (string item in backflushInputList.Select(f => f.Item).Distinct())
            {
                if (itemStatement == string.Empty)
                {
                    itemStatement = " and Item in(?";
                }
                else
                {
                    itemStatement += ", ?";
                }
                para.Add(item);
            }
            itemStatement += ")";
            selectProductLineLocationDetailStatement += itemStatement;
            selectPlanBackflushStatement += itemStatement;

            IList<ProductLineLocationDetail> productLineLocationDetailList =
                this.genericMgr.FindAll<ProductLineLocationDetail>(selectProductLineLocationDetailStatement, para.ToArray());

            IList<PlanBackflush> planBackflushList =
               this.genericMgr.FindAll<PlanBackflush>(selectPlanBackflushStatement, para.ToArray());
            #endregion

            List<InventoryTransaction> inventoryTransactionList = new List<InventoryTransaction>();
            List<WeightAverageBackflushResult> weightAverageBackflushResultList = new List<WeightAverageBackflushResult>();

            #region 循环回冲零件
            //小数保留位数
            int decimalLength = int.Parse(systemMgr.GetEntityPreferenceValue(EntityPreference.CodeEnum.DecimalLength));

            foreach (WeightAverageBackflushInput backflushInput in backflushInputList)
            {
                //对应的待回冲生产单Bom
                IList<PlanBackflush> thisPlanBackflushList = planBackflushList.Where(p => p.Item == backflushInput.Item).ToList();

                if (thisPlanBackflushList == null || thisPlanBackflushList.Count == 0)
                {
                    throw new BusinessException("没有找到和物料{0}对应的待回冲生产单Bom。", backflushInput.Item);
                }

                IList<ProductLineLocationDetail> targetProductLineLocationDetail = (from det in productLineLocationDetailList
                                                                                    where det.Item == backflushInput.Item
                                                                                    select det).ToList();

                decimal remainQty = backflushInput.Qty * backflushInput.UnitQty;  //转为库存单位
                if (targetProductLineLocationDetail != null && targetProductLineLocationDetail.Count > 0)
                {
                    #region 循环扣减物料
                    foreach (ProductLineLocationDetail productLineLocationDetail in targetProductLineLocationDetail)
                    {
                        if (remainQty == 0)
                        {
                            break;
                        }

                        if (productLineLocationDetail.RemainBackFlushQty == 0)
                        {
                            continue;
                        }

                        decimal currentBFQty = 0;
                        if (productLineLocationDetail.RemainBackFlushQty >= remainQty)
                        {
                            currentBFQty = remainQty;
                            productLineLocationDetail.BackFlushQty += currentBFQty;
                            remainQty = 0;
                            if (productLineLocationDetail.RemainBackFlushQty == 0)
                            {
                                productLineLocationDetail.IsClose = true;
                            }
                        }
                        else
                        {
                            currentBFQty = productLineLocationDetail.RemainBackFlushQty;
                            remainQty -= currentBFQty;
                            productLineLocationDetail.BackFlushQty += productLineLocationDetail.RemainBackFlushQty;
                            productLineLocationDetail.IsClose = true;
                        }

                        //剩余分摊数
                        decimal remianBFQty = currentBFQty;
                        decimal remianActingBFQty = 0;

                        #region 判断是否结算
                        SettleBillTransaction billTransaction = null;
                        if (productLineLocationDetail.IsConsignment && productLineLocationDetail.PlanBill.HasValue)
                        {
                            PlanBill pb = this.genericMgr.FindById<PlanBill>(productLineLocationDetail.PlanBill.Value);
                            pb.CurrentActingQty = currentBFQty / pb.UnitQty; //转为结算单位
                            pb.CurrentLocation = productLineLocationDetail.LocationFrom;
                            billTransaction = this.billMgr.SettleBill(pb, effectiveDate);
                            remianActingBFQty = currentBFQty;   //基本单位
                        }
                        #endregion

                        this.genericMgr.Update(productLineLocationDetail);

                        #region 计算每个PlanBackflush的加权平均数
                        //计算分摊因子
                        decimal averageFact = remianBFQty / planBackflushList.Sum(p => p.Qty);
                        decimal actingAverageFact = remianActingBFQty / planBackflushList.Sum(p => p.Qty);

                        for (int i = 0; i < thisPlanBackflushList.Count; i++)
                        {
                            #region 回冲结果
                            PlanBackflush planBackflush = thisPlanBackflushList[i];
                            WeightAverageBackflushResult weightAverageBackflushResult = new WeightAverageBackflushResult();
                            weightAverageBackflushResult.PlanBackflush = planBackflush;
                            weightAverageBackflushResult.ProductLineLocationDetail = productLineLocationDetail;
                            weightAverageBackflushResult.CurrentProductLine = backflushInput.CurrentProductLine;
                            weightAverageBackflushResult.LocationFrom = productLineLocationDetail.LocationFrom;
                            weightAverageBackflushResult.Operation = productLineLocationDetail.Operation;
                            weightAverageBackflushResult.OpReference = productLineLocationDetail.OpReference;
                            weightAverageBackflushResult.ProductLine = productLineLocationDetail.ProductLine;
                            weightAverageBackflushResult.ProductLineFacility = productLineLocationDetail.ProductLineFacility;
                            weightAverageBackflushResult.QualityType = productLineLocationDetail.QualityType;

                            if (i != thisPlanBackflushList.Count - 1)
                            {
                                weightAverageBackflushResult.BaseQty = Math.Round(averageFact * planBackflush.Qty, decimalLength, MidpointRounding.AwayFromZero);  //基本单位
                                weightAverageBackflushResult.BaseActingQty = Math.Round(actingAverageFact * planBackflush.Qty, decimalLength, MidpointRounding.AwayFromZero);   //基本单位

                                remianBFQty -= weightAverageBackflushResult.BaseQty;
                                remianActingBFQty -= weightAverageBackflushResult.BaseActingQty;
                            }
                            else
                            {
                                weightAverageBackflushResult.BaseQty = remianBFQty;
                                weightAverageBackflushResult.BaseActingQty = remianActingBFQty;

                                remianBFQty = 0;
                                remianActingBFQty = 0;
                            }
                            weightAverageBackflushResult.Qty = weightAverageBackflushResult.BaseQty / planBackflush.UnitQty;    //转为回冲的单位
                            weightAverageBackflushResult.ActingQty = weightAverageBackflushResult.BaseActingQty / planBackflush.UnitQty;   //转为回冲的单位

                            #region 库存事务
                            InventoryTransaction inventoryTransaction = new InventoryTransaction();

                            inventoryTransaction.Qty = -weightAverageBackflushResult.BaseQty;   //出库为负数
                            inventoryTransaction.LocationLotDetailId = productLineLocationDetail.Id;
                            inventoryTransaction.Location = productLineLocationDetail.LocationFrom;
                            inventoryTransaction.Item = productLineLocationDetail.Item;
                            inventoryTransaction.HuId = productLineLocationDetail.HuId;
                            inventoryTransaction.LotNo = productLineLocationDetail.LotNo;
                            inventoryTransaction.IsCreatePlanBill = false;
                            inventoryTransaction.IsConsignment = productLineLocationDetail.IsConsignment;
                            inventoryTransaction.PlanBill = productLineLocationDetail.PlanBill;
                            //if (inventoryTransaction.IsConsignment)
                            //{
                            //    
                            //理论上都是非寄售库存,PlanBillQty必定为零。
                            inventoryTransaction.PlanBillQty = 0;
                            //}
                            inventoryTransaction.QualityType = productLineLocationDetail.QualityType;
                            inventoryTransaction.IsATP = productLineLocationDetail.QualityType == com.Sconit.CodeMaster.QualityType.Qualified;
                            inventoryTransaction.IsFreeze = false;
                            inventoryTransaction.OccupyType = com.Sconit.CodeMaster.OccupyType.None;
                            inventoryTransaction.PlanBackflushId = planBackflush.Id;

                            if (billTransaction != null)
                            {
                                inventoryTransaction.IsConsignment = false;
                                inventoryTransaction.ActingBill = billTransaction.ActingBill;
                                inventoryTransaction.ActingBillQty = -weightAverageBackflushResult.BaseActingQty;  //基本单位,采购结算为负数
                                inventoryTransaction.BillTransactionId = billTransaction.Id;
                            }

                            weightAverageBackflushResult.InventoryTransaction = inventoryTransaction;

                            inventoryTransactionList.Add(inventoryTransaction);
                            #endregion

                            weightAverageBackflushResultList.Add(weightAverageBackflushResult);
                            #endregion
                        }
                        #endregion
                    }
                    #endregion

                    if (remainQty > 0)
                    {
                        throw new BusinessException("零件{0}在生产线{1}上余额不足。", backflushInput.Item, backflushInput.ProductLine);
                    }
                }
            }
            #endregion

            #region 记录工单投料明细
            DateTime dateTimeNow = DateTime.Now;
            User currentUser = SecurityContextHolder.Get();

            foreach (OrderBackflushDetail orderBackflushDetail in (from r in weightAverageBackflushResultList
                                                                   group r by new
                                                                   {
                                                                       PlanBackflush = r.PlanBackflush,
                                                                       LocationFrom = r.LocationFrom,
                                                                       Operation = r.Operation,
                                                                       OpReference = r.OpReference,
                                                                       ProductLine = r.ProductLine,
                                                                       ProductLineFacility = r.ProductLineFacility,
                                                                       QualityType = r.QualityType,
                                                                       InventoryTransaction = r.InventoryTransaction
                                                                   } into result
                                                                   select new OrderBackflushDetail
                                                                   {
                                                                       OrderNo = result.Key.PlanBackflush.OrderNo,
                                                                       OrderDetailId = result.Key.PlanBackflush.OrderDetailId,
                                                                       OrderDetailSequence = result.Key.PlanBackflush.OrderDetailSequence,
                                                                       OrderBomDetailId = result.Key.PlanBackflush.OrderBomDetailId,
                                                                       OrderBomDetailSequence = result.Key.PlanBackflush.OrderBomDetailSequence,
                                                                       ReceiptNo = result.Key.PlanBackflush.ReceiptNo,
                                                                       ReceiptDetailId = result.Key.PlanBackflush.ReceiptDetailId,
                                                                       ReceiptDetailSequence = result.Key.PlanBackflush.ReceiptDetailSequence,
                                                                       Bom = result.Key.PlanBackflush.Bom,
                                                                       FGItem = result.Key.PlanBackflush.FGItem,
                                                                       Item = result.Key.PlanBackflush.Item,
                                                                       ItemDescription = result.Key.PlanBackflush.ItemDescription,
                                                                       ReferenceItemCode = result.Key.PlanBackflush.ReferenceItemCode,
                                                                       Uom = result.Key.PlanBackflush.Uom,
                                                                       BaseUom = result.Key.PlanBackflush.BaseUom,
                                                                       UnitQty = result.Key.PlanBackflush.UnitQty,
                                                                       ManufactureParty = result.Key.PlanBackflush.ManufactureParty,
                                                                       //TraceCode = result.Key.PlanBackflush.TraceCode,
                                                                       //HuId = result.Key.HuId,
                                                                       //LotNo = result.Key.LotNo,
                                                                       Operation = result.Key.Operation,
                                                                       OpReference = result.Key.OpReference,
                                                                       BackflushedQty = result.Key.QualityType == CodeMaster.QualityType.Qualified ? result.Sum(p => p.Qty) : 0,
                                                                       BackflushedRejectQty = result.Key.QualityType == CodeMaster.QualityType.Reject ? result.Sum(p => p.Qty) : 0,
                                                                       //BackflushedScrapQty = input.BackflushedQty,
                                                                       LocationFrom = result.Key.LocationFrom,
                                                                       ProductLine = result.Key.ProductLine,
                                                                       ProductLineFacility = result.Key.ProductLineFacility,
                                                                       ReserveNo = result.Key.PlanBackflush.ReserveNo,
                                                                       ReserveLine = result.Key.PlanBackflush.ReserveLine,
                                                                       AUFNR = result.Key.PlanBackflush.AUFNR,
                                                                       PlanBill = result.Key.InventoryTransaction != null ? result.Key.InventoryTransaction.PlanBill : null,
                                                                       ICHARG = result.Key.PlanBackflush.ICHARG,
                                                                       BWART = result.Key.PlanBackflush.BWART,
                                                                       NotReport = false,   //理论都需要汇报
                                                                       EffectiveDate = effectiveDate,
                                                                       CreateUserId = currentUser.Id,
                                                                       CreateUserName = currentUser.FullName,
                                                                       CreateDate = dateTimeNow,
                                                                       IsVoid = false,
                                                                   }))
            {
                this.genericMgr.Create(orderBackflushDetail);
            }

            #endregion

            #region 记录库存事务
            RecordLocationTransaction(weightAverageBackflushResultList, effectiveDate);
            #endregion

            return inventoryTransactionList;
        }
        public IList<InventoryTransaction> ReturnProductRawMaterial(ReturnInput returnInput, DateTime effectiveDate)
        {
            #region 出生产线
            #region 查询生产线上物料
            IList<ProductLineLocationDetail> productLineLocationDetailList = null;
            if (returnInput.ProductLineLocationDetailId.HasValue)
            {
                string hql = "from ProductLineLocationDetail where Id = ? and IsClose = ? ";

                IList<object> para = new List<object>();
                para.Add(returnInput.ProductLineLocationDetailId.Value);
                para.Add(false);

                productLineLocationDetailList = this.genericMgr.FindAll<ProductLineLocationDetail>(hql, para.ToArray());

                if (productLineLocationDetailList != null && productLineLocationDetailList.Count > 0)
                {
                    OrderMaster orderMaster = this.genericMgr.FindById<OrderMaster>(productLineLocationDetailList[0].OrderNo);
                    FlowMaster flowMaster = this.genericMgr.FindById<FlowMaster>(productLineLocationDetailList[0].ProductLine);
                    Location location = this.genericMgr.FindById<Location>(productLineLocationDetailList[0].LocationFrom);
                    Item item = this.genericMgr.FindById<Item>(productLineLocationDetailList[0].Item);
                    returnInput.OrderNo = orderMaster.OrderNo;
                    returnInput.OrderType = orderMaster.Type;
                    returnInput.OrderSubType = orderMaster.SubType;
                    returnInput.TraceCode = productLineLocationDetailList[0].TraceCode;
                    returnInput.Item = productLineLocationDetailList[0].Item;
                    returnInput.Uom = item.Uom;
                    returnInput.BaseUom = item.Uom;
                    returnInput.UnitQty = 1;
                    returnInput.QualityType = productLineLocationDetailList[0].QualityType;
                    returnInput.HuId = productLineLocationDetailList[0].HuId;
                    returnInput.LotNo = productLineLocationDetailList[0].LotNo;
                    returnInput.CurrentProductLine = flowMaster;
                    returnInput.ProductLine = flowMaster.Code;
                    returnInput.CurrentLocationTo = location;
                }
            }
            else
            {
                string hql = "from ProductLineLocationDetail where ProductLine = ? and Item = ? and QualityType = ? and IsClose = ? ";
                IList<object> para = new List<object>();
                para.Add(returnInput.ProductLine);
                para.Add(returnInput.Item);
                para.Add(returnInput.QualityType);
                para.Add(false);

                if (!string.IsNullOrWhiteSpace(returnInput.ProductLineFacility))
                {
                    hql += " and ProductLineFacility = ?";
                    para.Add(returnInput.ProductLineFacility);
                }

                if (!string.IsNullOrWhiteSpace(returnInput.OrderNo))
                {
                    hql += " and OrderNo = ?";
                    para.Add(returnInput.OrderNo);

                    if (!string.IsNullOrWhiteSpace(returnInput.TraceCode))
                    {
                        hql += " and TraceCode = ?";
                        para.Add(returnInput.TraceCode);
                    }

                    if (returnInput.Operation.HasValue)
                    {
                        hql += " and Operation = ?";
                        para.Add(returnInput.Operation.Value);

                        if (!string.IsNullOrWhiteSpace(returnInput.OpReference))
                        {
                            hql += " and OpReference = ?";
                            para.Add(returnInput.OpReference);
                        }
                        else
                        {
                            //hql += " and OpReference is null";
                        }
                    }
                    else
                    {
                        //hql += " and Operation is null";
                    }
                }

                if (!string.IsNullOrWhiteSpace(returnInput.HuId))
                {
                    hql += " and HuId = ?";
                    para.Add(returnInput.HuId);
                }

                //hql += " order by CreateDate desc";  //
                productLineLocationDetailList = this.genericMgr.FindAll<ProductLineLocationDetail>(hql, para.ToArray());
            }
            #endregion

            #region 回冲生产线物料
            List<InventoryTransaction> issInventoryTransactionList = new List<InventoryTransaction>();
            decimal remainQty = returnInput.Qty * returnInput.UnitQty;  //转为库存单位
            if (productLineLocationDetailList != null && productLineLocationDetailList.Count > 0)
            {
                #region 循环扣减物料
                foreach (ProductLineLocationDetail productLineLocationDetail in productLineLocationDetailList)
                {
                    if (remainQty == 0)
                    {
                        break;
                    }

                    if (productLineLocationDetail.RemainBackFlushQty == 0)
                    {
                        continue;
                    }

                    InventoryTransaction inventoryTransaction = new InventoryTransaction();

                    if (productLineLocationDetail.RemainBackFlushQty >= remainQty)
                    {
                        productLineLocationDetail.VoidQty += remainQty;
                        inventoryTransaction.Qty = -remainQty;   //出库位负数
                        remainQty = 0;
                        if (productLineLocationDetail.RemainBackFlushQty == 0)
                        {
                            productLineLocationDetail.IsClose = true;
                        }
                    }
                    else
                    {
                        remainQty -= productLineLocationDetail.RemainBackFlushQty;
                        inventoryTransaction.Qty = -productLineLocationDetail.RemainBackFlushQty;   //出库位负数
                        productLineLocationDetail.VoidQty += productLineLocationDetail.RemainBackFlushQty;
                        productLineLocationDetail.IsClose = true;
                    }
                    inventoryTransaction.LocationLotDetailId = productLineLocationDetail.Id;
                    inventoryTransaction.Location = productLineLocationDetail.ProductLine;
                    inventoryTransaction.OrgLocation = productLineLocationDetail.LocationFrom;
                    inventoryTransaction.Bin = productLineLocationDetail.ProductLineFacility;
                    inventoryTransaction.Item = productLineLocationDetail.Item;
                    inventoryTransaction.HuId = productLineLocationDetail.HuId;
                    inventoryTransaction.LotNo = productLineLocationDetail.LotNo;
                    inventoryTransaction.IsCreatePlanBill = false;
                    inventoryTransaction.IsConsignment = productLineLocationDetail.IsConsignment;
                    inventoryTransaction.PlanBill = productLineLocationDetail.PlanBill;
                    if (inventoryTransaction.IsConsignment)
                    {
                        inventoryTransaction.PlanBillQty = inventoryTransaction.Qty;
                    }
                    inventoryTransaction.ActingBill = null;
                    inventoryTransaction.ActingBillQty = 0;
                    inventoryTransaction.QualityType = productLineLocationDetail.QualityType;
                    inventoryTransaction.IsATP = productLineLocationDetail.QualityType == com.Sconit.CodeMaster.QualityType.Qualified;
                    inventoryTransaction.IsFreeze = false;
                    inventoryTransaction.OccupyType = com.Sconit.CodeMaster.OccupyType.None;

                    issInventoryTransactionList.Add(inventoryTransaction);
                    this.genericMgr.Update(productLineLocationDetail);
                }
                #endregion
            }

            if (remainQty > 0)
            {
                if (!string.IsNullOrWhiteSpace(returnInput.HuId))
                {
                    throw new BusinessException("退料条码{0}在生产线{1}上不存在或余额不足。", returnInput.HuId, returnInput.ProductLine);
                }
                else
                {
                    throw new BusinessException("退料零件{0}在生产线{1}上余额不足。", returnInput.Item, returnInput.ProductLine);

                }
            }
            #endregion

            #region 记录退生产线事务
            if (issInventoryTransactionList.Count == 0)
            {
                throw new TechnicalException("Return InventoryTransaction is empty.");
            }

            RecordLocationTransaction(returnInput, effectiveDate, issInventoryTransactionList, true);
            #endregion
            #endregion

            #region 入库位
            var groupedInventoryTransactionList = from trans in issInventoryTransactionList
                                                  group trans by new
                                                  {
                                                      LocationTo = !string.IsNullOrWhiteSpace(returnInput.LocationTo) ? returnInput.LocationTo : trans.OrgLocation,
                                                      IsConsignment = trans.IsConsignment,
                                                      PlanBill = trans.PlanBill
                                                  } into result
                                                  select new
                                                  {
                                                      LocationTo = result.Key.LocationTo,
                                                      IsConsignment = result.Key.IsConsignment,
                                                      PlanBill = result.Key.PlanBill,
                                                      //Qty = result.Sum(trans => -trans.Qty),
                                                      Qty = result.Sum(trans => trans.Qty),
                                                  };

            List<InventoryTransaction> rctInventoryTransactionList = new List<InventoryTransaction>();
            foreach (var trans in groupedInventoryTransactionList)
            {
                InventoryIO inventoryIO = new InventoryIO();

                inventoryIO.Location = trans.LocationTo;
                inventoryIO.Item = returnInput.Item;
                inventoryIO.HuId = returnInput.HuId;
                inventoryIO.LotNo = returnInput.LotNo;
                inventoryIO.Qty = -trans.Qty;    //入库为正数
                inventoryIO.QualityType = returnInput.QualityType;
                inventoryIO.IsATP = returnInput.QualityType == com.Sconit.CodeMaster.QualityType.Qualified;
                inventoryIO.IsFreeze = false;
                inventoryIO.IsCreatePlanBill = false;
                inventoryIO.IsConsignment = trans.IsConsignment;
                inventoryIO.PlanBill = trans.PlanBill;
                inventoryIO.ActingBill = null;
                inventoryIO.TransactionType = com.Sconit.CodeMaster.TransactionType.RCT_MIN_RTN; //生产投料退库入库
                inventoryIO.OccupyType = com.Sconit.CodeMaster.OccupyType.None; //应该是非占用的零件才能投料
                //inventoryIO.OccupyReferenceNo = ipDetail.CurrentOccupyReferenceNo;
                inventoryIO.IsVoid = false;
                inventoryIO.EffectiveDate = effectiveDate;
                //inventoryIO.ManufactureParty = ;

                rctInventoryTransactionList.AddRange(RecordInventory(inventoryIO));
            }
            //记录出库事务
            RecordLocationTransaction(returnInput, effectiveDate, rctInventoryTransactionList, false);
            #endregion

            issInventoryTransactionList.AddRange(rctInventoryTransactionList);

            return issInventoryTransactionList;
        }
        private InventoryTransaction CreateInventoryTransaction(LocationLotDetail locationLotDetail, decimal qty, bool isCreatePlanBill, BillTransaction billTransaction)
        {
            InventoryTransaction inventoryTransaction = new InventoryTransaction();
            inventoryTransaction.LocationLotDetailId = locationLotDetail.Id;
            inventoryTransaction.Location = locationLotDetail.Location;
            inventoryTransaction.Bin = locationLotDetail.Bin;
            inventoryTransaction.Item = locationLotDetail.Item;
            inventoryTransaction.HuId = locationLotDetail.HuId;
            inventoryTransaction.LotNo = locationLotDetail.LotNo;
            inventoryTransaction.IsConsignment = locationLotDetail.IsConsignment;
            inventoryTransaction.IsCreatePlanBill = isCreatePlanBill;
            inventoryTransaction.PlanBill = locationLotDetail.PlanBill;
            if (locationLotDetail.IsConsignment)
            {
                //寄售库存
                inventoryTransaction.PlanBillQty = qty;
            }
            if (billTransaction != null)
            {
                //if (billTransaction.TransactionType == CodeMaster.BillTransactionType.POSettle)
                //{
                //发生了结算,记录结算数量
                inventoryTransaction.BillTransactionId = billTransaction.Id;
                inventoryTransaction.IsConsignment = false;
                inventoryTransaction.ActingBill = billTransaction.ActingBill;
                inventoryTransaction.ActingBillQty = qty;
                inventoryTransaction.PlanBillQty = 0;
                //}
                //else if(billTransaction.TransactionType == CodeMaster.BillTransactionType.POSettleVoid)
                //{
                //    //发生了反结算,记录反结算数量
                //    inventoryTransaction.BillTransactionId = billTransaction.Id;
                //    inventoryTransaction.IsConsignment = true;
                //    inventoryTransaction.ActingBill = 0;
                //    inventoryTransaction.ActingBillQty = 0;             //基本单位
                //    inventoryTransaction.PlanBill = billTransaction.PlanBill;
                //    inventoryTransaction.PlanBillQty = qty;
                //}
            }
            inventoryTransaction.Qty = qty;
            inventoryTransaction.QualityType = locationLotDetail.QualityType;
            inventoryTransaction.IsATP = locationLotDetail.IsATP;
            inventoryTransaction.IsFreeze = locationLotDetail.IsFreeze;
            inventoryTransaction.OccupyType = locationLotDetail.OccupyType;
            inventoryTransaction.OccupyReferenceNo = locationLotDetail.OccupyReferenceNo;

            return inventoryTransaction;
        }