<?php
/**
 * Created by PhpStorm.
 * User: Gss
 * Date: 2021/5/17 0017
 * Time: 17:58
 */

namespace JinDouYun\Model\Stock;

use JinDouYun\Dao\Customer\DCustomer;
use JinDouYun\Dao\Stock\DPicking;
use JinDouYun\Dao\Stock\DPickingGoods;
use JinDouYun\Dao\Stock\DPickingIndex;
use JinDouYun\Model\Finance\MAccount;
use JinDouYun\Model\Order\MOrder;
use Mall\Framework\Core\StatusCode;
use Mall\Framework\Core\ErrorCode;
use Mall\Framework\Core\ResultWrapper;

use JinDouYun\Model\MBaseModel;

class MPicking extends MBaseModel
{
    /**
     * @var int 用户id
     */
    private $userCenterId;

    /**
     * @var int 企业id
     */
    private $onlineEnterpriseId;

    /**
     * @var int 单表数据量
     */
    private $cutTable = 200000;

    private $objDPicking;

    private $objDPickingGoods;

    private $objDPickingIndex;

    private $objMAccount;

    private $objDCustomer;

    /**
     * MOrder constructor.
     * @param $userCenterId
     * @param $onlineEnterpriseId
     * @param null $loginUserCenterId
     * @param bool $isFront
     * @throws \Exception
     */
    public function __construct($userCenterId, $onlineEnterpriseId, $loginUserCenterId = null, $isFront = false, $isCashier = false)
    {
        $this->isCashier = $isCashier;
        $this->isFront = $isFront;
        $this->userCenterId = $userCenterId;
        $this->onlineEnterpriseId = $onlineEnterpriseId;
        $this->loginUserCenterId = $loginUserCenterId;
        parent::__construct($this->onlineEnterpriseId, $loginUserCenterId);

        $this->objDPicking = new DPicking('stock');
        self::pickingSubTable($onlineEnterpriseId, $userCenterId);
        $this->objMAccount = new MAccount($onlineEnterpriseId, $userCenterId);

        $this->objDCustomer = new DCustomer();
        $this->objDCustomer->setTable('qianniao_customer_' . $this->onlineEnterpriseId);

        $this->objDPickingGoods = new DPickingGoods();
        self::pickingGoodsSubTable($onlineEnterpriseId, $userCenterId);
        $this->objDPickingIndex = new DPickingIndex();
        $this->objDPickingIndex->setTable('qianniao_picking_index_'.$this->onlineEnterpriseId);
    }

    /**
     * 拣货单分表 分表规则:企业id_(客户/200000)
     * @param $enterpriseId (企业id)
     * @param $userId (用户id)
     * @throws \Exception
     */
    public function pickingSubTable($enterpriseId, $userId)
    {
        $tableName = $this->objDPicking->getTableName('qianniao_picking_' . $enterpriseId, $userId, $this->cutTable);
        $this->objDPicking->setTable($tableName);
    }

    /**
     * 拣货单分表 分表规则:企业id_(客户/200000)
     * @param $enterpriseId (企业id)
     * @param $userId (用户id)
     * @throws \Exception
     */
    public function pickingGoodsSubTable($enterpriseId, $userId)
    {
        $tableName = $this->objDPickingGoods->getTableName('qianniao_picking_goods_' . $enterpriseId, $userId, $this->cutTable);
        $this->objDPickingGoods->setTable($tableName);
    }

    /**
     * 获取拣货单表名
     */
    public function getPickingTable($enterpriseId, $userId){
        return $this->objDPicking->getTableName('qianniao_picking_' . $enterpriseId, $userId, $this->cutTable);
    }

    /* *************************************************************************************************************** */


