/// 
///LOGIC CLASS FOR TABLE t_wmsStockPandian
///By wm with codesmith. 
///on 07/27/2018
/// 
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;
namespace DeiNiu.wms.Logical
{
    [Serializable]
    public class lWmsStockPandian   :lbase
    {
       
        public lWmsStockPandian()
        {
             initialize();
        }
        WmsStockPandian _obj;
        public  WmsStockPandian getWmsStockPandian
        {
            get
            {
                if (_obj == null)
                {
                    _obj = new WmsStockPandian();
                   
                }
               _obj.operater = operId;
                return _obj;
            }
        }
        WmsStockPandianResult _pandianItem;
        public WmsStockPandianResult getWmsStockPandianResult
        {
            get
            {
                if (_pandianItem == null)
                {
                    _pandianItem = new WmsStockPandianResult();
                }
                _pandianItem.operater = operId;
                return _pandianItem;
            }
        }
        
       public lWmsStockPandian(int operId)
            : base(operId)
        {
            initialize();
        }
        
  
		/// 
		/// get all data
		/// 
        public DataSet getAllData()
        {
           return _obj.Query();
        }
        /// 
        /// get all data
        /// 
        public DataSet getAllActiveData()
        {
            return _obj.QueryActived();
        }
		/// 
		/// get a record by id
		/// 
        public void initialize(int id)
		{
            _obj = id != 0 ? new WmsStockPandian(id) : new WmsStockPandian();
            _obj.operater = operId; 
		}
        /// 
		/// get a record by id 0
		/// 
        public void initialize()
        {
            initialize(0);
        }
         /// 
        /// get a record by id
        /// 
        public void initialize(DataRow dr)
        {
            _obj =   new WmsStockPandian(dr);
            _obj.operater = operId; 
        }
        
        protected override DeiNiu.Data.BaseObject.BaseModel getModel()
        {
            return _obj;
        }
 
