/// 
///LOGIC CLASS FOR TABLE t_wmsStock
///By wm with codesmith. 
///on 05/14/2017
/// 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DeiNiu.wms.Data.Model;
using System.Data;
using System.Transactions;
using DeiNiu.Utils;
using DeiNiu.Data.BaseObject;
//using  Microsoft.Reporting.WinForms;
namespace DeiNiu.wms.Logical
{
    [Serializable]
    public class lWmsStock : lbase
    {
        WmsStock _obj;
        public lWmsStock()
        {
             initialize();
        }
        public lWmsStock(int operId)
            : base(operId)
        {
            initialize();       
        }
        public  WmsStock wmsStock
        {
            get
            {
                if (_obj == null)
                {
                    _obj = new WmsStock();
                }
              
                return _obj;
            }
        }
        protected override BaseModel getModel()
        {
            return _obj;
        }
		/// 
		/// get all data
		/// 
        public DataSet getAllData()
        {
           return wmsStock.Query();
        }
        /// 
        /// get all data
        /// 
        public DataSet getAllActiveData()
        {
            return wmsStock.QueryActived();
        }
		/// 
		/// get a record by id
		/// 
        public void initialize(int id)
		{
            _obj = id != 0 ? new WmsStock(id) : new WmsStock();
		}
        /// 
		/// get a record by id 0
		/// 
        public void initialize()
        {
            initialize(0);
        }
         /// 
        /// get a record by id
        /// 
        public void initialize(DataRow dr)
        {
            _obj =   new WmsStock(dr);
        }
 
        //begin cust db operation, query, excute sql etc.
        
     
         /// 
        ///  query with like, return talbe and record cnt.
        /// 
        public DataSet QueryByGoodsName(string namelike, int rownumStart, int rownumEnd,enumWhType whType)
        {
            if (rownumEnd > rownumStart && rownumStart > 0)
            {
                _obj.rownumStart = rownumStart;
                _obj.rownumEnd = rownumEnd;
            }
            DataSet ds = string.IsNullOrEmpty(namelike) ? _obj.Query() : _obj.QueryByName(namelike, whType);//enumWhType.合格库);
            return ds;
      
        }  
        /// 
        /// update in a transaction scrop
        /// 
        public void update()
        {
            if (valid())
            {
                using (TransactionScope scope = new TransactionScope())
                {
                    //Node tmp = new Node();
                    //tmp.parentid = 1;
                    //tmp.name = "test trans" + DateTime.Now;
                    //tmp.description = "this is for transTest";
                    //tmp.Add();
                    _obj.Update();
                    scope.Complete();
                }
            }
        }
        
