/// 
///INTERFACE CLASS FOR TABLE t_wmslocation
///By wm with codesmith. 
///on 05/02/2017
/// 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using DeiNiu.Utils;
namespace DeiNiu.wms.Data.Model
{
    [Serializable]
    public class WmsLocation : WmsLocation_base
    {
        private int _partion=0;
        public int partion
        {
            get {
                if (_partion==0 && ID > 0)
                {
                    DataTable dt = CustQuery(10).Tables[0];
                    if (dt.Rows.Count > 0)
                    {
                        dt.Rows[0]["partion"].ToString();
                        if (dt.Columns.Contains("partion") && !(dt.Rows[0]["partion"] is DBNull))
                        {
                            _partion = Convert.ToInt32(dt.Rows[0]["partion"].ToString());
                        }
                    }
                }
                return _partion; 
            }
            set { _partion = value; }
        }
        public WmsLocation()
        {
        }
        public WmsLocation(SqlConnection _Conn):base(_Conn) 
        {
        }
        public WmsLocation(int id): base(id)
        {
        }
         public WmsLocation(DataRow dr): base(dr)
        {
        }
         public WmsLocation(String locationId) 
         {
             cmdParameters[0] = locationId;
             getModel(10);
         
             
         }
         public new int Add()
         {
             base.Add();
             this.locationId128 = Util.getCode128(locationId + "");
             Update();
             return ID;
         }
         protected override void getImp()
         {
             model_imp = new Wmslocation_Imp();
         }
        //begin cust db operation, query, excute sql etc.
        //public override DataSet Query()  
        //{ 
        //    return  CustQuery(100);
        //}
        public WmsLocation getVirLocations(int part)
        {
            return getLocation(enumWhLocVol.虚拟, part,0);
        }
        public WmsLocation getLocation(enumWhLocVol volType,int part,int abc)
        {
           // getFreeLocation()
            List locations = getLocations(volType, 1,abc,part);
            foreach (WmsLocation l in locations)
            {
                if (l.warehouse == part)
                {
                    return l;
                }
            }
            if (locations.Count > 0)
            {
                return locations[0];
            }
            else
            {
              //  throw new Exception( string .Format("没有库位,请创建库位,库位类型 {0}, part {1}, abc {2} ",    volType.ToString(),part,abc));
                return new WmsLocation("11.01.01.11");
            }
        }
        public List getLocations( enumWhLocVol whLocVol, int count = 1,int abc=0,int part=0)
         {
             List locations = new List();
             cmdParameters[0] = count;
             cmdParameters[1] = (int)whLocVol;
             cmdParameters[2] = abc;
             cmdParameters[3] = part ;
            DataSet ds = CustQuery(301);
             int freeCnt = 0;
             foreach (DataTable dt in ds.Tables)
             {
                 freeCnt += dt.Rows.Count;
             }
             
             foreach (DataTable dt in ds.Tables)
             {
                 foreach (DataRow dr in dt.Rows)
                 {
                     locations.Add(new WmsLocation(dr));
                     if (locations.Count == count)
                     {
                         return locations;
                     }
                 }
             }
             if (locations.Count < count) //未找到足够空货位
             {
                 LogHelper.debug(this.GetType(), "0 to free location in stock , whLocVol? " + whLocVol);
                 freeLocations();
                 string error = string.Format("空货位不足,需要{0}个,找到{1}个。", count, locations.Count);
                 // throw new DeiNiuNoFreeLocationkException(error);
             }
             return locations;
         }
        public List getLocations(int wareHouse,int volType, enumWhType whType, int count = 1)
        {
            List locations = new List();
            cmdParameters[0] = count;
            cmdParameters[1] = (int)whType;
            cmdParameters[2] = wareHouse;
            cmdParameters[3] = volType;
            DataSet ds = CustQuery(302);
            int freeCnt = 0;
            foreach (DataTable dt in ds.Tables)
            {
                freeCnt += dt.Rows.Count;
            }
            foreach (DataTable dt in ds.Tables)
            {
                foreach (DataRow dr in dt.Rows)
                {
                    locations.Add(new WmsLocation(dr));
                    if (locations.Count == count)
                    {
                        return locations;
                    }
                }
            }
         
            return locations;
        }
        public List getNewLocations(decimal count, WmsGoods goods, enumWhLocVol volType)
        {
            List newLocs = new List();
            decimal goodsMaxcnt = goods.getMaxCount((int)volType);
            if (count > 0)
            {
                WmsLocation nearLocation = new WmsLocation();
                nearLocation.goodsType = goods.goodsType;
                nearLocation.whType = (int)enumWhType.合格库;
                nearLocation.volType = (int)volType;
                // nearLocation.locationId = lastBulkLocation;
                nearLocation.ABC = goods.ABC;
                nearLocation.warehouse = goods.part;
                decimal cnt = count / goodsMaxcnt;
                int locCnt = (int)Math.Ceiling(cnt);
                try
                {
                    newLocs = nearLocation.getFreeLocation(nearLocation, enumWhType.合格库, locCnt);
                }
                catch (DeiNiuNoFreeLocationkException er) //大小整货位不足
                {
                }
            }
            return newLocs;
        }
        public int updateLocJobCross(string whereIds, bool isCross, int operId)
        {
            cmdParameters[0] = whereIds;
            cmdParameters[1] = isCross;
            cmdParameters[2] = operId;
            return CustOper(720) ;
        }
        public List getFreeLocation(WmsLocation nearLocation,enumWhType whType,int count =1 )
        {
            List locations = new List();
            if (nearLocation != null && nearLocation.warehouse == 0  )
            {
                nearLocation.warehouse = WmsConstants.IN_STOCK_DEFAULT_WAREHOUSE;
                if (WmsConstants.IN_STOCK_DEFAULT_WAREHOUSE == 0)
                {
                    throw new DeiNiuException("请设置商品的默认库房存储分区信息");
                }
            }
            LogHelper.debug(GetType(), "start to get locations...>");
            LogHelper.debug(GetType(), Util.getJson(nearLocation));
            cmdParameters[0] = nearLocation.locationId;
            cmdParameters[1] = nearLocation.goodsType;
            cmdParameters[2] = nearLocation.volType;
            cmdParameters[3] = count;
            cmdParameters[4] = (int)whType;
            cmdParameters[5] = nearLocation.ABC;
            cmdParameters[6] = nearLocation.ownerCode;
            cmdParameters[7] = nearLocation.warehouse;
            DataSet ds = CustQuery(300);
            int freeCnt = 0;
            foreach (DataTable dt in ds.Tables)
            {
                foreach(DataRow dr in dt.Rows)
                {
                    freeCnt += new WmsLocation(dr).scaleFactor;
                }
                 
               // freeCnt += dt.Rows.Count;
            }
            if (freeCnt < count)
            {
                LogHelper.debug(this.GetType(), "1 to free location in stock , whtype? " + whType);
                freeLocations();
                ds = CustQuery(300);
            }
            freeCnt = 0;
            WmsLocation loc;
            foreach (DataTable dt in ds.Tables)
            {
                foreach (DataRow dr in dt.Rows)
                {
                    loc = new WmsLocation(dr);
                    freeCnt += loc.scaleFactor;
                    locations.Add(loc);
                   if (freeCnt >= count)
                   {
                        LogHelper.debug(GetType(), " end get locations...<<");
                        return locations;
                   }
                }
            }
           
            
            if (freeCnt > 0 ) //未找到足够空货位
            {
                LogHelper.debug(this.GetType(), "2 to free location in stock , whtype? " + whType);
                freeLocations();
                string error = string.Format("货区 {3} volType {2} 空货位不足,需要{0}个,找到{1}个。", count, locations.Count,nearLocation.volType,nearLocation.warehouse);
                LogHelper.debug(GetType(),error);
              
            }
            else
            {  
                LogHelper.debug(GetType(), " end get locations...<<");
                    throw new DeiNiuNoFreeLocationkException();
            }
            LogHelper.debug(GetType(), " end get locations...<<");
            return locations;
        }
        /// 
        /// 清除空货位
        /// 
        /// 
        public int freeLocations()
        {
            int count = CustOper(400);
            
            return count;
        }
        /// 
        /// get location info by locId
        /// 
        /// 
        public DataTable getLocations(string locId)
        {
            cmdParameters[0] = locId;
            return CustQuery(500).Tables[0];
        }
        public bool updateWhLocations(string p, Structs locs,int operId)
        {
            cmdParameters[0] = p;
            cmdParameters[1] = locs.whType;
            cmdParameters[2] = locs.whVoltype;
            cmdParameters[3] = locs.goodsType;
            cmdParameters[4] = locs.volType;
            cmdParameters[5] = locs.part;
            cmdParameters[6] = operId;         
            return CustOper(600)>0;
        }
        public bool updateSizeLocations(string p, Structs locs, int operId)
        {
            cmdParameters[0] = p;
            cmdParameters[1] = locs.length;
            cmdParameters[2] = locs.width;
            cmdParameters[3] = locs.height;
            cmdParameters[4] = locs.weight;
            cmdParameters[5] = operId;
            return CustOper(610)>0;
        }
        public bool updateLocationStatus(string IDS, int status, int operId)
        {
            cmdParameters[0] = IDS;
            cmdParameters[1] = status;
            cmdParameters[2] = operId;
            return CustOper(620) > 0;
        }
        public bool updateLocationTranLines(string IDS, Structs locs, int operId)
        {
            cmdParameters[0] = IDS;  
            cmdParameters[1] = locs.transLine;
            cmdParameters[2] = operId; 
            return CustOper(630) > 0;
        }
        public bool updateLocationABC(string IDS, Structs locs, int operId)
        {
            cmdParameters[0] = IDS;
            cmdParameters[1] = locs.ABC;
            cmdParameters[2] = operId;
            return CustOper(660) > 0;
        }
        public bool updateLocScale(string IDS, Structs locs, int operId)
        {
            cmdParameters[0] = IDS;
            cmdParameters[1] = locs.scale;
            cmdParameters[2] = operId;
            return CustOper(710) > 0;
        }
        public bool updateLocationLabelId(string IDs, Structs locs, int operId)
        {
            cmdParameters[0] = IDs;
            cmdParameters[1] = locs.elabId;
            cmdParameters[2] = locs.elabAddress;
            cmdParameters[3] = operId;
            return CustOper(640) > 0; 
        }
        public int deleteLocations(string IDs)
        {
            cmdParameters[0] = IDs;
            
            return CustOper(650) ; 
        }
        /// 
        /// query location percent data
        /// 
        /// 
        public DataTable getLocationsUsedPercent()
        { 
            return CustQuery(670).Tables[0];
        }
        public bool updateLocationOwner(string IDS, Structs locs, int operId)
        {
            cmdParameters[0] = IDS;
            cmdParameters[1] = locs.ownerCode;
            cmdParameters[2] = operId;
            return CustOper(680) > 0;
        }
        public bool updateLocationStoreType(string IDs, Structs locs, int operId)
        {
            cmdParameters[0] = IDs;
            cmdParameters[1] = locs.storeType;
            cmdParameters[2] = operId;
            return CustOper(690) > 0;
        }  
        
