<?php
/**
 * 报损管理Model
 * Created by PhpStorm.
 * User: haoren
 * Date: 2021/03/09
 * Time: 12:00
 */

namespace JinDouYun\Model\Stock;

use Exception;
use JinDouYun\Model\MBaseModel;
use Mall\Framework\Core\ErrorCode;
use Mall\Framework\Core\StatusCode;
use Mall\Framework\Core\ResultWrapper;

use JinDouYun\Dao\Stock\DReportLoss;
use JinDouYun\Dao\Stock\DReportLossDetails;

use JinDouYun\Model\Stock\MInventory;
use JinDouYun\Model\Stock\MInventoryOut;

class MReportLoss extends MBaseModel
{
    private $objDReportLossDetails;
    private $objDReportLoss;
    private $userCenterId;
    private $enterpriseId;

    public function __construct($enterpriseId, $userCenterId = false)
    {
        $this->enterpriseId = $enterpriseId;
        $this->userCenterId = $userCenterId;
        $this->objDReportLoss = new DReportLoss('stock');
        $this->objDReportLossDetails = new DReportLossDetails('stock');
        $this->objDReportLoss->setTable('qianniao_report_loss_' . $enterpriseId);
        $this->objDReportLossDetails->setTable('qianniao_report_loss_details_' . $enterpriseId);
    }

    /**
     * 库存报损添加
     * @param $params
     * @return ResultWrapper
     * @throws Exception
     */
    public function addReportLoss($params)
    {
        $details = $params['details'];
        unset($params['details']);
        unset($params['deleteArray']);
//        $params['no'] = createOrderSn(StatusCode::$source['manage'], StatusCode::$orderType['allocate'], $this->enterpriseId);
        // 生成编号
        $dbResult =  $this->objDReportLoss->get('createTime >='.strtotime(date('Ymd'.'0:0:0')), 'no', 'createTime desc');
        if ($dbResult === false) {
            return ResultWrapper::fail($this->objDReportLoss->error(), ErrorCode::$dberror);
        }
        if(empty($dbResult)){
            $params['no'] = createSerialNumberByDate('');
        }else{
            $params['no'] = createSerialNumberByDate($dbResult['no']);
        }
        $params['deleteStatus'] = StatusCode::$standard;
        $params['auditStatus'] = StatusCode::$auditStatus['auditing'];
        $params['auditId'] = 0;
        $params['auditName'] = '';
        $params['auditTime'] = 0;
        $params['createTime'] = time();
        $params['updateTime'] = time();
        //增加
        $beginStatus = $this->objDReportLoss->beginTransaction();
        $dbResult = $this->objDReportLoss->insert($params);
        if ($dbResult === false) {
            $this->objDReportLoss->rollBack();
            return ResultWrapper::fail($this->objDReportLoss->error(), ErrorCode::$dberror);
        }
        $returnData = $dbResult;
        unset($dbResult);

        foreach ($details as &$value) {
            $value['linkId'] = $returnData;
            $value['linkNo'] = $params['no'];
            $value['createTime'] = time();
            $value['updateTime'] = time();
        }
        unset($value);

        $dbResult = $this->objDReportLossDetails->insert($details, true);
        if ($dbResult === false) {
            $this->objDReportLoss->rollBack();
            return ResultWrapper::fail($this->objDReportLossDetails->error(), ErrorCode::$dberror);
        }

        $beginStatus && $this->objDReportLoss->commit();
        return ResultWrapper::success($returnData);
    }

    /**
     * 库存报损删除
     * @param $where
     * @return ResultWrapper
     */
    public function deleteReportLoss($where)
    {
        $params = [
            'deleteStatus' => StatusCode::$delete,
            'updateTime' => time(),
        ];
        $dbResult = $this->objDReportLoss->update($params, $where);
        if ($dbResult === false) {
            return ResultWrapper::fail($this->objDReportLoss->error(), ErrorCode::$dberror);
        }
        $returnData = $dbResult;
        return ResultWrapper::success($returnData);
    }