    /**
     * 新增拣货单
     */
    public function addPicking($params)
    {
        $goodsDate = $params['goodsData'];
        unset($params['goodsData']);

        // 生成拣货单编号
        $dbResult =  $this->objDPicking->get('createTime >='.strtotime(date('Ymd'.'0:0:0')), 'no', 'createTime desc');
        if ($dbResult === false) {
            return ResultWrapper::fail($this->objDPicking->error(), ErrorCode::$dberror);
        }
        if(empty($dbResult)){
            $params['no'] = createSerialNumberByDate('');
        }else{
            $params['no'] = createSerialNumberByDate($dbResult['no']);
        }
        unset($dbResult);

        //订单no 切割
        if( isset($params['originNo']) && !empty($params['originNo']) ){
            $params['originNo'] = explode('-',$params['originNo']);
            if(count($params['originNo']) == 3){
                $params['originNo'] = $params['originNo'][1].'-'.$params['originNo'][2];
            }
        }

        //开启事务
        $beginTransactionStatus = $this->objDPicking->beginTransaction();
        // 组装index数据
        $indexDate = [
            'no' => getArrayItem($params,'no',''),
            'shopId' => getArrayItem($params,'shopId',0),
            'shopName' => getArrayItem($params,'shopName',''),
            'merchantId' => getArrayItem($params,'merchantId',0),
            'originId' => getArrayItem($params,'originId',0),
            'originNo' => getArrayItem($params,'originNo',''),
            'warehouseId' => getArrayItem($params,'warehouseId',0),
            'warehouseName' => getArrayItem($params,'warehouseName',''),
            'currentUnitId' => getArrayItem($params,'currentUnitId',0),
            'currentUnitName' => getArrayItem($params,'currentUnitName',''),
            'personnel' => getArrayItem($params,'personnel',0),
            'personnelName' => getArrayItem($params,'personnelName',''),
            'sort' => getArrayItem($params,'sort',0),
            'managerId' => getArrayItem($params,'managerId',0),
            'managerName' => getArrayItem($params,'managerName',''),
            'pickingStatus' => getArrayItem($params,'pickingStatus',4),
            'pickingType' => getArrayItem($params,'pickingType',4),
            'createTime' => getArrayItem($params,'createTime',''),
        ];
        $pickIndexId = $this->objDPickingIndex->insert($indexDate);
        if ($pickIndexId === false) {
            $this->objDPicking->rollBack();
            return ResultWrapper::fail($this->objDPickingIndex->error(), ErrorCode::$dberror);
        }
        $params['id'] = $pickIndexId;
        $pickId = $this->objDPicking->insert($params);
        if ($pickId === false) {
            $this->objDPicking->rollBack();
            return ResultWrapper::fail($this->objDPicking->error(), ErrorCode::$dberror);
        }


        // 插入拣货单id、no
        foreach ($goodsDate as $key => $value){
            $goodsDate[$key]['pickingId'] = $pickIndexId;
            // 拣货单编号
            $goodsDate[$key]['no'] = getArrayItem($params,'no','');
        }
        $pickingGoodsId = $this->objDPickingGoods->insert($goodsDate,true);
        if ($pickingGoodsId === false) {
            $this->objDPicking->rollBack();
            return ResultWrapper::fail($this->objDPickingGoods->error(), ErrorCode::$dberror);
        }

        //生成完后同步更新订单的拣货状态为拣货中
        $objMOrder = new MOrder($this->userCenterId, $this->onlineEnterpriseId);
        $orderIds = explode(',',$params['originId']);
        //修改订单拣货状态
        $result = $objMOrder->updateOrderPicking($orderIds,StatusCode::$orderPickStatus['picking']);
        if(!$result->isSuccess()){
            return ResultWrapper::fail($result->getData(),$result->getErrorCode());
        }
        if($beginTransactionStatus){
            $this->objDPicking->commit();
        }

        return ResultWrapper::success($pickIndexId);
    }

    /**
     * 拣货单详情
     */
    public function getPickingInfo($pickingId)
    {
        $dbResult = $this->objDPicking->get($pickingId);
        if ($dbResult === false) {
            return ResultWrapper::fail($this->objDPicking->error(), ErrorCode::$dberror);
        }

        $goodsDate = $this->objDPickingGoods->select(['pickingId'=>$pickingId]);
        if ($goodsDate === false) {
            return ResultWrapper::fail($this->objDPicking->error(), ErrorCode::$dberror);
        }
        foreach ($goodsDate as $key =>$value){
            if (empty($value['specGroup'])){
                $goodsDate[$key]['specGroup'] = json_decode($value['specGroup'],true);
            }
        }
        $dbResult['goodsDate'] = $goodsDate;
        return ResultWrapper::success($dbResult);

    }