        //begin cust db operation, query, excute sql etc.
        
     
        /// 
        /// 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;
        }
        public string createPanOrder(int panType, bool noticeErp, int createBy,string inputValues, string stockCondition)
        {
            WmsStockPandian pandian = new WmsStockPandian(); 
            pandian.orderNo = Utils.Util.getOrderNo(Utils.enumCreateOrderType.pandianOrder,pandian.getNextSeq(enumCreateOrderType.pandianOrder));
            pandian.condition = stockCondition;
            pandian.createby = createBy;
            pandian.operater = operId;
            pandian.type = panType;
            pandian.inputValus =  inputValues;
            pandian.noticeErp = noticeErp;
            pandian.status = 0;
            pandian.Add();
            return pandian.orderNo;
        }
       public bool canStartNewPandian()
        {
            return getWmsStockPandian.canStartNewPandian();
        }
        public bool startPandian(string orderNo)
        {
            WmsStockPandian pandian = new WmsStockPandian(orderNo);
            if (pandian.ID == 0 ||  pandian.status !=(int) enumPandianStatus.未开始 || !canStartNewPandian() )
            { 
           
                return false;
            }
            pandian.clean();
           using (TransactionScope scope = new TransactionScope())
           {
                pandian.status = (int)enumPandianStatus.开始采集;
                string sqlWhere =pandian.getCondition(pandian.condition);
                sqlWhere += pandian.getPlusCondition();  
                
                logPandian.Debug(" condition: " + sqlWhere);
              int cnt=  pandian.createDetailMirror(sqlWhere);
                
             
                pandian.updateStockStatus(enumStockLocationStatus.盘点锁定, sqlWhere);
               pandian.startTime = pandian.getDateTime();
               pandian.Update();
                WmsFlow wmsflow = new WmsFlow();
                wmsflow.operater = operId;
                wmsflow.orderNo = pandian.orderNo;
                wmsflow.flowNo = pandian.orderNo;
                wmsflow.type = (int)EnumFlowTaskType.盘点采集;
                wmsflow.typeName = EnumFlowTaskType.盘点采集.ToString();
                wmsflow.task = pandian.orderNo; // Util.getOrderNo(enumCreateOrderType.pickJobNo, _obj.getNextSeq(enumCreateOrderType.pickJobNo));  
                wmsflow.taskCnt = cnt; 
                wmsflow.Add(); 
                scope.Complete();
           }
            WmsConstants.CURRENT_PANDIAN_ORDER = orderNo;
         return true;
        }
        public bool delPandian(string orderNo)
        {
            WmsStockPandian pandian = new WmsStockPandian(orderNo);
            if (pandian.ID > 0 && pandian.status == (int)enumPandianStatus.未开始)
            {
            }
            else
            {
                return false;
            }
            return pandian.Delete() >0;
        }
        public bool finishPandian(string orderNo)
        {
            log.Debug("to stop pandian " + orderNo);
            WmsConstants.CURRENT_PANDIAN_ORDER = "";
            WmsStockPandian pandian = new WmsStockPandian(orderNo);
            pandian.operater = operId;
            pandian.status = (int)enumPandianStatus.盘点结束;
            pandian.endTime = pandian.getDateTime();
            bool ret = true;
            using (TransactionScope scope = new TransactionScope())
            {
                ret = pandian.Update() > 0;
                ret = ret && pandian.finishPandian(orderNo, pandian.getCondition(pandian.condition));
                if (WmsConstants.ERP_NOTICE_STOCK_IN && pandian.noticeErp)
                {  
                    WmsOrderRequest wor = pandian.createErpOrder();
                    new lWmsOutPickRequest(operId).noticeErpOrder(wor);
                }
                else
                {
                    log.Debug("------------------------- not to notice erp pandian result.");
                }
                WmsFlow flow = new WmsFlow(pandian.orderNo);
                flow.finishedCnt = flow.taskCnt;
                flow.state = (int)enumFlowTaskStatus.已完成; 
                flow.Update();
                scope.Complete();
            }
            WmsConstants.CURRENT_PANDIAN_ORDER = "";
            log.Debug(" completed pandian " + orderNo);
            return ret;
        }
        internal bool adjustPandianStock(string orderNo, bool isRollBack)
        {
            WmsStockPandianAdjust wpa;
            WmsStock wstk;
            decimal factor = isRollBack ? 1  : -1 ;
            DataTable dt = getWmsStockPandian.getPandianBanlanceDetail(orderNo);
            WmsStockPandian wsp = new WmsStockPandian(orderNo);
            wsp.adjustStatus =isRollBack ?(int)enumPandianAdjustStatus.未校正 : (int)enumPandianAdjustStatus.已校正;
            wsp.operater = operId;
            DataView dv = dt.DefaultView;
            dv.Sort = "data " + (isRollBack ? "desc" : "asc");
            using (TransactionScope scope = new TransactionScope())
            {
                wsp.Update(); 
                lWmsStock lstk = new lWmsStock(operId);
                if (wsp.type == (int)enumPandianType.全仓盘点)
                {
                    // delete pandian stk
                    lstk.cleanPandiane();
                    lstk.deleteLocByType(enumWhLocVol.盘点);
                    lstk.deleteLocByType(enumWhLocVol.虚拟);
                   
                    lstk.deleteLocBySkuId(0);
                }
                if (isRollBack)
                {
                    getWmsStockPandian.deleteAdjust(orderNo);
                }
              
              
                foreach (DataRowView dr in dv)
                {
                    WmsStockRecord r = new WmsStockRecord();
                     
                    wpa = new WmsStockPandianAdjust(dr.Row);
                    wpa.operater = operId;
                    
                    r.count = wpa.count;
                    //删除旧库存记录 
                    wstk = new WmsStock( wpa.locationId,wpa.skuId,wpa.goodsId);
                    decimal oldCount = wstk.count - wstk.countOut;
                    wstk.Delete();
                    wstk = new WmsStock(dr.Row);
                    wstk.operater = operId;
                    logPandian.Debug(string.Format("isRollback? {0}, wpa.data {1}", isRollBack, wpa.data));
                    decimal adjustCnt = wstk.count - oldCount;
                    if (!isRollBack)
                    {
                        r.description = "盘点调整";
                        wpa.Add(); 
                        if (wpa.data == 0) //mirror
                        {
                            
                            r.count = r.count * -1; //减库存
                        }
                        else
                        { 
                           
                            wstk.Add();
                            if (wsp.type != (int)enumPandianType.全仓盘点)
                            {
                                lstk.logPandianStock(wpa.skuId, r.goodsId, adjustCnt);
                            }
                         
                            logPandian.Debug("applied pandian result..." + wstk);
                        }
                    }
                    else  //回退
                    {
                        r.description = "回退调整";
                        if (wpa.data == 1)//采集
                        { 
                            r.count = r.count * -1;//减库存
                            if (wsp.type != (int)enumPandianType.全仓盘点)
                            {
                                lstk.logPandianStock(wpa.skuId, r.goodsId, adjustCnt * -1);
                            }
                        }
                        else
                        { 
                            wstk.Add();
                            logPandian.Debug("rollback pandian result..." + wstk);
                        }
                    }
                    r.goodsId = wpa.goodsId.Trim();
                    r.locationId = wpa.locationId.Trim();
                    r.productDate = wpa.productDate;
                    r.validDate = wpa.validDate;
                    r.orderNo = wpa.orderNo.Trim();                
                    r.rectype = (int)enumStockRecordType.盘点调整;
                    r.operater = this.operId;
                    r.Add();
                }
                scope.Complete();
            }
            return true;
        }
        internal bool newPandianItem(string orderNo, string locationId, int mirrroId, string goodsId, string prdDate, string batch, decimal count)
        {
            logPandian.Debug(string.Format(" new pandian item:  orderNo {0},locationId {1},mirrroId {2},goodsId {3},prdDate {4},batch{5},count {6}", orderNo, locationId, mirrroId, goodsId, prdDate, batch, count));
            WmsStockPandian wsp = null;
            if (string.IsNullOrEmpty(orderNo))
            {
              wsp=  getWmsStockPandian.getCurrentPandianOrder();
            }else
             wsp = new WmsStockPandian(orderNo);
            if(wsp.status != (int)enumPandianStatus.开始采集)
            {
                return false;
            }
            int skuId = 0;
            string skuCode = "";
            WmsStockPandianResult wr;
            string dtValid = prdDate;
            WmsGoods wg = new WmsGoods(goodsId);
            if (wg.ID ==0)
            {
               throw new Exception("未知商品");
            }
          //  DateTime dtprd = Util.pareseDateString(prdDate);
            dtValid = (getValidDate(prdDate, wg.goodsId)).ToShortDateString();
            /*
            Dictionary skuValues = new Dictionary();
            skuValues[WmsConstants.SKU_RESEVRED_BATCH_ATTNAME] = batch;
            skuValues[WmsConstants.SKU_RESEVRED_EXPIREDATE_ATTNAME] = dtValid;
            skuValues[WmsConstants.SKU_RESEVRED_PRDDATE_ATTNAME] = dtprd.ToShortDateString();
            */
            Dictionary dic = new lLot().getSKU(prdDate, wg.goodsId,batch);
            foreach (int i in dic.Keys)
            {
                skuId = i;
                skuCode=dic[i];
                break;
            }
            wr = new WmsStockPandianResult(orderNo, locationId, skuId,wg.goodsId);
            logPandian.Debug(" to add new pandian item: " + wr);
            wr.goodsId = wg.goodsId;
            wr.validDate = dtValid;
            wr.batch = batch;
           // wr.mirrorId = mirrroId;
            wr.productDate = prdDate;
            wr.orderNo = orderNo;
            wr.locationId = locationId.ToUpper();
            wr.skuId = skuId;
            wr.skuCode = skuCode;
            if (wg.isWeightOut() && WmsConstants. PANDIAN_WEIGHT_SUM)  //称重的商品累加重量,一个商品可能多次称重
            {
                wr.avCount += count;
            }
            else
            {
                wr.avCount = count;
            }
            wr.operater = operId;
            int cnt = 0;
            using (TransactionScope scope = new TransactionScope())
            {
                if (wr.ID > 0)
                {
                    cnt = wr.Update();
                }
                else
                {
                    WmsStockPandianStockMirror sm = new WmsStockPandianStockMirror();
                    sm.skuId = wr.skuId;
                    sm.batch = wr.batch;
                    sm.goodsId = wr.goodsId;
                    sm.locationId = wr.locationId;
                    sm.orderNo = wr.orderNo;
                    sm.productDate = wr.productDate;
                    sm.validDate = wr.validDate;
                    sm.skuCode = wr.skuCode;
                    // sm.shelfCount = wr.avCount;
                    wr.mirrorId = sm.Add();
                    cnt = wr.Add();
                }
                flowTaskCount(wr.orderNo, wr.goodsId, count);
                scope.Complete();
            }
            logPandian.Debug(" done... new pandian result: " + wr  +" , success? " +(cnt > 0));
            return cnt > 0;
        }
        internal bool stopPandianPick(string orderNo)
        {
            WmsStockPandian pandian = new WmsStockPandian(orderNo);
            pandian.operater = operId;
            pandian.status = (int)enumPandianStatus.采集结束;  
            return pandian.Update() > 0;
        }
        internal DataTable getPandianResultItem(string orderNo, string locationId)
        { 
            return getWmsStockPandianResult.getPandianItem(orderNo,locationId);
        }
        internal int postPandianItem(int mirrorId, decimal count)
        {
            logPandian.Debug("post item mirrorId  "+ mirrorId + ",  count " + count);
            WmsStockPandianStockMirror wps = new WmsStockPandianStockMirror(mirrorId);
            WmsStockPandian wsp = new WmsStockPandian(wps.orderNo);
            if (wsp.status != (int)enumPandianStatus.开始采集 && wsp.status != (int)enumPandianStatus.采集结束)
            {
                logPandian.Debug("pandian status " + wsp.status);
                return 0;
            }
            WmsFlow flow = new WmsFlow(wps.orderNo);
            
            WmsStockPandianResult wr = new WmsStockPandianResult(wps.orderNo, wps.locationId, wps.skuId,wps.goodsId);
            using (TransactionScope scope = new TransactionScope())
            {
                flow.finishedCnt++;
                flow.Update();
                flowTaskCount(wps.orderNo,wps.goodsId, count);
                logPandian.Debug(" result item exists ? " +( wr.ID>0));
               
                wr.avCount = count;
                if (wr.ID == 0)
                {
                    wr.batch = wps.batch;
                    wr.goodsId = wps.goodsId;
                    wr.productDate = wps.productDate;
                    wr.validDate = wps.validDate;
                    wr.skuCode = wps.skuCode;
                    wr.skuId = wps.skuId;
                    wr.locationId = wps.locationId;
                    wr.orderNo = wps.orderNo;
                    wr.operater = operId;
                    wr.mirrorId = mirrorId;
                    wr.Add();
                }
                else
                {
                    wr.Update();
                }
                scope.Complete();
            }
             
            return 100;
        }
        internal DataTable getPandianTargetItem(string orderNo, string locationId)
        {
            WmsStockPandian wsp = new WmsStockPandian(orderNo);
            if (wsp.status != (int)enumPandianStatus.开始采集)
            {
                return new DataTable("Noitem");
            }
            return getWmsStockPandian.getPandianTargetItem(orderNo, locationId);
        }
        internal DataTable getPandianTargetItems(string orderNo )
        {
            return getWmsStockPandian.getPandianTargetItems(orderNo );
        }
        public DataTable getPandianTasksByLoc(string locationId)
        {
            WmsLocation loc = new WmsLocation(locationId);
            if (loc.ID == 0)
            {
                return new DataTable("noItems");
            }
            _obj = getWmsStockPandian.getCurrentPandianOrder();
            if(_obj.ID == 0)
            {
                return new DataTable("noItems");
            }
            enumPandianStatus status = (enumPandianStatus)_obj.status;
            DataTable dt = new DataTable("noItems");
            if(_obj.adjustStatus == (int)enumPandianAdjustStatus.已校正)
            {
                return dt;
            }
            if (status == enumPandianStatus.开始采集)
            {
                dt = getWmsStockPandian.getPandianTasksByLoc(loc.part, loc.channel, loc.shelf);
            }else if(status == enumPandianStatus.采集结束)
            {
                dt = getWmsStockPandian.getPandianRunningDiff(loc.part);
            }
            else
            {
                return dt;
            }
             
            if (!WmsConstants.PANDIAN_SHOW_CNT)
            {
                dt.Columns.Remove("avCount");
            }
            return dt;
        }
        void flowTaskCount(string panOrder,string goodsId,decimal count)
        {
            try
            {
                string task = EnumFlowTaskType.盘点采集 + operId + Utils.Util.getShortDateString(getWmsStockPandian.getDateTime());// this.wmsStock.getDateTime
                WmsFlow wmsFlow = new WmsFlow(task);
                if (wmsFlow.ID == 0)
                {
                    wmsFlow.type = (int)EnumFlowTaskType.盘点采集;   // ;  (int)EnumFlowTaskType.日常理货;
                    wmsFlow.typeName = EnumFlowTaskType.盘点采集.ToString();
                    wmsFlow.task = task;
                    wmsFlow.orderNo = panOrder;
                    wmsFlow.state = (int)enumFlowTaskStatus.进行中;
                    wmsFlow.Add();
                }
                wmsFlow.finishedTasksPlus(operId, count / new WmsGoods(goodsId).minOperateCount, true);
            }
            catch (Exception er)
            {
                log.Error(er);
            }
         
        }
   
   
        //---test pandian
        public void testPandian()
        {
            logTest.Debug("start pandian process test...");
            //create order
            int type =new Random().Next(0,3);
            string orderNo =   createPanOrder(type, true, 282, "whType = #0;state = #0;", "");
            logTest.Debug(" created pandian order " + orderNo);
     
            logTest.Debug("start pandian pick....." + startPandian(orderNo));
            DataTable dt= getPandianTargetItems(orderNo);
            foreach(DataRow dr in dt.Rows)
            {
                WmsStockPandianStockMirror wps = new WmsStockPandianStockMirror(dr);
                postPandianItem(wps.ID, wps.shelfCount);
                //newPandianItem(orderNo,wps.locationId,wps.ID,)
                 
            }
             
            logTest.Debug("stopped  pandian pick " + stopPandianPick(orderNo)); 
            logTest.Debug("adjusted  pandian  result  " + adjustPandianStock(orderNo, false));
            logTest.Debug("finish  pandian    " + finishPandian(orderNo ));
          
        }
    }
    
    
}