    /**
     * 库存报损审核
     * @param $updateData
     * @return ResultWrapper
     * @throws Exception
     */
    public function auditReportLoss($updateData)
    {
        $where['id'] = $updateData['id'];
        unset($updateData['id']);
        $updateData['auditStatus'] = StatusCode::$auditStatus['auditPass'];
        $updateData['auditTime'] = time();
        //查询报损信息
        $dbResult = $this->objDReportLoss->get($where);
        if ($dbResult === false) {
            return ResultWrapper::fail($this->objDReportLoss->error(), ErrorCode::$dberror);
        }
        if (empty($dbResult)) {
            return ResultWrapper::fail('库存报损信息为空', ErrorCode::$dberror);
        }
        $reportLossData = $dbResult;
        unset($dbResult);
        if ($reportLossData['auditStatus'] == StatusCode::$auditStatus['auditPass']) {
            return ResultWrapper::fail('该单据已审核', ErrorCode::$paramError);
        }

        //查询详情
        $dbResult = $this->objDReportLossDetails->select(['linkId' => $where['id']]);
        if ($dbResult === false) {
            return ResultWrapper::fail($this->objDReportLossDetails->error(), ErrorCode::$dberror);
        }
        $reportLossData['details'] = $dbResult;
        unset($dbResult);

        $reportLossData = array_merge($reportLossData, $updateData);

        $updateInventoryData = [
            'warehouseId' => $reportLossData['warehouseId'],
            'originId' => $reportLossData['id'],
            'originNo' => $reportLossData['no'],
            'sourceId' => $reportLossData['id'],
            'sourceNo' => $reportLossData['no'],
            'operatorId' => $this->userCenterId,
            'operatorName' => $updateData['auditName'],
            'remark' => $reportLossData['remark'],
            'type' => StatusCode::$orderType['reportLoss'],
        ];
        $updateInventoryData['details'] = $reportLossData['details'];

        $beginStatus = $this->objDReportLoss->beginTransaction();

        //减少库存
        $objMInventory= new MInventory($this->enterpriseId, $this->userCenterId);
        $modelResult = $objMInventory->updateDecInventoryNum($updateInventoryData);
        if(!$modelResult->isSuccess()){
            $this->objDReportLoss->rollBack();
            return ResultWrapper::fail($modelResult->getData(), $modelResult->getErrorCode());
        }

        //更改审核状态
        $dbResult = $this->objDReportLoss->update($updateData, $where);
        if ($dbResult === false) {
            $this->objDReportLoss->rollBack();
            return ResultWrapper::fail($this->objDReportLoss->error(), ErrorCode::$dberror);
        }
        $returnData = $dbResult;
        unset($dbResult);

        $beginStatus && $this->objDReportLoss->commit();
        return ResultWrapper::success($returnData);
    }

    /**
     * 库存报损修改
     * @param $updateData
     * @return ResultWrapper
     */
    public function updateReportLoss($updateData)
    {
        $where['id'] = $updateData['id'];
        unset($updateData['id']);
        unset($updateData['no']);
        $details = $updateData['details'];
        unset($updateData['details']);
        $deleteArray = $updateData['deleteArray'];
        unset($updateData['deleteArray']);
        $this->objDReportLoss->beginTransaction();
        if (isset($updateData['extend'])) unset($updateData['extend']);
        //查询要修改的单据
        $dbResult = $this->objDReportLoss->get($where);
        if($dbResult === false){
            return ResultWrapper::fail($this->objDReportLoss->error(), ErrorCode::$paramError);
        }
        $allocateData = $dbResult;
        unset($dbResult);

        $dbResult = $this->objDReportLoss->update($updateData, $where);
        if ($dbResult === false) {
            $this->objDReportLoss->rollBack();
            return ResultWrapper::fail($this->objDReportLoss->error(), ErrorCode::$dberror);
        }
        $returnData = $dbResult;
        unset($dbResult);
        $addDetailsData = [];
        foreach ($details as &$value) {
            $id = isset($value['id']) && !empty($value['id']) ? $value['id'] : 0;
            unset($value['id']);
            isset($value['batch']) && $value['batch'] = json_encode($value['batch']);
            if ($id) {
                //修改
                $dbResult = $this->objDReportLossDetails->update($value, ['id' => $id]);
                if ($dbResult === false) {
                    $this->objDReportLoss->rollBack();
                    return ResultWrapper::fail($this->objDReportLossDetails->error(), ErrorCode::$dberror);
                }
                unset($dbResult);
                //修改es
                $esId = parent::setEsId($this->enterpriseId, 'allocateId', $id);
                $esResult = $this->objDReportLossDetails->esupdateTypeFieldVaule($updateData, $esId);
                if (!$esResult) {
                    $this->objDReportLoss->rollBack();
                    return ResultWrapper::fail($esResult, ErrorCode::$paramError);
                }
            } else {
                //新增
                $addDetails = [
                    'linkId' => $where['id'],
                    'linkNo' => $updateData['no'],
                    'materielId' => $value['materielId'],
                    'materielName' => $value['materielName'],
                    'materielCode' => $value['materielCode'],
                    'skuId' => $value['skuId'],
                    'num' => $value['num'],
                    'otherNum' => $value['otherNum'],
                    'costUnitPrice' => $value['costUnitPrice'],
                    'deleteStatus' => StatusCode::$standard,
                    'createTime' => time(),
                    'updateTime' => time(),
                ];
                isset($value['batch']) && $addDetails['batch'] = $value['batch'];
                $addDetailsData[] = $addDetails;
            }
        }
        //删除
        if ($deleteArray) {
            $dbResult = $this->objDReportLossDetails->update(['deleteStatus' => StatusCode::$delete, 'updateTime' => time()], ['id' => $deleteArray]);
            if ($dbResult === false) {
                $this->objDReportLoss->rollBack();
                return ResultWrapper::fail($this->objDReportLossDetails->error(), ErrorCode::$dberror);
            }
            //es删除
            foreach ($deleteArray as $value) {
                $esResult = $this->objDReportLossDetails->esupdateTypeFieldVaule(['deleteStats' => StatusCode::$delete, 'updateTime' => time()], $value);
                if (!$esResult) {
                    return ResultWrapper::fail($esResult, ErrorCode::$paramError);
                }
            }
        }

        //新增
        if ($addDetailsData) {
            $dbResult = $this->objDReportLossDetails->insert($addDetailsData, true);
            if ($dbResult === false) {
                return ResultWrapper::fail($this->objDReportLossDetails->error(), ErrorCode::$dberror);
            }
            $detailsIds = $dbResult;
            unset($dbResult);
            //新增es
            foreach ($addDetailsData as $key => $value) {
                $modelResult = self::updateEsData($value, $allocateData, $detailsIds[$key], true);
                if (!$modelResult->isSuccess()) {
                    $this->objDReportLoss->rollBack();
                    return ResultWrapper::fail($modelResult->getData(), $modelResult->getErrorCode());
                }
            }
        }

        $this->objDReportLoss->commit();
        return ResultWrapper::success($returnData);
    }