    /**
     * @param $pickingDate
     * @param $goodsDate
     * @return mixed
     * 编辑拣货单
     */
    public function editPicking($params)
    {
        $goodsDate = $params['goodsDate'];
        unset($params['goodsDate']);

        // 重新计算编辑后的数量
        $number = 0;
        $notPickingNum = 0;
        $totalMoney = 0;
        $notOutNum = 0;
        //循环获取商品数量，销售金额
        foreach ($goodsDate as $key =>$value ){
            $params['number'] = bcadd($number,$value['orderNum']);
            $params['notPickingNum'] = bcadd($notPickingNum,$value['orderNum']);
            $params['totalMoney'] = bcadd($totalMoney,$value['totalMoney']);
            $params['notOutNum'] = bcadd($notOutNum,$value['orderNum']);
        }
        //商品行数
        $params['goodsLine'] = count($goodsDate);

        // 拣货单id
        $pickingId = $params['id'];
        unset($params['id']);
        unset($params['no']);
        unset($params['originNo']);

        $params['updateTime'] = time();
        $beginTransactionstatus = $this->objDPicking->beginTransaction();
        $dbResult = $this->objDPicking->update($params, $pickingId);
        if ($dbResult === false) {
            $this->objDPicking->rollBack();
            return ResultWrapper::fail($this->objDPicking->error(), ErrorCode::$dberror);
        }
        unset($dbResult);
        //index数据
        $indexDate = [
            'personnel' => getArrayItem($params,'personnel',0),
            'personnelName' => getArrayItem($params,'personnelName',''),
            'sort' => getArrayItem($params,'sort',0),
            'managerId' => getArrayItem($params,'managerId',0),
            'managerName' => getArrayItem($params,'managerName',''),
            'pickingStatus' => getArrayItem($params,'pickingStatus',4),
            'pickingType' => getArrayItem($params,'pickingType',4),
            'updateTime' => getArrayItem($params,'updateTime',''),
        ];
        $dbResult = $this->objDPickingIndex->update($indexDate, $pickingId);
        if ($dbResult === false) {
            $this->objDPicking->rollBack();
            return ResultWrapper::fail($this->objDPickingIndex->error(), ErrorCode::$dberror);
        }
        unset($dbResult);
        // 拣货商品数据
        foreach ($goodsDate as $key => $value){
            $goodsId = getArrayItem($value, 'id', 0);
            //判断拣货状态 根据应拣数量和本次拣货数量判断
            if($value['pickingedNum'] <=0){
                return ResultWrapper::fail('本次件货数量不能为0',ErrorCode::$notAllowAccess);
            }
//            if($value['pickingedNum'] == $value['pickingNum']){ // 说明全部拣货
//                $value['pickingStatus'] = StatusCode::$standard;
//            }else{
//                $value['pickingStatus'] = StatusCode::$partion;
//            }
            unset($value['no']);
            $value['updateTime'] = time();
            $dbResult = $this->objDPickingGoods->update($value, $goodsId);
            if ($dbResult === false) {
                $this->objDPicking->rollBack();
                return ResultWrapper::fail($this->objDPickingGoods->error(), ErrorCode::$dberror);
            }
        }
        if($beginTransactionstatus){
            $this->objDPicking->commit();
        }
        return ResultWrapper::success($pickingId);
    }

    /**
     * 完成拣货
     */
    public function updatePicking($params)
    {
        $dbResult = $this->objDPicking->get($params['id']);
        if ($dbResult === false) {
            return ResultWrapper::fail($this->objDPicking->error(), ErrorCode::$dberror);
        }

        $beginTransactionstatus = $this->objDPicking->beginTransaction();
        //更新拣货状态
        $updateResult = $this->objDPicking->update(['pickingStatus'=>StatusCode::$standard,'updateTime'=>time()],['id'=>$params['id']]);
        if ($updateResult === false) {
            $this->objDPicking->rollBack();
            return ResultWrapper::fail($this->objDPicking->error(), ErrorCode::$dberror);
        }

        if($beginTransactionstatus){
            $this->objDPicking->commit();
        }
        return ResultWrapper::success($updateResult);
    }