        public bool isFree(string locId)
        {
            cmdParameters[0] = locId;
            return CustQuery(700).Tables[0].Rows.Count==1;
        }
        public int locationEleIdCombine(int shelf, int channel, int eleId)
        {
            cmdParameters[0] =channel ;
            cmdParameters[1] = shelf;
            cmdParameters[2] = eleId;
            return CustOper(800) ;
        }
        public void formatLocName()
        {
            WmsLocation loc;
            DataTable dt = CustQuery(900).Tables[0];
            foreach (DataRow dr in dt.Rows)
            {
                loc = new WmsLocation(dr);
                if (loc.locationId.Length < 3)
                {
                    continue;
                }
                loc.locationId = string.Format("{0}.{1:D2}.{2:D2}.{3}{4}",
                loc.locationId.Substring(0, 3), loc.channel, loc.shelf, loc.layer, loc.col);
                loc.locationId128 = Util.getCode128(loc.locationId);
                loc.Update();
               // break;
            }
        }
        public WmsLocation getByPartion(int partion,int cnt)
        {
            cmdParameters[0] = partion;
            cmdParameters[1] = cnt;
            
            DataTable dt = CustQuery(1000).Tables[0];
            if(dt.Rows.Count > 0)
            {
                return new WmsLocation(dt.Rows[0]);
            }
            return new WmsLocation();
        }
    }
}