    /**
     * 库存报损列表
     * @param $selectParams
     * @return ResultWrapper
     * @throws Exception
     */
    public function getAllReportLoss($selectParams)
    {
        $limit = $selectParams['limit'];
        unset($selectParams['limit']);
        $offset = $selectParams['offset'];
        unset($selectParams['offset']);
        $whereSql = ' deleteStatus = '.StatusCode::$standard;
        if(isset($selectParams['no']) && !empty($selectParams['no'])){
            if (strstr($selectParams['no'],StatusCode::$noPrefix['33'])){
                $selectParams['no'] = substr($selectParams['no'],strlen(StatusCode::$noPrefix['33'])+1);
            }
            $str = substr_replace($selectParams['no'].' ','%"',-1);
            $no = substr_replace($str,'"%',0,0);
            $whereSql .= ' and `no` like ' . $no;
        }
        if(isset($selectParams['warehouseId']) && !empty($selectParams['warehouseId'])){
            $whereSql .= ' and warehouseId = ' . $selectParams['warehouseId'];
        }

        if(isset($selectParams['auditStatus']) && !empty($selectParams['auditStatus'])){
            $whereSql .= ' and auditStatus = ' . $selectParams['auditStatus'];
        }

        if(isset($selectParams['star']) && !empty($selectParams['star']) && isset($selectParams['end']) && !empty($selectParams['end'])){
            $whereSql .= ' and createTime BETWEEN ' . $selectParams['star'] . ' and ' . $selectParams['end'];
        }

        $dbResult = $this->objDReportLoss->select($whereSql,'*', 'createTime desc', $limit, $offset);
        if ($dbResult === false) {
            return ResultWrapper::fail($this->objDReportLoss->error(), ErrorCode::$dberror);
        }

        // 渲染编号
        foreach ($dbResult as $key =>$value){
            if(isset($dbResult[$key]['no']) && !empty($dbResult[$key]['no']) ){
                $dbResult[$key]['no'] = StatusCode::$noPrefix['33'].'-'.$value['no'];
            }
        }

        $countResult = $this->objDReportLoss->count($whereSql);
        if ($countResult === false) {
            return ResultWrapper::fail($this->objDReportLoss->error(), ErrorCode::$dberror);
        }

        $formatData = parent::formatOrderMan($this->enterpriseId, $dbResult);
        $return = [
            'data' => $formatData,
            'total' => ($countResult) ? intval($countResult) : 0,
        ];
        return ResultWrapper::success($return);
    }

    /**
     * 库存报损详情
     * @param $params
     * @return ResultWrapper
     * @throws Exception
     */
    public function getReportLossInfo($params)
    {
        $params['deleteStatus'] = StatusCode::$standard;
        $dbResult = $this->objDReportLoss->get($params);
        if ($dbResult === false) {
            return ResultWrapper::fail($this->objDReportLoss->error(), ErrorCode::$dberror);
        }
        $returnData = $dbResult;
        unset($dbResult);
        $dbResult = $this->objDReportLossDetails->select(['linkId' => $params['id'], 'deleteStatus' => StatusCode::$standard]);
        if ($dbResult === false) {
            return ResultWrapper::fail($this->objDReportLossDetails->error(), ErrorCode::$dberror);
        }
        $returnData['details'] = $dbResult;
        unset($dbResult);

        $returnData = parent::formatOrderMan($this->enterpriseId, $returnData);
        return ResultWrapper::success($returnData);
    }