         private bool valid()
        {
            return true;
        }
         /// 
         /// get by locaiton id
         /// for wince
         /// 
         /// 
         /// 
         public DataTable getStockLocation(string locId)
         {
             return wmsStock.getStockLocation(locId.Trim());
         }
        /// 
         /// 手持上下架 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
         public enumRepResult upDownGoodsCountWithLocation(string locId, string goodsId, int skuId,string batch, decimal count, 
             string reason, enumStockRecordType type, int recId,string flowNo="")
         {
             WmsLocation loc = new WmsLocation(locId);
             if(loc.ID ==0){
                 return enumRepResult.货位不存在;
             }
             if (loc.state != (int)enumStockLocationStatus.正常)
             {
                 return enumRepResult.货位不可用;  
             }
             if (type == enumStockRecordType.初始盘点)
             {
                
                 if (loc.whType == (int)enumWhType.不合格库) //非合格库
                 {
                     return enumRepResult.货位非合格库;
                 } 
                  
                 enumRepResult r1 = validLocation(locId, goodsId, skuId, batch, count) ;
                 if (r1!= enumRepResult.成功)
                 {
                     return r1;
                 }
                 return updateStockLocation(locId, goodsId, skuId,batch, count, reason, type) ? enumRepResult.成功 : enumRepResult.失败;
             }else 
             if (type == enumStockRecordType.移库下架   )
             {
                /*
                _obj = new WmsStock(locId, skuId, goodsId);
                if (_obj.countOuting > 0)
                {
                    return enumRepResult.状态待拣货;   //--- 可以移库,但留下countouting 数量用于待拣货任务
                }*/
                return updateStockLocation(locId, goodsId, skuId, batch, count, reason, type,flowNo) ? enumRepResult.成功 : enumRepResult.失败;
             }else
            if ( type == enumStockRecordType.库存对比)
            {
                return   enumRepResult.失败;
            }
            enumRepResult r = validLocation(locId, goodsId, skuId, batch, count);
             if (r != enumRepResult.成功)
             {
                 return r;
             }
             if ( type == enumStockRecordType.普通入库)
             {
                 return updateStockLocation(locId, goodsId, skuId, batch, count, reason, type) ? enumRepResult.成功 : enumRepResult.失败;
             }
             if (type == enumStockRecordType.移库上架 )
             {
  
                 WmsStockRecord strec = new WmsStockRecord(recId);
                 strec.count1 += count; //update up count
                 strec.operater = this.operId;
                 strec.description += "," + locId; 
                 reason += ",from rec: " + strec.ID;
                WmsPlateStock_tmp wpt = new WmsPlateStock_tmp();
                DataTable dt= wpt.getStockLst(strec.orderNo, strec.skuId);
                try
                {
                    using (TransactionScope scope = new TransactionScope())
                    {
                        foreach (DataRow dr in dt.Rows)
                        {
                            wpt = new WmsPlateStock_tmp(dr);
                            if (wpt.goodsId == goodsId)
                            {
                                wpt.count -= count;
                                if (wpt.count == 0)
                                {
                                    wpt.Delete();
                                }
                                else
                                {
                                    wpt.Update();
                                }
                            }
                        }
                        strec.Update();
                        updateStockLocation(locId, goodsId, skuId, batch, count, reason, type);
                        scope.Complete();
                    }
                }
                catch
                {
                    return enumRepResult.失败;
                }
             }
           return  enumRepResult.成功;
         }
        /// 
        /// 手持终端盘点调整库存数量
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
         public bool updateStockLocation(string locId, string goodsId, int skuId, string batch, decimal count, 
             string reason, enumStockRecordType type,string flowNo="")
         {
            logPandian.Debug(string.Format(" pandian locId {0}, skuId {1}, batch {2}, count {3},reason {4},type {5},flowNo {6} ",
                locId,     skuId,   batch,   count, reason, type.ToString(), flowNo));
            WmsStockRecord strec = new WmsStockRecord();
            strec.skuId = skuId;
             strec.batch = batch;
             strec.goodsId = goodsId;
             strec.locationId = locId;
             strec.orderNo = goodsId; // "StockGoodsCheck";
            WmsPlateStock_tmp wpt=null;
             _obj = new WmsStock( locId,skuId,goodsId);
            // _obj = new WmsStock(locId);
             if (_obj.ID == 0) //new one
             {
                 Sku sku = new Sku(skuId);
                 if (sku.ID == 0)
                 {
                     return false;
                 }
                if (string.IsNullOrEmpty(batch))
                {
                    batch = _obj.getDateTime();
                }
                 _obj.skuCode = sku.skuCode;
                 _obj.productDate = String.IsNullOrEmpty( sku.ProductDate)?batch:sku.ProductDate ;
                 _obj.validDate = String.IsNullOrEmpty(sku.ValidDate) ? batch : sku.ValidDate;
                 _obj.batch = batch;
                 _obj.goodsId = goodsId;
                 _obj.skuId = skuId;
                 _obj.locationId = locId;
                 _obj.batch = batch;
                
             }
             decimal newStockCount = 0m;
             decimal adjustCnt = 0m;
             decimal oldCount = _obj.count - _obj.countOut-_obj.countOuting;// +_obj.countIn - _obj.countOut;
            if (type == enumStockRecordType.手持盘点 || type == enumStockRecordType.初始盘点 || type == enumStockRecordType.库存对比)// update stock count directly
            {
                newStockCount = count;
                adjustCnt = count - oldCount + _obj.virtialCount;
                _obj.count = count;// + _obj.countOut + _obj.countOuting; 
                _obj.countOut = _obj.countOuting = 0;
                reason += _obj.virtialCount > 0 ? "预借库存清零: " + _obj.virtialCount : "";
                _obj.virtialCount = 0;
            }
            else if (type == enumStockRecordType.移库下架) // caculate new stock count and adjust count
            {
                count = count > oldCount ? oldCount : count;
                newStockCount = oldCount - count;
                adjustCnt = count;
                _obj.countOut += count;
                wpt = new WmsPlateStock_tmp();
                wpt.skuCode = _obj.skuCode;
                wpt.productDate = _obj.productDate;
                wpt.validDate = _obj.validDate;
                wpt.skuId = _obj.skuId;
                wpt.goodsId = _obj.goodsId;
                wpt.count = count;
                wpt.batch = _obj.batch;
                wpt.locationid = locId;
                wpt.plateId = String.IsNullOrEmpty(flowNo) ? "xj_" + operId + "_" + DateTime.Now.Date : flowNo;
                wpt.recType = (int)type;
                strec.orderNo = wpt.plateId;
            }
            else if (type == enumStockRecordType.移库上架
                       || type == enumStockRecordType.普通入库
                       || type == enumStockRecordType.补零入库
                 )
            {
                newStockCount = oldCount + count;
                adjustCnt = count;
                _obj.count += count;
            }
            else //无其他类型的规则时,报错
            {
                throw new Exception("没有定义库存调整规则:" + type.ToString());
            }
              
             string description = string.Format("商品ID {4},skuId {5}, 库位 {6}, 业务类型:{0},调整前数量{1},调整后数量{2},备注:{3}", 
                 type.ToString(), oldCount, newStockCount, reason, _obj.goodsId, _obj.skuId,_obj.locationId);
           //  _obj.count = newStockCount;
          //   _obj.countOut = 0;
             _obj.operater = this.operId;
             _obj.description = description;
           
            // if (type != enumStockRecordType.初始盘点)
            {
                 strec.skuCode = _obj.skuCode;
                 strec.batch = _obj.batch;
                 strec.productDate = _obj.productDate;
                 strec.validDate = _obj.validDate;
             }
           //  else //TODO: 根据goodsId,batch 取erp库存的生产日期等lot信息,生成wms 批次信息
             {
             }
             strec.operater = this.operId;
             strec.count = adjustCnt;
             strec.description = description;
             strec.rectype = (int)type;
            // try
             {
                 using (TransactionScope scope = new TransactionScope())
                 {
                    if (type == enumStockRecordType.初始盘点)
                    {
                        /* WmsStock stk = new WmsStock(locId, skuId, goodsId);
                         if (stk.ID > 0)
                         {
                             stk.Delete();
                         }*/
                        logPandian.Debug(" 初始盘点, stkId " + _obj.ID);
                        if (_obj.ID > 0)
                        {
                            _obj.Delete();
                        }
                        _obj.Add();
                    }
                    else
                    {
                        if (_obj.ID > 0)
                        {
                            //  _obj.updateCountOut();
                            _obj.Update();
                        }
                        else
                        {
                            _obj.Add();
                        }
                    }
                    
                    strec.Add();
                    if (wpt != null)
                    {
                        wpt.recordId = strec.ID;
                        wpt.Add();
                    }
                    if (type == enumStockRecordType.手持盘点)
                    {
                        // 变化进盘点虚拟库
                        logPandianStock(skuId, goodsId, adjustCnt); 
                    }
                    try
                    {
                        string task = type + operId + Utils.Util.getShortDateString(this.wmsStock.getDateTime());// this.wmsStock.getDateTime
                        WmsFlow wmsFlow = new WmsFlow(task);
                        if (wmsFlow.ID == 0)
                        {
                            wmsFlow.type = (int)Util.getTaskType((int)type);   // ;  (int)EnumFlowTaskType.日常理货;
                            wmsFlow.typeName = Util.getTaskType((int)type).ToString();
                            wmsFlow.task = task;
                            wmsFlow.orderNo = task;
                            wmsFlow.state = (int)enumFlowTaskStatus.进行中;
                            wmsFlow.Add();
                        }
                        wmsFlow.finishedTasksPlus(operId, adjustCnt / new WmsGoods(goodsId).minOperateCount, true);
                    }
                    catch (Exception er)
                    {
                        log.Error(er);
                    }
                    scope.Complete();
                 }
             }
            // catch (Exception e)
             {
               // log.Error(e);
               // throw e;
               //  return false;
             }
             return true;
         }
        internal void deleteLocBySkuId(int skuId)
        {
            _obj.deleteLocBySkuId(skuId);
        }
        internal void deleteLocByType(enumWhLocVol locType)
        {
            _obj.deleteLocByType(locType);
        }
        /// 
        /// 清理零库存及负库存
        /// 
        internal void cleanPandiane()
        {
            _obj.cleanPandiane();
        }
        public  void logPandianStock(int skuId,string goodsId,decimal adjustCnt)
        {
            WmsLocation loc = new WmsLocation();
            List locations =   loc.getLocations(enumWhLocVol.盘点, 1);
            if (locations.Count == 0)
            {
                locations = loc.getLocations(enumWhLocVol.盘点, 1);
            }
            if (locations.Count > 0)
            {
                loc = locations[0];
            }
            else
            {
                throw new Exception("没有虚拟库库位,请创建虚拟库位");
            }
            logSpec.Debug(" 出周转 虚拟库库位 。。 " + loc.locationId);
            WmsStock stk = new WmsStock(loc.locationId, skuId, goodsId);
            stk.locationId = loc.locationId;
            stk.skuId = skuId;
            stk.skuCode = String.IsNullOrEmpty(stk.skuCode) ? wmsStock.skuCode : stk.skuCode;
            stk.productDate = String.IsNullOrEmpty(stk.productDate) ? wmsStock.productDate : stk.productDate;
            stk.validDate = String.IsNullOrEmpty(stk.validDate) ? stk.productDate : stk.validDate;
            stk.batch = String.IsNullOrEmpty(stk.batch) ? stk.productDate : stk.batch;
            if (stk.ID == 0
                || string.IsNullOrEmpty(stk.goodsId)
                || stk.goodsId != goodsId) //商品没有虚拟记录
            {
                stk.goodsId = goodsId;
                stk.count = adjustCnt * -1;
                stk.Add();
                logSpec.Debug("新增盘点虚拟库存 " + stk);
            }
            else
            {
                stk.count += adjustCnt * -1;
                stk.Update();
                logSpec.Debug("更新 盘点虚拟库存 " + stk);
            }
        }
        /// 
        /// 清空location
        /// 
        /// 
        /// 
        /// 
         public bool clearLocation(string locId, string reason)
         {
             _obj = new WmsStock();
             List sks = _obj.getStockObjs(locId);
             try
             {
                 using (TransactionScope scope = new TransactionScope())
                 {
                     foreach (WmsStock obj in sks)
                     {
                         if (obj.ID == 0)
                         {
                             return false;
                         }
                        string description = string.Format("业务类型:{0},调整前数量{1},调整后数量{2},备注:{3}", enumStockRecordType.手持盘点.ToString(), obj.count - obj.countOut , 0, reason);
                        WmsStockRecord strec = new WmsStockRecord();
                         strec.batch = obj.batch;
                         strec.skuId = obj.skuId;
                         strec.skuCode = obj.skuCode;
                         strec.goodsId = obj.goodsId;
                         strec.locationId = locId;
                         strec.orderNo = _obj.goodsId; // "StockGoodsCheck";
                         strec.productDate = obj.productDate;
                         strec.validDate = obj.validDate;
                         strec.operater = this.operId;
                         strec.description =description;
                         strec.count = 0;
                         strec.count1 = obj.count - obj.countOut;
                         strec.rectype = (int)enumStockRecordType.手持盘点;
                         obj.Delete();
                         strec.Add();
                     }
                     scope.Complete();
                 }
             }
             catch (Exception e)
             {
                 return false;
             }
             return true;
         }
         public bool updateLocationStatus(string locId, int status)
         {
             WmsLocation loc = new WmsLocation(locId);
             if (loc.state != status)
             { 
                 loc.state = status;
                 loc.operater = this.operId;
                 return loc.Update() > 0;
             }
             return true;
         }
         public bool updateGoodsLocationVolume(string goodsId,int volType,decimal volume)
         {
             WmsGoods goods = new WmsGoods(goodsId);
             enumWhLocVol vt = (enumWhLocVol)volType;
             switch (vt)
             {
                 case  enumWhLocVol.小整:
                     goods.batchMax1 = volume;
                     break;
                 case enumWhLocVol.中整:
                     goods.batchMax2 = volume;
                     break;
                 case enumWhLocVol.大整:
                     goods.batchMax3 = volume;
                     break; 
                 case enumWhLocVol.零库:
                     goods.bulkMax = volume;
                     break;
                 case enumWhLocVol.零库1:
                     goods.bulkMax1 = volume;
                     break;
                
             } 
       
                 goods.operater = this.operId;
                 return goods.Update() > 0;
           
            
         }
         /// 
         /// 补货入库
         /// 
         /// 
         /// 
         /// 
         /// 
         /// 
         /// 
         public enumRepResult repItemIn(string locId, string goodsId, int skuId, string batch, decimal count, int portId)
         {  
             WmsOutPickPort wpp = new WmsOutPickPort(portId);
             if (wpp.state == (int)enumPickState.复核完成)
             {
                 return enumRepResult.状态已完成上架;
             }
             if (wpp.state == (int)enumPickState.未拣)
             {
                 return enumRepResult.状态待拣货;
             }
             //check loc is okay  for the goods
             enumRepResult r = validLocation(locId, goodsId, skuId, batch, count);
             if (r != enumRepResult.成功)
             {
                 return  r;
             }
             lWmsStock lstock = new lWmsStock(operId); //传入operId
            // using (TransactionScope scope = new TransactionScope())
             {
                 lstock.updateStockLocation(locId, goodsId, skuId,batch, count, "补零", enumStockRecordType.补零入库);
                  
                 wpp.pickCount += count;
                 wpp.operater = operId;
                 if (wpp.pickCount >= wpp.count)
                 {
                     wpp.state = (int)enumPickState.复核完成;//结束补货流程
                 }
                 wpp.Update();
                /*
                 if (wpp.isDoneByFlow(wpp.flowNo))
                 {
                     WmsFlow.done(wpp.flowNo);
                     //WmsFlow.free(wpp.flowNo);
                 }
                 */
               //  scope.Complete();
             }
             return 0;
         }
         public enumRepResult validLocation(string locId, string goodsId, int skuId, string batch, decimal count)
         {
             WmsLocation loc = new WmsLocation(locId);
             WmsGoods goods = new WmsGoods(goodsId);
             decimal maxcnt = 0;
             decimal percent = 0;
             if (loc.ID == 0)
             {
                 return enumRepResult.货位不存在;
             }
             if (loc.state != (int)enumStockLocationStatus.正常)
             {
                 return enumRepResult.货位不可用;
             }
            enumWhLocStoreType enSt = (enumWhLocStoreType)loc.storeType;
            if (enSt == enumWhLocStoreType.虚拟库位 
                || enSt == enumWhLocStoreType.不良品  
                )
            {
                return enumRepResult.成功;
            }
            if (WmsConstants.VALID_LOC_CAPICITY)
            {
                maxcnt = goods.getMaxCount(loc.volType);
             
                percent += count / maxcnt;
                log.Debug(string.Format(" 库容验证 locid {0}, skuid {1},count {2},maxcnt {3},percent {4}, bigcount {5},percent > 1 {6}", locId, skuId, count, maxcnt, percent,goods.bigCount, percent > 1));
                if (percent > 1)
                { 
                    return enumRepResult.库容不足;
                }
            }
             if (loc.state != (int)enumStockLocationStatus.正常)
             {
                 return (enumRepResult)loc.state;
             }
             else if (WmsConstants.PDA_LOC_GOODTYPE_VALIDATION && loc.goodsType>0 && loc.goodsType != goods.goodsType) //商品类型不符
             {
                 return enumRepResult.货位商品类型不符;
             }
            else if (WmsConstants.PDA_LOC_GOODTYPE_VALIDATION && loc.warehouse > 0 && loc.warehouse != goods.part) //存储库区类型不符
            {
                return enumRepResult.货位库区不符;
            }
            else if (WmsConstants.IN_STOCK_ABC && loc.ABC != goods.ABC) //商品ABC类型不符
             {
                 return enumRepResult.ABC不符;
             }
             else if (loc.whType == (int)enumWhType.不合格库) //非合格库
             {
                 return enumRepResult.货位非合格库;
             }
             else if (loc.isFree(locId))
             {
                 return enumRepResult.成功;
             }
             else
             {
                 if ((enumWhLocVol)loc.volType == enumWhLocVol.小整 || (enumWhLocVol)loc.volType == enumWhLocVol.中整
                     || (enumWhLocVol)loc.volType == enumWhLocVol.大整)
                 {
                     if (goods.bigCount == 0 || count < goods.bigCount || count % goods.bigCount > 0)
                     {
                         return enumRepResult.整库只能整进整出;
                     }
                 }
                 WmsStock stock = new WmsStock();
                 DataTable dt = stock.getStocks(locId);
                
                 switch (enSt)
                 {
                     case enumWhLocStoreType.同品同批:
                         foreach (DataRow dr in dt.Rows)
                         {
                             stock = new WmsStock(dr);
                            if (stock.isCanDelete())
                            {
                                stock.Delete();
                                continue;
                               // return enumRepResult.成功;
                            }
                             if (!stock.goodsId.Trim().Equals(goodsId))
                             {
                                 /*if (stock.count - stock.countOut == 0 && stock.countIn == 0 && stock.countOuting == 0)
                                 {
                                     stock.Delete();
                                     return enumRepResult.成功;
                                 }*/
                                 return enumRepResult.货位已被其他商品占用;
                             }
                             else
                                 if (stock.skuId > 0 && stock.skuId != skuId
                                 || !string.IsNullOrEmpty(stock.batch) && !stock.batch.Equals(batch))
                                 {
                                    /* if (stock.isCanDelete())
                                     {
                                         stock.Delete();
                                    stock.updateCountOut();
                                         return enumRepResult.成功;
                                     }
                                     else
                                    */
                                         return enumRepResult.货位商品同品不同批;
                                 }
                         }
                         break;
                     case enumWhLocStoreType.混品同批:
                         foreach (DataRow dr in dt.Rows)
                         {
                             stock = new WmsStock(dr);
                            if (stock.isCanDelete())
                            {
                                stock.Delete();
                                continue;
                                // return enumRepResult.成功;
                            }
                            if (stock.goodsId.Equals(goodsId) && ( //同品不同批
                                        stock.skuId > 0 && stock.skuId != skuId
                                         || !string.IsNullOrEmpty(stock.batch) && !stock.batch.Equals(batch))
                                 )
                             {
                                /* if (stock.count - stock.countOut == 0 && stock.countIn == 0 && stock.countOuting == 0)
                                 {
                                     stock.Delete();
                                     return enumRepResult.成功;
                                 }
                                 else
                                    */
                                     return enumRepResult.货位商品同品不同批;
                             }
                         }
                         break;
                     case enumWhLocStoreType.同品混批:
                         foreach (DataRow dr in dt.Rows)
                         {
                             stock = new WmsStock(dr);
                            if (stock.isCanDelete())
                            {
                                stock.Delete();
                                continue;
                                // return enumRepResult.成功;
                            }
                            if (!stock.goodsId.Equals(goodsId))
                             {
                                 return enumRepResult.货位已被其他商品占用;
                             }
                         }
                         break;
                     case enumWhLocStoreType.混品混批:
                         break;
                 }
                 //计算库容是否够  
                 
                 /*foreach (DataRow dr in dt.Rows)
                 {
                     stock = new WmsStock(dr);
                     goods = new WmsGoods(stock.goodsId);
                     decimal cnt = stock.count - stock.countOut + stock.countIn;
                     maxcnt = goods.getMaxCount(loc.volType);
                     maxcnt = maxcnt > 0 ? maxcnt : 1;
                     percent += cnt / maxcnt;
                     if (percent > 1)
                     {
                         break;
                     }
                 }*/
                 percent = stock.getUsedPercent(locId);
                 
                 maxcnt = goods.getMaxCount(loc.volType);
                  
                 decimal freeCntCapicity= Math.Ceiling((1 - percent) * maxcnt);
              
                log.Debug(string.Format(" 库容验证 freeCntCapicity {0}, skuid {1},count {2},maxcnt {3},percent {4}, bigcount {5},percent > 1 {6}", locId, skuId, count, maxcnt, percent, goods.bigCount, percent > 1));
                if (freeCntCapicity 
         /// 自动分配零库货位
         /// 
         /// 
         /// 
         /// 
         /// 
         public DataTable getBulkLocations(int skuId,string skuCode,string goodsId, string batch, decimal count)
         {
            decimal oCnt = count;
             WmsStock stock = new WmsStock();
             WmsGoods goods = new WmsGoods(goodsId);
             DataTable dtLocs = new DataTable("locs"); //自己构造的datatable一定要命名!!!不然wcf 序列化有问题
             if (goods.ID == 0) //没找到商品
             {
                 return dtLocs;
             }
              
             string lastBulkLocation = "";
             DataTable dt = stock.querySameGoodsLocations(goodsId, enumWhLocVol.零库, skuId, batch );
             Dictionary locs = new Dictionary();
             decimal goodsMaxcnt = goods.getMaxCount((int)enumWhLocVol.零库);
             goodsMaxcnt = goodsMaxcnt > 0 ? goodsMaxcnt : WmsConstants.BULK_MAX_RATE * goods.bigCount;//200m;
             string lastLoc = "";
             foreach (DataRow dr in dt.Rows)  //补现有的货位,商品已在这些货位中 
             { 
                 stock = new WmsStock(dr);
                 if (stock.locationId == WmsConstants.TMP_BATCH_LOCATION ||
                     stock.locationId == WmsConstants.TMP_BULK_LOCATION)
                 {
                     continue;
                 }
                 if (lastLoc == "") 
                 {
                     lastLoc = stock.locationId;
                 }else
                 if(lastLoc.Equals(stock.locationId)){
                     continue;
                 }
                 lastLoc = stock.locationId;
                /*
                 int locVolType =  Convert.ToInt32(dr[WmsLocation.fields.volType.ToString()].ToString());
                 enumWhLocVol volType = (enumWhLocVol)locVolType;
                 if (volType != enumWhLocVol.零库)
                 {
                     continue;
                 } 
                 */
                  
                 lastBulkLocation = stock.locationId;
                 enumWhLocStoreType stype = (enumWhLocStoreType) Convert.ToInt32(dr["storeType"].ToString());
                 switch (stype)
                 {
                     case enumWhLocStoreType.同品同批:
                         if (stock.batch != batch || stock.skuId != skuId)
                         {
                             continue;
                         }
                         break;
                     case enumWhLocStoreType.混品同批:
                         if (stock.batch != batch || stock.skuId != skuId)
                         {
                             continue;
                         }
                         break;
                 }
                decimal freeCntCapicity= Math.Ceiling((1 - stock.getUsedPercent(lastBulkLocation)) * goodsMaxcnt);
                if (freeCntCapicity <= 0)
                {
                    continue;
                }
                if (count > freeCntCapicity  )
                {
                    if (!WmsConstants.BOX_BULK_IN_SINGLE_LOC)
                    {
                        locs.Add(stock.locationId, freeCntCapicity);
                        count -= freeCntCapicity;
                    }
                }
                else
                {
                    locs.Add(stock.locationId, count);
                    count = 0;
                    break;
                }
                /*
                 decimal cnt = stock.count - stock.countOut - stock.countIn;// - stock.countLock;
                 cnt = cnt > 0 ? cnt : 0;
                if (cnt < goodsMaxcnt) //补充货位
                {
                    lastBulkLocation = stock.locationId;
                    decimal c = goodsMaxcnt - cnt;
                    if (c < count) // 需要新货位
                    {
                        count -= c; //补现有货位后,剩余的入新货位
                    }
                    else
                    {
                        c = count;
                        count = 0;
                    }
                    locs.Add(stock.locationId, c);
                }*/
             }
            
            if (count > 0) //新货位
             {
                 WmsLocation nearLocation = new WmsLocation();
                 nearLocation.goodsType = goods.goodsType;
                 nearLocation.whType = (int)enumWhType.合格库;
                 nearLocation.volType = (int)enumWhLocVol.零库;
                 nearLocation.locationId = lastBulkLocation;
                 nearLocation.ABC = goods.ABC;
                nearLocation.warehouse = goods.part;
                 decimal cnt = count / goodsMaxcnt;
                 int locCnt = (int)Math.Ceiling(cnt);
                try
                {
                    List newLocs = nearLocation.getFreeLocation(nearLocation, enumWhType.合格库, locCnt);
                    foreach (WmsLocation loc in newLocs)
                    {
                        if (count <= 0)
                        {
                            break;
                        }
                        locs.Add(loc.locationId, count > goodsMaxcnt ? goodsMaxcnt : count);
                        count -= goodsMaxcnt;
                    }
                }
                catch (DeiNiuNoFreeLocationkException er) //大小整货位不足
                {
                }
              
                 if (count>0 && WmsConstants.NO_FREE_LOCATION_USE_TMP)
                 {
                     locs.Add( WmsConstants.TMP_BULK_LOCATION, count);
                 }
             }
             if (count > 0) //和其他商品或批次共用货位
             {
                 int locCnt = (int)Math.Ceiling(count / goodsMaxcnt)*50;
                 dt = stock.queryOtherSharingLocations( goods, (int)enumWhLocVol.零库, locCnt);
                 lastLoc = "";
                 foreach (DataRow dr in dt.Rows)
                 {
                     stock = new WmsStock(dr);
                     if (lastLoc == "")
                     {
                         lastLoc = stock.locationId;
                     }
                     else
                         if (lastLoc.Equals(stock.locationId))
                         {
                             continue;
                         }
                     lastLoc = stock.locationId;
                      
                     lastBulkLocation = stock.locationId;
                     decimal freeCntCapicity =Math.Ceiling(  (1 - Convert.ToDecimal( dr["usedPercent"].ToString())) * goodsMaxcnt);
                     if (freeCntCapicity <= 0)
                     {
                         continue;
                     }
                     if (count > freeCntCapicity)
                     {
                         locs.Add(stock.locationId,  freeCntCapicity );
                         count -= freeCntCapicity;
                     }
                     else
                     {
                         locs.Add(stock.locationId, count);
                         count = 0;
                         break;
                     }
                 } 
             }
             DataColumn dc1 = new DataColumn();
             dc1.ColumnName = "推荐货位";
             dc1.DataType = typeof(string);
             DataColumn dc2 = new DataColumn();
             dc2.ColumnName = "数量";
             dc2.DataType = typeof(decimal);
             dtLocs.Columns.Add(dc1);
             dtLocs.Columns.Add(dc2);
            //---> 修正因取整,而可能造成的小数变为0的情况
            decimal assignedCnt = 0;
            foreach (string key in locs.Keys)
            { 
                assignedCnt += locs[key];
            }
            if (assignedCnt < oCnt)
            {
                foreach (string key in locs.Keys)
                {
                   if( locs[key] == 0)
                    {
                        locs[key] = oCnt - assignedCnt;
                        break;
                    };
                }
            }
            //-----<<
            foreach (string key in locs.Keys)
             {
                 DataRow dr = dtLocs.NewRow();
  
                 dr[0] = key;
                 dr[1] = locs[key].ToString();
                 dtLocs.Rows.Add(dr);
             }
             return dtLocs;
         }
         public bool newMaintain(int stockId, decimal mCount, decimal issueCount, string details  )
         {
             enumStockLocationStatus type = issueCount > 0 ? enumStockLocationStatus.养护异常 : enumStockLocationStatus.正常;
             WmsStock stk = new WmsStock(stockId); 
             WmsStockMaintain wm = new WmsStockMaintain();
             wm.operater = operId;
             wm.locationId = stk.locationId;
             wm.mcount = mCount;
             wm.productDate = stk.productDate;
             wm.validDate = stk.validDate;
             wm.issueCount = issueCount;
             wm.goodsId = stk.goodsId;
             wm.batch = stk.batch;
             wm.skuId = stk.skuId;
             wm.skuCode = stk.skuCode;
             wm.details = details;
             wm.issueType = (int)type;
              
             try
             {
                 using (TransactionScope scope = new TransactionScope())
                 {
                     wm.Add();
                     if (issueCount > 0)
                     {
                         stk.maintainIssue(stk.skuId, enumStockLocationStatus.养护异常, operId);
                     }
                     stk.recordMaintain(stk.locationId,operId);
                     scope.Complete();
                 }
             }
             catch(Exception e)
             {
                // throw e;
                 return false;
             }
             return true;
         }
         internal bool fixIssueData(int skuId)
         {
             return _obj.maintainIssue(skuId, enumStockLocationStatus.正常, operId) > 1; 
         }
        //---initial stock data for skuId,skuCode
        /// 
        /// 库存初始化sku 属性
        /// 
         internal void initialSkus(bool isDownOnly,int start)
         {
            // initialLocaitons();
            if (isDownOnly)
            {
                //downAll(start);
                downAllByGoodsPart(start);
                return;
            }
          
            DataTable stks = wmsStock.queryBySku(0,enumWhLocVol.通用);
             string skuCode;
             Dictionary skuValues = new Dictionary();
             lLot lot = new lLot();
            log.Debug(string.Format("stks.Rows count {0} ",stks.Rows.Count));
            foreach (DataRow dr in stks.Rows)
             {
                 WmsStock s = new WmsStock(dr);
                 skuValues.Clear();
                /*
                 skuValues.Add(WmsConstants.SKU_RESEVRED_BATCH_ATTNAME,  s.batch .Trim());
                 skuValues.Add(WmsConstants.SKU_RESEVRED_PRDDATE_ATTNAME, Util.getShortDateString(s.productDate.Trim()));
                 skuValues.Add(WmsConstants.SKU_RESEVRED_EXPIREDATE_ATTNAME,Util.getShortDateString(getValidDate( s.validDate.Trim(),s.goodsId).ToShortDateString()));
                */
                
                skuValues.Add(WmsConstants.SKU_RESEVRED_BATCH_ATTNAME, s.batch.Trim());
                string prd = Util.getShortDateString(s.batch.Trim());
                string valid = Util.getShortDateString(getValidDate(prd, s.goodsId).ToShortDateString());
                skuValues.Add(WmsConstants.SKU_RESEVRED_PRDDATE_ATTNAME, prd);
                skuValues.Add(WmsConstants.SKU_RESEVRED_EXPIREDATE_ATTNAME, valid);
                s.productDate = prd;
                s.validDate = valid;
                // skuValues.Add("批次属性测试1", "7333" );
                /*
                 skuCode = string.Format("{0}:{1};", "goodsId", s.goodsId.Trim());              
                 skuCode += string.Format("{0}:{1};", WmsConstants.SKU_RESEVRED_PRDDATE_ATTNAME, Util.getShortDateString(s.productDate.Trim()));
                 skuCode += string.Format("{0}:{1};", WmsConstants.SKU_RESEVRED_EXPIREDATE_ATTNAME, Util.getShortDateString(s.validDate.Trim()));
                 skuCode += string.Format("{0}:{1};", WmsConstants.SKU_RESEVRED_BATCH_ATTNAME, s.batch.Trim());
                 */
                // skuCode += string.Format("{0}:{1};", "批次属性测试1",  "蓝色");
                // string ownerCode = "LNTHYYYXGS1";// dr["ownerCode"].ToString();//;
                //   int skuId = lot.getSKU(skuCode, skuValues, 1, s.goodsId, ownerCode);
                // skuValues[WmsConstants.SKU_RESEVRED_PRDDATE_ATTNAME] = Util.getShortDateString(skuValues[WmsConstants.SKU_RESEVRED_PRDDATE_ATTNAME]);
                // skuValues[WmsConstants.SKU_RESEVRED_EXPIREDATE_ATTNAME] = Util.getShortDateString(s.validDate.ToShortDateStri );
                Dictionary dic = lot.getSKU(prd, s.goodsId, s.batch.Trim());
                foreach (int i in dic.Keys)
                {
                    //skuId = i;
                    s.skuId = i;
                    s.skuCode = dic[i];
                    break;
                }
                // s.skuId = skuId;
                // s.skuCode = skuCode;
                s.operater = operId;
                s.adjustingCnt = 0;
                s.plateCount = 0;
                s.countLock = 0;
                s.state = 0;
                s.Update();
             
             }
         
        }
         internal void initialLocaitons()
         {
             WmsLocation loc = new WmsLocation();
            DataTable dt = loc.QueryActived().Tables[0];
            DataView dv = dt.DefaultView;
           // dv.RowFilter = "len(locationid)>9 and isnull(channel,0)=0";
            foreach (DataRowView dr in dv)
            {
                try
                {
                    loc = new WmsLocation(dr.Row);
                    string locId = loc.locationId.Substring(4);
                    string channel = locId.StartsWith("0") ? locId.Substring(1, 1) : locId.Substring(0, 2);
                    locId = locId.Substring(2);
                    string shelf = locId.StartsWith("0") ? locId.Substring(1, 1) : locId.Substring(0, 2);
                    locId = locId.Substring(2);
                    locId = loc.locationId.Substring(8);
                    string h = locId.Substring(0, 1);
                    string l = locId.Substring(1);
                    loc.channel =  Convert.ToInt32(channel);
                    loc.shelf =  Convert.ToInt32(shelf);
                    loc.layer =  Convert.ToInt32(h);
                    loc.col =  Convert.ToInt32(l);
                    loc.state = 0;
                    loc.createtime = loc.getDateTime();
                    loc.locationId128 = Util.getCode128(loc.locationId);
                    loc.Update();
                }
                catch (Exception er)
                {
                    continue;
                }
            } 
         }
        /// 
        /// 库存初始化时,按库位导入数据
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
         internal enumRepResult initialStockIn(string goodsId, string locId, decimal batchCount, string prdDate,string batch) {
           
            /*
            DateTime pDate = Util.pareseDateString(prdDate);
            string validDate = getDateStr( getValidDate(prdDate, goodsId));
            batch =string.IsNullOrEmpty(batch)?prdDate:batch;
            /*Dictionary sku = new Dictionary();
            sku[WmsConstants.SKU_RESEVRED_PRDDATE_ATTNAME] = prdDate;
            sku[WmsConstants.SKU_RESEVRED_EXPIREDATE_ATTNAME] = validDate;
            sku[WmsConstants.SKU_RESEVRED_BATCH_ATTNAME] = batch;
            */
            if (getLeftDays(prdDate, goodsId) <= 0)
            {
                return enumRepResult.过期商品;
            }
            if (isNearExpired(prdDate, goodsId))
            {
                return enumRepResult.临期商品;
            }
            int skuId =0;
            Dictionary dic = new lLot(operId).getSKU(prdDate, goodsId, batch);   
            foreach (int i in dic.Keys)
            {
                skuId = i;
                break;
            }
            
          
            return upDownGoodsCountWithLocation(locId, goodsId, skuId, batch
                , batchCount, "初始盘点入库", enumStockRecordType.初始盘点, -1);
           
         }
        //初始化 erp 销售明细 sku信息
         public void initialErpSaledSku()
         {
             Erp_sale_d esd = new Erp_sale_d();
             WmsStock stk = new WmsStock();;
             DataTable dt = esd.QueryActived().Tables[0];
             foreach(DataRow dr in dt.Rows){
                 esd = new Erp_sale_d(dr);
                 DataTable dt1 = stk.getStockInfo(esd.goods_id);
                 foreach (DataRow  dr1 in dt1.Rows)
                 {
                     stk = new WmsStock(dr1);
                     esd.skuCode = stk.skuCode;
                     esd.skuId = stk.skuId;
                     esd.batch = stk.batch;
                     esd.product_date = stk.productDate;
                     esd.save_date = stk.validDate;
                     esd.Update();
                     break;
                 }
             }
         }
        public void downAll(int start)
        {
            
            WmsStock stock = new WmsStock();
            DataTable dt = stock.QueryActived().Tables[0];
            logTest.Debug(" downall stock list cnt" + dt.Rows.Count);
            DataView dv = dt.DefaultView;
            dv.Sort = "locationId";
            foreach(DataRowView dr in dv)
            {
                
                stock = new WmsStock(dr.Row);
                string flow = stock.locationId.Substring(0, 1);
                if (stock.locationId.StartsWith(start+"") || start==0) 
                this. upDownGoodsCountWithLocation(stock.locationId,stock.goodsId,stock.skuId, stock.batch, stock.count, "初始下架", enumStockRecordType.移库下架, 0, flow);
            }
           
           
           // WmsStock stock = new WmsStock();
           // DataTable   dt = stock.queryTmps() ;
            /*  
            DataView dv = dt.DefaultView;
            dv.Sort = "pickdetailId";
             
            foreach (DataRowView dr in dv)
            {
                WmsOutPickPort wop = new WmsOutPickPort(dr.Row);
                WmsOutPickDetail wpd = new  WmsOutPickDetail(wop.pickDetailId); 
                wpd.bulkPicked += wop.pickCount;
                wpd.Update(); 
                
            }
             */
 
            /*
            dt = stock.queryTmps();
            lWmsOutPickRequest lop = new lWmsOutPickRequest(operId);
            foreach (DataRow  dr in dt.Rows)
            {
              lop.finishRequest( new WmsOutPickRequest(dr));
              
             
            }
            */
            /*
            DataSet ds = stock.queryTmps();
            DataTable dtStk = ds.Tables[0];
            DataTable dtTmp = ds.Tables[1];
            DataView dv = dtTmp.DefaultView;
            foreach(DataRow dr in dtStk.Rows)
            {
                WmsStock stk = new WmsStock(dr);
                dv.RowFilter = "goodsId ='" + stk.goodsId + "'";
                foreach(DataRowView drv in dv)
                {
                    stk.count = Convert.ToDecimal( drv["count"].ToString());
                    stk.Update();
                } 
            }
            dv = dtStk.DefaultView;
          
            
            foreach (DataRow dr in dtStk.Rows)
            {
                WmsStock tmp = new WmsStock(dr);
                dv.RowFilter = "goodsId='" + tmp.goodsId +"'";
                if (dv.Count == 0)
                {
                    WmsStock stk = new WmsStock();
                    stk.goodsId = tmp.goodsId;
                    stk.count = tmp.count;
                    stk.Update();
                }
            }
            */
        }
        public void downAllByGoodsPart(int start)
        {
            WmsStock stock = new WmsStock();
            DataTable dt = stock.QueryActived().Tables[0];
            logTest.Debug(" downall stock list cnt" + dt.Rows.Count);
            DataView dv = dt.DefaultView;
            dv.Sort = "locationId";
            foreach (DataRowView dr in dv)
            {
                string flow = "1";
                stock = new WmsStock(dr.Row);
                WmsGoods gd = new WmsGoods(stock.goodsId);
                if (stock.locationId.StartsWith(start + ""))
                {
                    flow = start + "";
                    this.upDownGoodsCountWithLocation(stock.locationId, stock.goodsId, stock.skuId, stock.batch, stock.count, "初始下架", enumStockRecordType.移库下架, 0, flow);
                    continue;
                }
                 
                if (gd.part > 0)
                {
                    Node nd = new Node(gd.part);
                    flow = nd.name;
                    if (gd.ABC > 0)
                    {
                        switch (nd.name)
                        {
                            case "1":
                                if (gd.ABC == 6294)
                                    flow = "13";
                                else
                                {
                                    flow = "15";
                                }
                                break;
                            case "2":
                                flow = "22";
                                break;
                            case "3":
                                flow = "32";
                                break;
                        }
                    }
                }
               
                if (start+""==flow|| start == 0)
                    this.upDownGoodsCountWithLocation(stock.locationId, stock.goodsId, stock.skuId, stock.batch, stock.count, "初始下架", enumStockRecordType.移库下架, 0, flow);
            }
        }
        }
    }