    /**
     * 拣货单列表
     */
    public function getAllPicking($selectParams)
    {
        $limit = $selectParams['limit'];
        unset($selectParams['limit']);
        $offset = $selectParams['offset'];
        unset($selectParams['offset']);
        //组装sql where条件
        $whereSql = '';
        if (isset($selectParams['no']) && !empty($selectParams['no'])) {
            $where = empty($whereSql) ? ' WHERE ' : ' AND ';
            $whereSql .= $where . ' no like "%' . $selectParams['no'] . '%"';
        }
        if (isset($selectParams['warehouseId']) && !empty($selectParams['warehouseId'])) {
            $where = empty($whereSql) ? ' WHERE ' : ' AND ';
            $whereSql .= $where . ' warehouseId = ' . $selectParams['warehouseId'];
        }
        if (isset($selectParams['personnel']) && !empty($selectParams['personnel'])) {
            $where = empty($whereSql) ? ' WHERE ' : ' AND ';
            $whereSql .= $where . ' personnel = ' . $selectParams['personnel'];
        }
        if (isset($selectParams['originId']) && !empty($selectParams['originId'])) {
            $where = empty($whereSql) ? ' WHERE ' : ' AND ';
            $whereSql .= $where . ' originId = ' . $selectParams['originId'];
        }
        if (isset($selectParams['originNo']) && !empty($selectParams['originNo'])) {
            $where = empty($whereSql) ? ' WHERE ' : ' AND ';
            $whereSql .= $where . ' originNo like "%' . $selectParams['originNo'] . '%"';
        }
        if (isset($selectParams['currentUnitId']) && !empty($selectParams['currentUnitId'])) {
            $where = empty($whereSql) ? ' WHERE ' : ' AND ';
            $whereSql .= $where . ' currentUnitId = ' . $selectParams['currentUnitId'];
        }
        if (isset($selectParams['managerId']) && !empty($selectParams['managerId'])) {
            $where = empty($whereSql) ? ' WHERE ' : ' AND ';
            $whereSql .= $where . ' managerId = ' . $selectParams['managerId'];
        }
        //时间删选  有timeName字段优先
        if( isset($selectParams['timeName']) && !empty($selectParams['timeName']) ){
            $timeName = $selectParams['timeName'];
            $timestamp = gettimestamp($timeName,time());
            $where = empty($whereSql) ? ' WHERE ' : '  AND ';
            $whereSql .= $where . ' createTime BETWEEN ' . $timestamp['start'] . ' AND '. $timestamp['end'];
        }else{
            if ( (isset($selectParams['start']) && !empty($selectParams['start']))&&(isset($selectParams['end']) && !empty($selectParams['end'])) ) {
                $where = empty($whereSql) ? ' WHERE ' : '  AND ';
                $whereSql .= $where . ' createTime BETWEEN ' . $selectParams['start'] . ' AND '. $selectParams['end'];
            }
        }
        $sql = 'select * from '.$this->objDPickingIndex->get_Table().$whereSql . ' ORDER BY createTime DESC LIMIT ' . $offset . ' , ' . $limit;
        $pickIndexDbResult = $this->objDPickingIndex->query($sql);
        $pickDbResult = [];
        foreach ($pickIndexDbResult as $key => $value){
            $dbResult = $this->objDPicking->select(['id'=>$value['id']], '*', 'createTime desc');
            if ($dbResult === false) {
                return ResultWrapper::fail($this->objDPicking->error(), ErrorCode::$dberror);
            }
            $pickDbResult = array_merge($pickDbResult, $dbResult);
        }
        // 渲染编号
        foreach ($pickDbResult as $k => $v){
            $pickDbResult[$k]['originNo'] = StatusCode::$noPrefix[1].'-'.$v['originNo'];
            $pickDbResult[$k]['no'] = StatusCode::$noPrefix[31].'-'.$v['no'];
        }

        $totalSql = 'SELECT COUNT(1) as count FROM '.$this->objDPickingIndex->get_Table().$whereSql;
        $dbTotalResult = $this->objDPickingIndex->query($totalSql);
        if ($dbTotalResult === false) {
            return ResultWrapper::fail($this->objDPickingIndex->error(), ErrorCode::$dberror);
        }
        if(empty($dbTotalResult)){
            return ResultWrapper::success([]);
        }
        $return = [
            'data'  => $pickDbResult,
            'total' => $dbTotalResult[0]['count']
        ];
        return ResultWrapper::success($return);
    }