    /**
     * 查询多条报损数据
     * @param $where
     * @return ResultWrapper
     */
    public function selectReportLossData($where)
    {
        $where['deleteStatus'] = StatusCode::$standard;
        $dbResult = $this->objDReportLoss->select($where);
        if($dbResult === false){
            return ResultWrapper::fail($this->objDReportLoss->error(), ErrorCode::$dberror);
        }
        return ResultWrapper::success($dbResult);
    }

    /**
     * 查询报损数据
     * @param $where
     * @return ResultWrapper
     */
    public function getReportLoss($where)
    {
        $where['deleteStatus'] = StatusCode::$standard;
        $dbResult = $this->objDReportLoss->get($where);
        if ($dbResult === false) {
            return ResultWrapper::fail($this->objDReportLoss->error(), ErrorCode::$dberror);
        }
        return ResultWrapper::success($dbResult);
    }


    /**
     * 报损导出
     * @param $selectParams
     * @return ResultWrapper
     * @throws Exception
     */
    public function reportLossExport($selectParams)
    {
        $whereSql = ' where r.deleteStatus = '.StatusCode::$standard;
        if(isset($selectParams['no']) && !empty($selectParams['no'])){
            $whereSql .= ' and r.`no` = ' . $selectParams['no'];
        }

        if(isset($selectParams['warehouseId']) && !empty($selectParams['warehouseId'])){
            $whereSql .= ' and r.warehouseId = ' . $selectParams['warehouseId'];
        }

        if(isset($selectParams['auditStatus']) && !empty($selectParams['auditStatus'])){
            $whereSql .= ' and r.auditStatus = ' . $selectParams['auditStatus'];
        }

        if(isset($selectParams['star']) && !empty($selectParams['star']) && isset($selectParams['end']) && !empty($selectParams['end'])){
            $whereSql .= ' and r.createTime BETWEEN ' . $selectParams['star'] . ' and ' . $selectParams['end'];
        }

        $sql = 'select d.*,r.warehouseId,r.warehouseName from qianniao_report_loss_details_'.$this->enterpriseId.' d left join qianniao_report_loss_'.$this->enterpriseId.' r on d.linkId = r.id';
        $orderSql = ' order by d.createTime desc';
        $selectSql = $sql.$whereSql.$orderSql;
        $dbResult = $this->objDReportLoss->exportQuery($selectSql);
        if($dbResult === false){
            return ResultWrapper::fail($this->objDReportLoss->error(), ErrorCode::$dberror);
        }
        self::exportReportLoss($dbResult);
        ResultWrapper::success('操作成功');
    }



    /**
     * 报损商品导出方法
     * @param $result
     * @return void
     * @throws Exception
     */
    public function exportReportLoss($result)
    {
        //导出到本地
        header("Content-type:application/vnd.ms-excel");
        header("Content-Disposition:filename=报损记录表.csv");
        header('Cache-Control: max-age=0');

        $fp = fopen('php://output', 'a');

        $head = ['报损单号','商品名称', '仓库', '库存单位', '库存属性', '账目库存', '报损数量', '其他单位', '报损金额', '报损日期'];       //定义标题

        foreach ($head as $i => $v) {
            $head[$i] = mb_convert_encoding($v, 'GBK', 'utf-8');     //将中文标题转换编码，否则乱码
        }

        fputcsv($fp, $head);

        $limit = 10000;
        $num = 0;                                         //计数器
        foreach ($result as $v) {                           //循环数据
            $num++;
            if ($num == $limit) {
                ob_flush();         //释放内存
                flush();
            }
            $rows['no'] = isset($v['linkNo']) ? $v['linkNo'] : '';
            $rows['materielName'] = isset($v['materielName']) ? $v['materielName'] : '';
            $rows['warehouseName'] = isset($v['warehouseName']) ? $v['warehouseName'] : '';
            $rows['unitName'] = isset($v['unitName']) ? $v['unitName'] : '';
            $rows['skuName'] = isset($v['skuName']) ? $v['skuName'] : '';
            $rows['inventoryNum'] = isset($v['inventoryNum']) ? $v['inventoryNum'] : '';
            $rows['num'] = isset($v['num']) ? $v['num'] : '';
            $rows['otherNum'] = isset($v['otherNum']) ? $v['otherNum'] : '';
            $rows['lossAmount'] = isset($v['lossAmount']) ? $v['lossAmount'] : '';
            $rows['createTime'] = isset($v['createTime']) ? $v['createTime'] : '';
            foreach ($rows as $kk => $vv) {
                $rs[$kk] = mb_convert_encoding($vv, 'GBK', 'utf-8');  //转译编码
            }
            fputcsv($fp, $rs);

            $rows = [];
        }
    }

}