    /**
     * 拣货明细（根据商品维度进行统计）
     */
    public function getAllPickingGoodsDetail($selectParams)
    {
//        $timeName = $selectParams['today'];
        $time = gettimestamp('preday',time());

        $limit = $selectParams['limit'];
        unset($selectParams['limit']);
        $offset = $selectParams['offset'];
        unset($selectParams['offset']);

        //组装sql where条件
        $whereSql = '';
        if (isset($selectParams['no']) && !empty($selectParams['no'])) {
            $where = empty($whereSql) ? ' WHERE ' : ' AND ';
            $whereSql .= $where . ' p.no like "%' . $selectParams['no'] . '%"';
        }
        if (isset($selectParams['warehouseId']) && !empty($selectParams['warehouseId'])) {
            $where = empty($whereSql) ? ' WHERE ' : ' AND ';
            $whereSql .= $where . ' p.warehouseId = ' . $selectParams['warehouseId'];
        }
        if (isset($selectParams['personnel']) && !empty($selectParams['personnel'])) {
            $where = empty($whereSql) ? ' WHERE ' : ' AND ';
            $whereSql .= $where . ' p.personnel = ' . $selectParams['personnel'];
        }
        if (isset($selectParams['goodsName']) && !empty($selectParams['goodsName'])) {
            $where = empty($whereSql) ? ' WHERE ' : ' AND ';
            $whereSql .= $where . ' g.goodsName = ' . $selectParams['goodsName'];
        }
        if (isset($selectParams['originId']) && !empty($selectParams['originId'])) {
            $where = empty($whereSql) ? ' WHERE ' : ' AND ';
            $whereSql .= $where . ' g.originId = ' . $selectParams['originId'];
        }
        if (isset($selectParams['originNo']) && !empty($selectParams['originNo'])) {
            $where = empty($whereSql) ? ' WHERE ' : ' AND ';
            $whereSql .= $where . ' p.originNo like "%' . $selectParams['originNo'] . '%"';
        }
        if (isset($selectParams['currentUnitId']) && !empty($selectParams['currentUnitId'])) {
            $where = empty($whereSql) ? ' WHERE ' : ' AND ';
            $whereSql .= $where . ' p.currentUnitId = ' . $selectParams['currentUnitId'];
        }
        if (isset($selectParams['managerId']) && !empty($selectParams['managerId'])) {
            $where = empty($whereSql) ? ' WHERE ' : ' AND ';
            $whereSql .= $where . ' p.managerId = ' . $selectParams['managerId'];
        }
        if (isset($selectParams['pickingStatus']) && !empty($selectParams['pickingStatus'])) {
            $where = empty($whereSql) ? ' WHERE ' : ' AND ';
            $whereSql .= $where . ' p.pickingStatus = ' . $selectParams['pickingStatus'];
        }
        //时间删选  有timeName字段优先
        if( isset($selectParams['timeName']) && !empty($selectParams['timeName']) ){
            $timeName = $selectParams['timeName'];
            $timestamp = gettimestamp($timeName,time());
            $where = empty($whereSql) ? ' WHERE ' : '  AND ';
            $whereSql .= $where . ' p.createTime BETWEEN ' . $timestamp['start'] . ' AND '. $timestamp['end'];
        }else{
            if ( (isset($selectParams['start']) && !empty($selectParams['start']))&&(isset($selectParams['end']) && !empty($selectParams['end'])) ) {
                $where = empty($whereSql) ? ' WHERE ' : '  AND ';
                $whereSql .= $where . ' p.createTime BETWEEN ' . $selectParams['start'] . ' AND '. $selectParams['end'];
            }
        }
        $sql = 'select p.createTime,p.pickingStatus,p.no,p.currentUnitId,p.currentUnit,p.personnel,p.personnelName,p.managerId,p.managerName,g.* from '.$this->objDPicking->get_Table().' as p left join '.$this->objDPickingGoods->get_Table().' as g on p.id = g.pickingId'.$whereSql.' LIMIT '. $offset . ' , ' . $limit;

        $dbResult = $this->objDPicking->query($sql);
        if ($dbResult === false) {
            return ResultWrapper::fail($this->objDPicking->error(), ErrorCode::$dberror);
        }

        //渲染编号
        foreach ($dbResult as $k => $v){
            $dbResult[$k]['no'] = StatusCode::$noPrefix[31].'-'.$v['no'];
        }

        $totalSql = 'select COUNT(1) AS count from '.$this->objDPicking->get_Table().' as p left join '.$this->objDPickingGoods->get_Table().' as g on p.id = g.pickingId'.$whereSql;
        $dbTotalResult = $this->objDPickingIndex->query($totalSql);
        if ($dbTotalResult === false) {
            return ResultWrapper::fail($this->objDPickingIndex->error(), ErrorCode::$dberror);
        }
        if(empty($dbTotalResult)){
            return ResultWrapper::success([]);
        }
        $return = [
            'data'  => $dbResult,
            'total' => $dbTotalResult[0]['count']
        ];
        return ResultWrapper::success($return);
    }




}