<?php
/**
 * 收款单管理模块
 * Created by PhpStorm.
 * User: wxj
 * Date: 2019/10/30
 * Time: 14:02
 */

namespace JinDouYun\Model\Finance;

use JinDouYun\Dao\Order\DOrder;
use Mall\Framework\Core\ErrorCode;
use Mall\Framework\Core\StatusCode;
use Mall\Framework\Core\ResultWrapper;

use JinDouYun\Dao\Finance\DReceived;
use JinDouYun\Dao\Finance\DReceivedIndex;
use JinDouYun\Dao\Finance\DReceivedAccount;
use JinDouYun\Dao\Finance\DReceivedReceiptCheckQueue;
use JinDouYun\Dao\Finance\DReceiveReceiptIndex;
use JinDouYun\Dao\Finance\DReceiveOffset;

use JinDouYun\Dao\Finance\DReceive;
use JinDouYun\Model\Order\MOrder;
use JinDouYun\Model\MBaseModel;
use JinDouYun\Model\Finance\MCustomerBalanceDetail;
use JinDouYun\Model\Finance\MCustomerBalance;
use JinDouYun\Model\Finance\MAccount;
use JinDouYun\Model\Finance\MAccountDetail;
use JinDouYun\Model\Finance\MFinanceType;

use JinDouYun\Cache\OverviewCache;

class MReceived extends MBaseModel
{
    private $objDReceive;
    private $objDReceived;
    private $objDReceivedIndex;
    private $objDReceivedAccount;
    private $objMCustomerBalanceDetail;
    private $objMCustomerBalance;
    private $objMAccount;
    private $objMAccountDetail;
    private $objOverviewCache;
    private $objDReceivedReceiptCheckQueue;
    private $objDReceiveReceiptIndex;
    private $objMFinanceType;
    private $objDReceiveOffset;

    private $enterpriseId;
    private $userCenterId;

    /**
     * @param $enterpriseId
     * @param $userCenterId
     * @throws \Exception
     */
    public function __construct($enterpriseId, $userCenterId)
    {
        $this->userCenterId = $userCenterId;
        $this->enterpriseId = $enterpriseId;
        parent::__construct($enterpriseId, $userCenterId);

        $this->objMCustomerBalanceDetail = new MCustomerBalanceDetail($enterpriseId, $userCenterId);
        $this->objMCustomerBalance = new MCustomerBalance($enterpriseId, $userCenterId);
        $this->objMAccount = new MAccount($enterpriseId, $userCenterId);
        $this->objMAccountDetail = new MAccountDetail($enterpriseId, $userCenterId);
        $this->objMFinanceType = new MFinanceType($enterpriseId, $userCenterId);

        $this->objDReceive = new DReceive('finance');
        $this->objDReceived = new DReceived('finance');
        $this->objDReceivedIndex = new DReceivedIndex('finance');
        $this->objDReceivedAccount = new DReceivedAccount('finance');
        $this->objOverviewCache = new OverviewCache();
        $this->objDReceivedReceiptCheckQueue = new DReceivedReceiptCheckQueue('finance');
        $this->objDReceiveReceiptIndex = new DReceiveReceiptIndex('finance');
        $this->objDReceiveOffset = new DReceiveOffset('finance');

        $this->objDReceiveOffset->setTable('qianniao_receive_offset_'. $enterpriseId);
        $this->objDReceived->setTable('qianniao_received_' . $enterpriseId . '_' . date('Y') . '_' . ceil(date('m') / 3));
        $this->objDReceivedAccount->setTable('qianniao_received_account_' . $enterpriseId . '_' . date('Y') . '_' . ceil(date('m') / 3));
        $this->objDReceivedIndex->setTable('qianniao_received_index_' . $enterpriseId);
        $this->objDReceiveReceiptIndex->setTable('qianniao_receive_receipt_index_'.$enterpriseId);
        //$this->objDReceived->setSearchIndex('received_receipt_search')->setType('received_receipt');

    }

    /**
     * 添加收款单
     *
     * @param array $params 收款单数据
     * @param bool $autoCheck 是否需要自动审核
     * @return ResultWrapper
     */
    public function addReceived($params, $autoCheck= false)
    {
        $offsetDate = $params['receiptOffsetData'];
        unset($params['receiptOffsetData']);
        $accountList = $params['accountList'];
        unset($params['accountList']);

        $beginTransactionStatus = $this->objDReceived->beginTransaction();

        //先款后货查询收款单是否已生成
        if($params['originId'] != 0){
            $dbResult = $this->objDReceived->get(['originId'=>$params['originId']]);
            if ($dbResult === false) {
                return ResultWrapper::fail($this->objDReceived->error(), ErrorCode::$dberror);
            }
            if(!empty($dbResult)){
                // 查询订单是否是先款后货的
                $objMOrder = new DOrder();
                $orderDbResult = $objMOrder->query('select * from qianniao_order_'.$this->enterpriseId.'_1 where id = '.$params['originId']);
                if ($orderDbResult === false) {
                    return ResultWrapper::fail($objMOrder->error(), ErrorCode::$dberror);
                }
                if (!empty($orderDbResult) && $orderDbResult[0]['payType'] == StatusCode::$payType['cashBefore']){// 说明该先款后货的单子已经生成过
                    return ResultWrapper::fail('该订单已经创建收款单,请先审核收款单',ErrorCode::$notAllowAccess);
                }
            }
        }

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

        // 索引表数据
        $indexData = [
            'no'                 => $params['no'],
            'receivedId'         => 0,
            'customerId'         => $params['customerId'],
            'currentAccountName' => $params['currentAccountName'],//制单人
            'sourceNo'           => $params['sourceNo'],
            'sourceId'           => getArrayItem($params,'sourceId',0),
            'originId'           => getArrayItem($params,'originId',0),
            'originNo'           => getArrayItem($params,'originNo',''),
            'auditStatus'        => $params['auditStatus'],
            'financeTypeId'      => $params['financeTypeId'],
            'financeType'        => $params['financeType'],
            'receivedType'       => empty($offsetDate) ? StatusCode::$standard : StatusCode::$delete,
            'createTime'         => $params['createTime'],
            'updateTime'         => $params['updateTime'],
            'receiptTime'        => $params['receiptTime'],
        ];
        $ReceivedId = $this->objDReceivedIndex->insert($indexData);
        if ($ReceivedId === false) {
            $this->objDReceived->rollBack();
            return ResultWrapper::fail($this->objDReceivedIndex->error(), ErrorCode::$dberror);
        }

        // 收款单表数据
        $params['id'] = $ReceivedId; // 收款单id = 索引表自动id
        $params['totalMoney'] = 0;
        $params['totalDiscountMoney'] = 0;
        $params['totalFinalMoney'] = 0;
        foreach ($accountList as $account) {
            $account['discountMoney'] = !empty($account['discountMoney']) ? $account['discountMoney'] : 0;
            $params['totalMoney'] = bcadd($params['totalMoney'], $account['money'], 4);//总金额
            $params['totalDiscountMoney'] = bcadd($params['totalDiscountMoney'], $account['discountMoney'], 4); //总优惠金额
            $params['totalFinalMoney'] = bcadd($params['totalFinalMoney'], bcsub($account['money'] , $account['discountMoney'], 4), 4);//总实付金额
            $params['offsetStatus'] = StatusCode::$delete;
        }
        $params['offsetMoney'] = 0;
        $params['notOffsetMoney'] = bcadd($params['totalFinalMoney'],$params['totalDiscountMoney'],2);
        $result = $this->objDReceived->insert($params);
        if ($result === false) {
            $this->objDReceived->rollBack();
            return ResultWrapper::fail($this->objDReceived->error(), ErrorCode::$dberror);
        }

        //收款账户数据
        foreach ($accountList as $account) {
            $account['operatorId'] = $this->userCenterId;
            $account['receivedId'] = $ReceivedId;
            $account['finalMoney'] = bcsub($account['money'],$account['discountMoney'],2);
            $account = self::buildAccountData($account);
            $result = $this->objDReceivedAccount->insert($account);
            if ($result === false) {
                $this->objDReceived->rollBack();
                return ResultWrapper::fail($this->objDReceivedAccount->error(), ErrorCode::$dberror);
            }
            unset($result);
        }

        //需要自动审核的单据加到队列表里,通过cron审核
        if($autoCheck) {
            $data = [
                'enterpriseId'=>$this->enterpriseId,
                'receivedNo'=>$params['no'],
                'createTime'=>$params['createTime']
            ];
            $result = $this->objDReceivedReceiptCheckQueue->insert($data);
            if ($result === false) {
                $this->objDReceived->rollBack();
                return ResultWrapper::fail($this->objDReceivedReceiptCheckQueue->error(), ErrorCode::$dberror);
            }
        }

        //记录核销明细
        if (empty($offsetDate)){
            if( $beginTransactionStatus ){
                $this->objDReceived->commit();
            }
            return ResultWrapper::success($ReceivedId);
        }

        if(!empty($offsetDate)){
            foreach ($offsetDate as $key => $value){
                $offsetDate[$key]['receivedId'] = $ReceivedId;
            }
        }
        unset($result);
        $result = $this->objDReceiveOffset->insert($offsetDate,true);
        if ($result === false) {
            $this->objDReceived->rollBack();
            return ResultWrapper::fail($this->objDReceiveOffset->error(), ErrorCode::$dberror);
        }

        if( $beginTransactionStatus ){
            $this->objDReceived->commit();
        }

        /*
        $_id = self::createEsDocumentId($ReceivedId, $params['createTime']);
        $esData = $params;
        $esData['id'] = $ReceivedId;
        $esData['enterpriseId'] = $this->enterpriseId;
        $result = $this->objDReceived->addUpSearchIndexDocument($esData, $_id);
        if (isset($result['_shards']) && isset($result['_shards']['successful']) && $result['_shards']['successful'] == 1) {
            //echo "es操作成功";die;
        }else {
            file_put_contents('/apps/logs/elasticsearch.log',date('Y-m-d H:i:s').'生成收款单es错误,错误原因'.var_export($result,true).PHP_EOL,FILE_APPEND);
        }
        */

        return ResultWrapper::success($ReceivedId);
    }

    /**
     * Doc: (des="")
     * User: XMing
     * Date: 2020/11/5
     * Time: 7:08 下午
     * @param array $params
     * @return array
     */
    public static function buildAccountData(array $params)
    {
        return [
            'receivedId' => isset($params['receivedId']) ? $params['receivedId'] : 0,
            'accountId' => isset($params['accountId']) ? $params['accountId'] : 0,
            'accountNumber' => isset($params['accountNumber']) ? $params['accountNumber'] : 0,
            'accountName' => getArrayItem($params, 'accountName', ''),
            'money' => isset($params['money']) ? $params['money'] : 0,
            'discountMoney' => isset($params['discountMoney']) ? $params['discountMoney'] : 0,
            'finalMoney' => isset($params['finalMoney']) ? $params['finalMoney'] : 0,
            'payWay' => isset($params['payWay']) ? $params['payWay'] : 0,
            'remark' => isset($params['remark']) ? $params['remark'] : '',
            'createTime' => time(),
            'updateTime' => time(),
            'operatorId' => isset($params['operatorId']) ? $params['operatorId'] : 0,
        ];
    }

    /**
     * 编辑收款单
     * @param $params
     * @return ResultWrapper
     * @throws \Exception
     */
    public function editReceived($params)
    {
        $this->objDReceived->setTable('qianniao_received_' . $this->enterpriseId . '_' . date('Y', $params['createTime']) . '_' . ceil(date('m', $params['createTime']) / 3));
        $this->objDReceivedAccount->setTable('qianniao_received_account_' . $this->enterpriseId . '_' . date('Y', $params['createTime']) . '_' . ceil(date('m', $params['createTime']) / 3));

        $beginTransactionstatus = $this->objDReceived->beginTransaction();

        $accountList = $params['accountList'];
        unset($params['accountList']);
        $offsetDate = $params['receiptOffsetData'];
        unset($params['receiptOffsetData']);

        $params['totalMoney'] = 0;
        $params['totalDiscountMoney'] = 0;
        $params['totalFinalMoney'] = 0;
        foreach ($accountList as $account) {
            $account['discountMoney'] = !empty($account['discountMoney']) ? $account['discountMoney'] : 0;
            $params['totalMoney'] += $account['money'];
            $params['totalDiscountMoney'] += $account['discountMoney'];
            $params['totalFinalMoney'] += ($account['money'] - $account['discountMoney']);
        }

        $receivedId = $params['id'];
        unset($params['id']);
        if( isset($params['no']) ){
            unset($params['no']);
        }
        $dbResult = $this->objDReceived->update($params, $receivedId);

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

        //索引表数据
        $indexData = [
            'customerId'         => $params['customerId'],
            'currentAccountName' => $params['currentAccountName'],
            'sourceNo'           => $params['sourceNo'],
            'auditStatus'        => $params['auditStatus'],
            'financeTypeId'      => $params['financeTypeId'],
            'financeType'        => $params['financeType'],
            'receivedType'       => empty($offsetDate) ? StatusCode::$standard : StatusCode::$delete,
            'createTime'         => $params['createTime'],
            'updateTime'         => $params['updateTime'],
            'receiptTime'        => $params['receiptTime'],
        ];
        $result = $this->objDReceivedIndex->update($indexData,['id'=>$receivedId]);

        if ($result === false) {
            $this->objDReceived->rollBack();
            return ResultWrapper::fail($this->objDReceivedIndex->error(), ErrorCode::$dberror);
        }
        unset($result);
        //收款账户数据
        foreach ($accountList as $account) {
            if (isset($account['id'])) {
                $account['receivedId'] = $receivedId;
                $account['operatorId'] = $this->userCenterId;
                $account['updateTime'] = $params['updateTime'];
                $result = $this->objDReceivedAccount->update($account, $account['id']);
            }else{
                $account['receivedId'] = $receivedId;
                $account['operatorId'] = $this->userCenterId;
                $account['createTime'] = $params['createTime'];
                $result = $this->objDReceivedAccount->insert($account);
            }
            if ($result === false) {
                $this->objDReceived->rollBack();
                return ResultWrapper::fail($this->objDReceivedAccount->error(), ErrorCode::$dberror);
            }
            unset($result);
        }

        //更新核销明细
        if (empty($offsetDate)){
            if($beginTransactionstatus){
                $this->objDReceived->commit();
            }
            return ResultWrapper::success($dbResult);
        }
        if(!empty($offsetDate)){
            foreach ($offsetDate as $key => $value){
                $offsetDate[$key]['receivedId'] = $receivedId;
                unset($result);
                $result = $this->objDReceiveOffset->update($value, ['receivedId'=>$receivedId]);
            }
        }
        if ($result === false) {
            $this->objDReceived->rollBack();
            return ResultWrapper::fail($this->objDReceiveOffset->error(), ErrorCode::$dberror);
        }

        if($beginTransactionstatus){
            $this->objDReceived->commit();
        }
        /*
        $_id = self::createEsDocumentId($receivedId, $params['createTime']);
        $esData = $params;
        $esData['id'] = $receivedId;
        $esData['enterpriseId'] = $this->enterpriseId;
        $this->objDReceived->esupdateTypeFieldVaule($esData, $_id);
        */

        return ResultWrapper::success($dbResult);
    }

    private function createEsDocumentId($receivedId, $time)
    {
        $t = date('Y', $time) . '_' . ceil(date('m', $time) / 3);
        return 'EnterpriseId_' . $this->enterpriseId . '_' . $t . '_receivedId_' . $receivedId;
    }

    /**
     * 获取指定收款单信息
     * @param $receivedParams
     * @return ResultWrapper
     * @throws \Exception
     */
    public function getReceivedInfo($receivedParams)
    {
        unset($receivedParams['createTime']);
        $receivedIndexData = $this->objDReceivedIndex->get($receivedParams['id']);
        if ($receivedIndexData === false) {
            return ResultWrapper::fail($this->objDReceivedIndex->error(), ErrorCode::$dberror);
        }
        if(empty($receivedIndexData)){
            return ResultWrapper::fail('要查看的收款单索引数据不存在', ErrorCode::$contentNotExists);
        }

        $this->objDReceived->setTable('qianniao_received_' . $this->enterpriseId . '_' . date('Y', $receivedIndexData['createTime']) . '_' . ceil(date('m', $receivedIndexData['createTime']) / 3));
        $this->objDReceivedAccount->setTable('qianniao_received_account_' . $this->enterpriseId . '_' . date('Y', $receivedIndexData['createTime']) . '_' . ceil(date('m', $receivedIndexData['createTime']) / 3));
        $dbResult = $this->objDReceived->get($receivedParams);
        if ($dbResult === false) {
            return ResultWrapper::fail($this->objDReceived->error(), ErrorCode::$dberror);
        }
        if(empty($dbResult)){
            return ResultWrapper::fail('要查看的收款单不存在', ErrorCode::$contentNotExists);
        }

        //渲染前缀
        $dbResult['no'] = StatusCode::$noPrefix[17] . '-' . $dbResult['no'];
        //渲染凭证
        if( isset($dbResult['extends'])&& !empty($dbResult['extends']) ){
            $dbResult['extends'] = json_decode($dbResult['extends'],true);
        }
        $accountData = $this->objDReceivedAccount->select(['receivedId' => $receivedParams['id'],'deleteStatus'=>StatusCode::$standard]);
        if ($accountData === false) {
            return ResultWrapper::fail($this->objDReceivedAccount->error(), ErrorCode::$dberror);
        }
        $dbResult['accountList'] = $accountData;
        //查出客户当前余额
        $dbResult['currentBalanceMoney'] = !empty($dbResult['customerId']) ? $this->objMCustomerBalance->getCustomerBalance($dbResult['customerId']) : 0;

        // 处理应收和收款单核销关系
        $dbResult['offsetDate']= [];
        $offsetdbResult = $this->objDReceiveOffset->select(['receivedId' => $receivedParams['id']]);
        if ( $offsetdbResult === false ) {
            return ResultWrapper::fail($this->objDReceiveOffset->error(), ErrorCode::$dberror);
        }
        if ( !empty($offsetdbResult) ){
            // 映射应收单对应的核销金额
            $receiveReceiptIdBindOffsetMoney = [];
            foreach ($offsetdbResult as $key => $value){
                $receiveReceiptIdBindOffsetMoney[$value['receiveReceiptId']] = $value['offsetMoney'];
            }

            // 批量查询应收数据
            $receiveReceiptIds = array_column($offsetdbResult,'receiveReceiptId');
            $objMReceive = new MReceive($this->enterpriseId, $this->userCenterId);
            $selectParams = [
                'limit'  => 200,
                'offset' => 0,
                'receiveReceiptIds' => $receiveReceiptIds,
                'offsetStatus' =>$offsetdbResult['offsetStatus']
            ];
            $receiveData = $objMReceive->getAllReceive($selectParams);
            if(!$receiveData->isSuccess()){
                return ResultWrapper::fail($receiveData->getData(), $receiveData->getErrorCode());
            }
            $receiveData = $receiveData->getData();
            if(!empty($receiveData['total'])){
                foreach ($receiveData['data'] as $key => $value){
                    $receiveData['data'][$key]['offsetMoney'] = getArrayItem($receiveReceiptIdBindOffsetMoney, $value['id'], 0);
                }
                $dbResult['offsetDate'] = $receiveData['data'];
            }
        }

        return ResultWrapper::success($dbResult);
    }

    /**
     * 删除收款单
     */
    public function updateReceivedDeleteStatus($where, $createTime)
    {
        $this->objDReceived->setTable('qianniao_received_' . $this->enterpriseId . '_' . date('Y', $createTime) . '_' . ceil(date('m', $createTime) / 3));
        $this->objDReceivedAccount->setTable('qianniao_received_account_' . $this->enterpriseId . '_' . date('Y', $createTime) . '_' . ceil(date('m', $createTime) / 3));

        $receivedId = $this->objDReceivedIndex->get($where, 'receivedId');
        if ($receivedId === false) {
            return ResultWrapper::fail($this->objDReceivedIndex->error(), ErrorCode::$dberror);
        }

        if(empty($receivedId)){
            return ResultWrapper::fail('要删除的收款单不存在', ErrorCode::$contentNotExists);
        }

        // 删除索引
        $dbResult = $this->objDReceivedIndex->update(['deleteStatus'=>StatusCode::$delete,'updateTime'=>time()], ['id'=>$receivedId]);
        if ($dbResult === false) {
            return ResultWrapper::fail($this->objDReceivedIndex->error(), ErrorCode::$dberror);
        }
        // 删除收款单单据
        $dbResult = $this->objDReceived->update(['deleteStatus'=>StatusCode::$delete,'updateTime'=>time()], ['id'=>$receivedId]);
        if ($dbResult === false) {
            return ResultWrapper::fail($this->objDReceived->error(), ErrorCode::$dberror);
        }
        // 删除收款单账号
        $dbResult = $this->objDReceivedAccount->update(['deleteStatus'=>StatusCode::$delete,'updateTime'=>time(), ['receivedId'=>$receivedId]]);
        if ($dbResult === false) {
            return ResultWrapper::fail($this->objDReceivedAccount->error(), ErrorCode::$dberror);
        }

        return ResultWrapper::success('删除成功');
    }

    /**
     * 收款单审核 (修改 判断账户是否存在)
     * @param array $params
     * @return ResultWrapper
     * @throws \Exception
     */
    public function updateReceivedStatus($params)
    {
        // 切换收款单和收款单账户表
        $this->objDReceived->setTable('qianniao_received_' . $this->enterpriseId . '_' . date('Y', $params['createTime']) . '_' . ceil(date('m', $params['createTime']) / 3));
        $this->objDReceivedAccount->setTable('qianniao_received_account_' . $this->enterpriseId . '_' . date('Y', $params['createTime']) . '_' . ceil(date('m', $params['createTime']) / 3));

        // 查询收款单数据
        $receivedData = $this->objDReceived->get(['id' => $params['id']]);
        if ($receivedData === false) {
            return ResultWrapper::fail($this->objDReceived->error(), ErrorCode::$dberror);
        }
        if(empty($receivedData)){
            return ResultWrapper::fail('要操作得收款单不存在', ErrorCode::$contentNotExists);
        }
        if($receivedData['auditStatus'] == StatusCode:: $auditStatus['auditPass']){
            return ResultWrapper::fail('当前收款单已经审核过了', ErrorCode::$notAllowAccess);
        }


        $beginTransactionStatus = $this->objDReceived->beginTransaction();
        // 更新收款单审核状态
        $dbResult = $this->objDReceived->update(['auditStatus' => StatusCode:: $auditStatus['auditPass']], ['id' => $params['id']]);
        if ($dbResult === false) {
            $this->objDReceived->rollBack();
            return ResultWrapper::fail($this->objDReceived->error(), ErrorCode::$dberror);
        }
        unset($dbResult);
        // 更新收款单索引表审核状态
        $dbResult = $this->objDReceivedIndex->update(['auditStatus' => StatusCode:: $auditStatus['auditPass']], ['id' => $params['id']]);
        if ($dbResult === false) {
            $this->objDReceived->rollBack();
            return ResultWrapper::fail($this->objDReceivedIndex->error(), ErrorCode::$dberror);
        }
        unset($dbResult);
        // 获取客户往来余额
        $customerBalance = $this->objMCustomerBalance->getCustomerBalance($receivedData['customerId']);
        // 查出源单据已收过的金额
        $remark = '';
        if (!empty($receivedData['sourceNo'])) {
            $beforeReceivedMoney = 0;
            $where = 'sourceNo = ' . $receivedData['sourceNo'] . ' AND auditStatus = ' . StatusCode::$auditStatus['auditPass'] . ' AND receivedId !=' . $params['id'];
            $sourceNoReceivedResult = $this->objDReceivedIndex->get($where);
            if (!empty($sourceNoReceivedResult)) {
                $this->objDReceived->setTable('qianniao_received_' . $this->enterpriseId . '_' . date('Y', $sourceNoReceivedResult['createTime']) . '_' . ceil(date('m', $sourceNoReceivedResult['createTime']) / 3));
                $beforeReceivedMoney = $this->objDReceived->get_field('totalMoney', $sourceNoReceivedResult['receivedId']);
            }
            $remark = ',源单据剩余应收'. bcsub(bcsub($receivedData['sourceNoMoney'] , $beforeReceivedMoney, 4), $receivedData['totalMoney'], 4) . '元';
        }


        $detailData = [
            'customerId'             => $receivedData['customerId'],//'客户id',
            'receiptTime'            => $receivedData['receiptTime'],//'单据日期',
            'sourceId'               => $receivedData['id'],//'单据编号',
            'sourceNo'               => $receivedData['no'],//'单据编号',
            'financeType'            => $receivedData['financeType'],//'财务类型名称',
            'financeTypeId'          => $receivedData['financeTypeId'],//'财务类型id',
            'originNo'               => $receivedData['sourceNo'],//'源订单销货号',
            'originId'               => $receivedData['sourceId'],//'源订单销货号',
            'salesAmount'            => $receivedData['totalMoney'],//总金额
            'discountMoney'          => $receivedData['totalDiscountMoney'],// '优惠金额',
            'customerAmount'         => $receivedData['totalFinalMoney'],// '客户承担金额',
            'receivableAmount'       => $receivedData['totalFinalMoney'],// '应收金额',
            'actualReceivableAmount' => $receivedData['totalFinalMoney'],//'实际收款金额',
            'receivableBalance'      => bcsub($customerBalance , $receivedData['totalFinalMoney'], 4),//'应收后余额',
            'remark'                 => '收款单审核通过,本次优惠后实收' . $receivedData['totalFinalMoney'] . '元,优惠'.$receivedData['totalDiscountMoney'].'元'.$remark,//'备注',
            'createTime'             => time(),//'创建日期',
            'updateTime'             => time(),//'修改日期',
        ];
        // 添加客户往来余额明细,修改客户往来余额
        $result = $this->objMCustomerBalanceDetail->addCustomerBalanceDetail($detailData);
        if (!$result->isSuccess()) {
            $this->objDReceived->rollBack();
            return ResultWrapper::fail($result->getData(), $result->getErrorCode());
        }

        // 编辑客户往来余额
        $changedMoney = $receivedData['totalMoney'] > 0 ? -1 * $receivedData['totalFinalMoney'] : abs($receivedData['totalFinalMoney']);
        $result = $this->objMCustomerBalance->addCustomerBalance($receivedData['customerId'], $changedMoney);
        if (!$result->isSuccess()) {
            $this->objDReceived->rollBack();
            return ResultWrapper::fail($result->getData(), $result->getErrorCode());
        }

        // 查询核销记录表
        $offsetDbResult = $this->objDReceiveOffset->select(['receivedId'=>$receivedData['id'],'type'=>StatusCode::$standard]);
        if ($offsetDbResult === false) {
            return ResultWrapper::fail($this->objDReceiveOffset->error(), ErrorCode::$dberror);
        }
        // 核销收款单指定的应收单
        if (!empty($offsetDbResult)){
            // 手动核销指定的应收单数据
            foreach ($offsetDbResult as $offsetKey =>$offsetValue){
                // 查询应收单数据
                $sql = 'select * from ' . $this->objDReceiveReceiptIndex->get_Table() . ' where id='.$offsetValue['receiveReceiptId'];
                $firstOffset = $this->objDReceiveReceiptIndex->query($sql);
                if ($firstOffset === false) {
                    $this->objDReceived->rollBack();
                    return ResultWrapper::fail($this->objDReceiveReceiptIndex->error(), ErrorCode::$dberror);
                }
                if(empty($firstOffset)){
                    $this->objDReceived->rollBack();
                    return ResultWrapper::fail('要操作得应收单不存在', ErrorCode::$contentNotExists);
                }

                // 当前要处理的应收单已经核销则不做处理
                if( $firstOffset[0]['offsetStatus'] == StatusCode::$standard ){
                    continue;
                }
                $autoCustomerMoney = self::autoCustomerMoney($receivedData['customerId'],bcadd($receivedData['totalFinalMoney'],$receivedData['totalDiscountMoney'],2),$receivedData['id'],$receivedData['createTime'],$firstOffset,$offsetValue['receiveReceiptId']);
                if(!$autoCustomerMoney->isSuccess()){
                    $this->objDReceived->rollBack();
                    return ResultWrapper::fail($autoCustomerMoney->getData(),$autoCustomerMoney->getErrorCode());
                }
            }
        }else{ // 从最老单子到最新单子的顺序依次核销
            // 核销应收单
            if (empty($receivedData['originId'])){
                $autoCustomerMoney = self::autoCustomerMoney($receivedData['customerId'],bcadd($receivedData['totalFinalMoney'],$receivedData['totalDiscountMoney'],2),$receivedData['id'],$receivedData['createTime'],$firstOffsetDate=[],0);
                if(!$autoCustomerMoney->isSuccess()){
                    $this->objDReceived->rollBack();
                    return ResultWrapper::fail($autoCustomerMoney->getData(),$autoCustomerMoney->getErrorCode());
                }
            }else{ //核销指定订单
                //查询应收表
                $dbResult = $this->objDReceiveReceiptIndex->get(['originId'=>$receivedData['originId']]);
                if ($dbResult === false) {
                    return ResultWrapper::fail($this->objDReceiveReceiptIndex->error(), ErrorCode::$dberror);
                }
                if(!empty($dbResult)){
                    //根据时间切表
                    $suffix = date('Y', $dbResult['createTime']) . '_' . ceil(date('m', $dbResult['createTime']) / 3);
                    $this->objDReceive->setTable('qianniao_receive_receipt_' . $this->enterpriseId . '_' . $suffix);
                    $receiveResult = $this->objDReceive->get(['id'=>$dbResult['id']]);
                    if ($receiveResult === false) {
                        return ResultWrapper::fail($this->objDReceive->error(), ErrorCode::$dberror);
                    }
                    //核销应收
                    switch (true){
                        case bcsub($receivedData['notOffsetMoney'],$receiveResult['notOffsetMoney'],2) == 0;
                            $receiveOffsetDate = [
                                'offsetMoney'=> bcadd($receiveResult['offsetMoney'],$receiveResult['notOffsetMoney'],2),
                                'notOffsetMoney'=> 0,
                                'offsetStatus'=> StatusCode::$standard,
                                'updateTime' => time()
                            ];
                            $receiveIndexOffsetDate = [
                                'offsetStatus' => StatusCode::$standard,
                                'updateTime' => time()
                            ];
                            $receivedOffsetDate = [
                                'offsetMoney'       => !empty($receivedData['offsetMoney']) ? $receivedData['totalFinalMoney'] : $receiveResult['notOffsetMoney'],
                                'notOffsetMoney'    =>0,
                                'offsetStatus'      =>StatusCode::$standard,
                                'updateTime' => time()
                            ];
                            break;
                        case bcsub($receivedData['notOffsetMoney'],$receiveResult['notOffsetMoney'],2) > 0;
                            $receiveOffsetDate = [
                                'offsetMoney'=> bcadd($receiveResult['offsetMoney'],$receiveResult['notOffsetMoney'],2),
                                'notOffsetMoney'=> 0,
                                'offsetStatus'=> StatusCode::$standard,
                                'updateTime' => time()
                            ];
                            $receiveIndexOffsetDate = [
                                'offsetStatus' => StatusCode::$standard,
                                'updateTime' => time()
                            ];
                            $receivedOffsetDate = [
                                'offsetMoney'       =>$receiveResult['notOffsetMoney'],
                                'notOffsetMoney'    =>bcsub($receivedData['notOffsetMoney'],$receiveResult['notOffsetMoney'],2),
                                'offsetStatus'      =>StatusCode::$partion,
                                'updateTime' => time()
                            ];
                            break;
                        case bcsub($receivedData['notOffsetMoney'],$receiveResult['notOffsetMoney'],2) < 0;
                            $receiveOffsetDate = [
                                'offsetMoney'=> bcadd($receiveResult['offsetMoney'],$receivedData['notOffsetMoney'],2),
                                'notOffsetMoney'=> bcsub($receiveResult['notOffsetMoney'],$receivedData['notOffsetMoney'],2),
                                'offsetStatus'=> StatusCode::$partion,
                                'updateTime' => time()
                            ];
                            $receiveIndexOffsetDate = [
                                'offsetStatus' => StatusCode::$partion,
                                'updateTime' => time()
                            ];
                            $receivedOffsetDate = [
                                'offsetMoney'       => empty($receivedData['offsetMoney']) ? $receivedData['totalFinalMoney'] :$receivedData['notOffsetMoney'],
                                'notOffsetMoney'    =>0,
                                'offsetStatus'      =>StatusCode::$standard,
                                'updateTime' => time()
                            ];
                    }
                    $updateOffsetStatus = $this->objDReceive->update($receiveOffsetDate,['id'=>$receiveResult['id']]);
                    if ($updateOffsetStatus === false) {
                        $this->objDReceive->rollBack();
                        return ResultWrapper::fail($this->objDReceive->error(), ErrorCode::$dberror);
                    }

                    $updateIndexOffsetStatus = $this->objDReceiveReceiptIndex->update($receiveIndexOffsetDate, ['id' => $receiveResult['id']]);
                    if ($updateIndexOffsetStatus === false) {
                        $this->objDReceive->rollBack();
                        return ResultWrapper::fail($this->objDReceiveReceiptIndex->error(), ErrorCode::$dberror);
                    }
                    //在线支付的收款单直接核销
                    $updateReceivedOffset = $this->objDReceived->update($receivedOffsetDate,['id'=>$receivedData['id']]);
                    if ($updateReceivedOffset === false) {
                        $this->objDReceive->rollBack();
                        return ResultWrapper::fail($this->objDReceived->error(), ErrorCode::$dberror);
                    }
                    // 记录核销明细
                    //核销完成,记录核销明细
                    $updateOffset = [
                        'receiveReceiptId' => $receiveResult['id'],
                        'receivedId' => $receivedData['id'],
                        'offsetMoney' => $receiveOffsetDate['offsetMoney'],
                        'receiveCreateTime' => $receiveResult['createTime'],
                        'type'  => StatusCode::$delete
                    ];
                    $result = $this->objDReceiveOffset->insert($updateOffset);
                    if ($result === false) {
                        $this->objDReceived->rollBack();
                        return ResultWrapper::fail($this->objDReceiveOffset->error(), ErrorCode::$dberror);
                    }
                }
            }
        }
      
        //更新客户总付款金额
        $result = $this->objMCustomerBalance->updateCustomerTotalPayMoney($receivedData['customerId'], $receivedData['totalFinalMoney']);
        if (!$result->isSuccess()) {
            $this->objDReceived->rollBack();
            return ResultWrapper::fail($result->getData(), $result->getErrorCode());
        }

        //给账户加钱
        $accounts = $this->objDReceivedAccount->select(['receivedId' => $receivedData['id']]);
        foreach ($accounts as $account) {
            //获取账户信息
            $accountResult = $this->objMAccount->getAccountInfo($account['accountId']);
            if (!$accountResult->isSuccess()) {
                $this->objDReceived->rollBack();
                return ResultWrapper::fail($accountResult->getData(), $accountResult->getErrorCode());
            }
            $accountInfo = $accountResult->getData();
            //账户明细
            $accountDetail = [
                'accountId'          => $accountInfo['id'],
                'accountCode'        => $accountInfo['accountCode'],
                'accountName'        => $accountInfo['name'],
                'accountNumber'      => $accountInfo['accountNumber'],
                'sourceId'           => $receivedData['id'],
                'sourceNo'           => $receivedData['no'],
                'financeType'        => $receivedData['financeType'],
                'beginBalance'       => $accountInfo['money'],
                'shopId'             => $receivedData['shopId'],
                'shopName'           => $receivedData['shopName'],
                'income'             => $receivedData['totalFinalMoney']>0 ? $receivedData['totalFinalMoney'] : 0,
                'expend'             => $receivedData['totalFinalMoney']<0 ? -1 * $receivedData['totalFinalMoney'] : 0,
                'endBalance'         => $accountInfo['money'] + $receivedData['totalFinalMoney'],
                'contactUnit'        => '客户名称:' . $receivedData['customerName'],
                'supplierId'         => 0,
                'customerId'         => $receivedData['customerId'],
                'operatorId'         => $this->userCenterId,
                'receiveOrPayPerson' => $receivedData['currentAccountName'],
                'remark'             => '收款单审核通过,本次收客户' . $receivedData['totalMoney'] . '元,优惠' . $receivedData['totalDiscountMoney'] . '元,最终收款' . $receivedData['totalFinalMoney'] . '元',
                'createTime'         => time(),
                'updateTime'         => time(),
            ];
            $result = $this->objMAccountDetail->addAccountDetail($accountDetail);
            if (!$result->isSuccess()) {
                $this->objDReceived->rollBack();
                return ResultWrapper::fail($result->getData(), $result->getErrorCode());
            }

            $result = $this->objMAccount->updateMoney($account['accountId'], $receivedData['totalFinalMoney']);
            if (!$result->isSuccess()) {
                $this->objDReceived->rollBack();
                return ResultWrapper::fail($result->getData(), $result->getErrorCode());
            }
        }

        //审核通过记录核销金额,未核销金额,核销状态。
       /* $objMReceive = new MReceive($this->enterpriseId, $this->userCenterId);

        if( !empty($offsetDbResult) ){
            foreach ($offsetDbResult as $key =>$value) {
//                //如果$customerBalance客户余额是负的,直接自动核销订单。
//                if ($customerBalance<0){
//                    $autoOffset = $objMReceive->autoOffset($customerBalance,$offsetDbResult[$key]['receiveReceiptId'],$offsetDbResult[$key]['receiveCreateTime']);
//                    if ($autoOffset->isSuccess() === false) {
//                        $this->objDReceived->rollBack();
//                        return ResultWrapper::fail($autoOffset->getData(), $autoOffset->getErrorCode());
//                    }
//                }else{
                    //修改应付单核销金额,索引表核销状态。
                    $updateOffsetDbResult = $objMReceive->updateOffsetStatus($offsetDbResult[$key]['receiveReceiptId'], $offsetDbResult[$key]['offsetMoney'], $offsetDbResult[$key]['receiveCreateTime']);
                    if ($updateOffsetDbResult->isSuccess() === false) {
                        $this->objDReceived->rollBack();
                        return ResultWrapper::fail($updateOffsetDbResult->getData(), $updateOffsetDbResult->getErrorCode());
                    }
//                }
            }
        }*/

        if ($beginTransactionStatus){
            $this->objDReceived->commit();
        }
        $objMOrder = new MOrder($this->userCenterId, $this->enterpriseId);
        //根据orderId修改订单状态
        if(!empty($receivedData['originId'])){
            //查询所有的收款
            $allReceivedMoney = 0;
            $allReceiveMoney = 0;
            unset($dbResult);
            $dbResult = $this->objDReceived->select(['originId' => $receivedData['originId']]);
            if ($dbResult === false) {
                return ResultWrapper::fail($this->objDReceived->error(), ErrorCode::$dberror);
            }
            foreach ($dbResult as $receivedKey => $receivedValue){
                $allReceivedMoney = bcadd($allReceivedMoney,$receivedValue['totalFinalMoney'],2);
            }
            unset($dbResult);
            //查询订单对应的应收
            $dbResult = $this->objDReceiveReceiptIndex->select(['originId'=>$receivedData['originId']]);
            foreach ($dbResult as $receiptIndexKey => $receiptIndexValue){
                $suffix = date('Y', $receiptIndexValue['createTime']) . '_' . ceil(date('m', $receiptIndexValue['createTime']) / 3);
                $this->objDReceive->setTable('qianniao_receive_receipt_' . $this->enterpriseId . '_' . $suffix);
                $objReceiveResult = $this->objDReceive->get(['id'=>$receiptIndexValue['id']]);
                if ($objReceiveResult === false) {
                    return ResultWrapper::fail($this->objDReceive->error(), ErrorCode::$dberror);
                }
                if(!empty($objReceiveResult)){
                    $allReceiveMoney = $objReceiveResult['offsetMoney'];
                }
            }

            //判断订单状态
            $orderTable = $objMOrder->getOrderTable($this->enterpriseId,$this->userCenterId);
            $objDOrder = new DOrder();
            $statusOrder =  $objDOrder->query('select * from '.$orderTable.' where id = '.$receivedData['originId']);
            if( bcsub(bcsub($allReceivedMoney,$allReceiveMoney,2),$statusOrder[0]['payAmount'],2) >= 0 ){//已支付
                $orderPayStatus = [
                    'payStatus' => StatusCode::$standard,
                    'payTime' => time()
                ];
            }else{
                $orderPayStatus = [
                    'payStatus' => StatusCode::$partion,
                    'payTime' => time()
                ];
            }

            $orderDbResult = $objMOrder->updateOrderPayData($orderPayStatus, ['id' => $receivedData['originId']]);
            if ($orderDbResult->isSuccess() === false) {
                return ResultWrapper::fail($orderDbResult->getData(), $orderDbResult->getErrorCode());
            }
        }else{
            //查询当前核销表
            unset($offsetDbResult);
            $offsetDbResult = $this->objDReceiveOffset->select(['receivedId'=>$receivedData['id'],'type'=>StatusCode::$standard]);
            if ($offsetDbResult === false) {
                return ResultWrapper::fail($this->objDReceiveOffset->error(), ErrorCode::$dberror);
            }
            //财务完成,修改订单表支付状态
            foreach ($offsetDbResult as $key =>$value) {
                //根据应付单获取orderId,用来修改订单支付状态
                $suffix = date('Y', $offsetDbResult[$key]['receiveCreateTime']) . '_' . ceil(date('m', $offsetDbResult[$key]['receiveCreateTime']) / 3);
                $this->objDReceive->setTable('qianniao_receive_receipt_' . $this->enterpriseId . '_' . $suffix);
                $orderIdDbResult = $this->objDReceive->get(['id' => $offsetDbResult[$key]['receiveReceiptId']]);
                if ($orderIdDbResult === false) {
                    return ResultWrapper::fail($this->objDReceive->error(), ErrorCode::$dberror);
                }
                if (empty($orderIdDbResult)) {
                    return ResultWrapper::fail('应付单不存在', ErrorCode::$notAllowAccess);
                }
                //判断核销金额,未核销金额,来计算payStatus的状态
                $updateOrderPayData1 = ['payStatus' => StatusCode::$standard, 'payTime' => time()];
                $updateOrderPayData2 = ['id' => $orderIdDbResult['originId']];
                switch (true) {
                    case $orderIdDbResult['offsetMoney'] == $orderIdDbResult['receiveMoney'];
                        $updateOrderPayData1['payStatus'] = StatusCode::$standard;
                        break;
                    case $orderIdDbResult['offsetMoney'] == 0;
                        $updateOrderPayData1['payStatus'] = StatusCode::$delete;
                        break;
                    case $orderIdDbResult['offsetMoney'] > 0 && $orderIdDbResult['offsetMoney'] < $orderIdDbResult['receiveMoney'];
                        $updateOrderPayData1['payStatus'] = StatusCode::$partion;
                        $updateOrderPayData1['notPayMoney'] = $orderIdDbResult['notOffsetMoney'];
                }
                $orderDbResult = $objMOrder->updateOrderPayData($updateOrderPayData1, $updateOrderPayData2);
                if ($orderDbResult->isSuccess() === false) {
                    return ResultWrapper::fail($orderDbResult->getData(), $orderDbResult->getErrorCode());
                }
            }
        }


        //今日收款金额redis
        $this->objOverviewCache->saveBusinessOverview($this->enterpriseId, 'todayReceivedMoney', $receivedData['totalFinalMoney']);
        $this->objOverviewCache->saveBusinessOverview($this->enterpriseId, 'todayReceivedMoney', $receivedData['totalFinalMoney'], $receivedData['shopId']);

        /*
        $_id = self::createEsDocumentId($receivedData['id'], $receivedData['createTime']);
        $this->objDReceived->esupdateTypeFieldVaule(['auditStatus' => StatusCode::$auditStatus['auditPass']], $_id);
        */
        return ResultWrapper::success($dbResult);
    }

    /**
     * 自动核销客户余额
     * 客户id,收款单总的money进行自动核销
     */
    public function autoCustomerMoney($customerId,$money,$id,$createTime,$firstOffset,$receiveReceiptId)
    {
        $ReceivedDbResult = $this->objDReceived->get($id);
        if ($ReceivedDbResult === false) {
            $this->objDReceived->rollBack();
            return ResultWrapper::fail($this->objDReceived->error(), ErrorCode::$dberror);
        }

        // 随便核销
        if ($receiveReceiptId == 0){
            // 查询这个客户所有未核销的应收单
            $sql = 'select * from ' . $this->objDReceiveReceiptIndex->get_Table() . ' where customerId='.$customerId.' and offsetStatus != '. StatusCode::$standard;
            $dbResultOffset = $this->objDReceiveReceiptIndex->query($sql);
        }else{ // 核销指定的应收单
            $sql = 'select * from ' . $this->objDReceiveReceiptIndex->get_Table() . ' where customerId='.$customerId.' and offsetStatus != '. StatusCode::$standard.' and id !='. $receiveReceiptId;
            $dbResultOffset = $this->objDReceiveReceiptIndex->query($sql);
        }
        $dbResultIndex = array_merge($firstOffset,$dbResultOffset);

        if ($dbResultIndex === false) {
            return ResultWrapper::fail($this->objDReceiveReceiptIndex->error(), ErrorCode::$dberror);
        }
        if(empty($dbResultIndex)){//如果为空,说明当前单子只做付款,预付,不做核销.
            return ResultWrapper::success([]);
        }

        $surplusMoney = $money; // 剩余可核销金额
        $receivedOffsetMoney = 0; // 收款单累计核销金额
        $receivedNotOffsetMoney = $money; // 收款单未核销金额
        foreach ($dbResultIndex as $key => $value){
            // 收款单钱核销完了,则不再进行核销
            if($surplusMoney <= 0){
                break;
            }

            // 切应收分表
            $suffix = date('Y', $value['createTime']) . '_' . ceil(date('m', $value['createTime']) / 3);
            $this->objDReceive->setTable('qianniao_receive_receipt_' . $this->enterpriseId . '_' . $suffix);

            // 查出当前应收单的信息
            $receiveDate = $this->objDReceive->get($value['id']);
            if ($receiveDate === false) {
                return ResultWrapper::fail($this->objDReceive->error(), ErrorCode::$dberror);
            }
            if(empty($receiveDate)){
                continue;
            }

            // 只核销金额大于0的,小于0是退款单
            if ($receiveDate['receiveMoney']<0) {
                continue;
            }

            switch (true) {
                case $receiveDate['notOffsetMoney'] <= $surplusMoney; // 未核销金额小于剩余可核销金额,整单核销
                    $offsetMoney = $receiveDate['notOffsetMoney'];
                    $notOffsetMoney = 0;
                    $offsetStatus = StatusCode::$standard;
                    $receivedOffsetMoney = bcadd($receivedOffsetMoney, $receiveDate['notOffsetMoney'], 2);
                    $receivedNotOffsetMoney = bcsub($receivedNotOffsetMoney, $receiveDate['notOffsetMoney'], 2);
                    $updateReceived = [
                        'offsetMoney' => $receivedOffsetMoney,
                        'notOffsetMoney' => $receivedNotOffsetMoney,
                        'offsetStatus' => ($receivedNotOffsetMoney ==0 ) ? StatusCode::$standard : StatusCode::$partion,
                    ];
                    $updateReceivedIndex = [
                        'offsetStatus' => ($receivedNotOffsetMoney ==0 ) ? StatusCode::$standard : StatusCode::$partion,
                    ];

                    break;
                case $receiveDate['notOffsetMoney'] > $surplusMoney;  // 未核销金额大于剩余可核销金额,部分核销
                    $offsetMoney = $surplusMoney;
                    $notOffsetMoney = bcsub($receiveDate['notOffsetMoney'], $offsetMoney, 2);
                    $offsetStatus = StatusCode::$partion;

                    $receivedOffsetMoney = bcadd($receivedOffsetMoney, $surplusMoney, 2);
                    $updateReceived = [
                        'offsetMoney' => $receivedOffsetMoney,
                        'notOffsetMoney' => 0,
                        'offsetStatus' => StatusCode::$standard,
                    ];
                    $updateReceivedIndex = [
                        'offsetStatus' => StatusCode::$standard,
                    ];
                    break;
            }
            $surplusMoney = bcsub($surplusMoney, $receiveDate['notOffsetMoney'], 2);
            //判断该单据是否已经审核

            if ($receiveDate['auditStatus'] == StatusCode:: $auditStatus['auditPass']) {
                $update = [
                    'offsetMoney' => bcadd($receiveDate['offsetMoney'],$offsetMoney),
                    'notOffsetMoney' => $notOffsetMoney,
                    'offsetStatus' => $offsetStatus,
                ];
            } else {
                $update = [
                    'offsetMoney' => bcadd($receiveDate['offsetMoney'],$offsetMoney),
                    'notOffsetMoney' => $notOffsetMoney,
                    'offsetStatus' => $offsetStatus,
                    'auditStatus' => StatusCode:: $auditStatus['auditPass']
                ];
            }
            //判断index单据是否已经审核
            if ($value['auditStatus'] == StatusCode:: $auditStatus['auditPass']) {
                $updateIndex = [
                    'offsetStatus' => $offsetStatus,
                ];
            } else {
                $updateIndex = [
                    'offsetStatus' => $offsetStatus,
                    'auditStatus' => StatusCode:: $auditStatus['auditPass']
                ];
            }

            $updateDReceive = $this->objDReceive->update($update, ['id' => $value['id']]);
            if ($updateDReceive === false) {
                $this->objDReceived->rollBack();
                return ResultWrapper::fail($this->objDReceive->error(), ErrorCode::$dberror);
            }
            $updateDReceiveReceiptIndex = $this->objDReceiveReceiptIndex->update($updateIndex, ['id' => $value['id']]);
            if ($updateDReceiveReceiptIndex === false) {
                $this->objDReceived->rollBack();
                return ResultWrapper::fail($this->objDReceive->error(), ErrorCode::$dberror);
            }
            //应收核销完成,记录核销信息
            $this->objDReceived->setTable('qianniao_received_' . $this->enterpriseId . '_' . date('Y', $createTime) . '_' . ceil(date('m', $createTime) / 3));
            $updateReceivedResult = $this->objDReceived->update($updateReceived, ['id' => $id]);
            if ($updateReceivedResult === false) {
                $this->objDReceived->rollBack();
                return ResultWrapper::fail($this->objDReceived->error(), ErrorCode::$dberror);
            }

            //核销完成更新index表的核销状态
            $updateReceivedIndexResult = $this->objDReceivedIndex->update($updateReceivedIndex, ['id' => $ReceivedDbResult['id'], 'receiptTime' => $ReceivedDbResult['receiptTime']]);
            if ($updateReceivedIndexResult === false) {
                $this->objDReceived->rollBack();
                return ResultWrapper::fail($this->objDReceivedIndex->error(), ErrorCode::$dberror);
            }
            //如果已经记过,需要剔除
            if (!empty($firstOffset) && count($firstOffset) - 1 >= $key) {//剔除
                continue;
            } else {
                //核销完成,记录核销明细
                $updateOffset = [
                    'receiveReceiptId' => $value['id'],
                    'receivedId' => $id,
                    'offsetMoney' => $offsetMoney,
                    'receiveCreateTime' => $value['createTime']
                ];
                $result = $this->objDReceiveOffset->insert($updateOffset);
                if ($result === false) {
                    $this->objDReceived->rollBack();
                    return ResultWrapper::fail($this->objDReceiveOffset->error(), ErrorCode::$dberror);
                }
            }

        }
        return ResultWrapper::success($updateDReceive);
    }

    /**
     * 获取所有收款单数据
     * @param array $selectParams 过滤条件
     * @return ResultWrapper
     * @throws \Exception
     */
    public function getAllReceived($selectParams,$export = 0)
    {
        $limit = $selectParams['limit'];
        unset($selectParams['limit']);
        $offset = $selectParams['offset'];
        unset($selectParams['offset']);
        if($export){
            $limit = 999;
            $offset = 0;
        }
        //组装sql where条件
        $whereSql = ' where deleteStatus = '.StatusCode::$standard;
        if (isset($selectParams['no']) && !empty($selectParams['no'])) {
            //no编号切割
            $explodeNo = explode("-",$selectParams['no']);
            $where = empty($whereSql) ? ' WHERE ' : ' AND ';
            $whereSql .= $where . ' no = "' . $explodeNo[1] . '-' . $explodeNo[2] . '"';
        }
        if (isset($selectParams['financeTypeId']) && !empty($selectParams['financeTypeId'])) {
            $where = empty($whereSql) ? ' WHERE ' : ' AND ';
            $whereSql .= $where . ' financeTypeId = ' . $selectParams['financeTypeId'];
        }
        if (isset($selectParams['auditStatus']) && !empty($selectParams['auditStatus'])) {
            $where = empty($whereSql) ? ' WHERE ' : ' AND ';
            $whereSql .= $where . ' auditStatus = ' . $selectParams['auditStatus'];
        }
        if (isset($selectParams['customerId']) && !empty($selectParams['customerId'])) {
            $where = empty($whereSql) ? ' WHERE ' : ' AND ';
            $whereSql .= $where . ' customerId = ' . $selectParams['customerId'];
        }
        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->objDReceivedIndex->get_Table(). $whereSql . ' ORDER BY createTime DESC LIMIT ' . $offset . ' , ' . $limit;
        $receivedIndexResult = $this->objDReceivedIndex->query($sql);
        $tableSuffix = [];
        foreach ($receivedIndexResult as $receivedIndex) {
            $k = date('Y', $receivedIndex['createTime']) . '_' . ceil(date('m', $receivedIndex['createTime']) / 3);
            $tableSuffix[$k][] = $receivedIndex['id'];
        }

        $receivedResult = [];
        foreach ($tableSuffix as $suffix => $receivedIds) {
            $this->objDReceived->setTable('qianniao_received_' . $this->enterpriseId . '_' . $suffix);
            $dbResult = $this->objDReceived->select($receivedIds, '*', 'createTime desc');
            if ($dbResult === false) {
                return ResultWrapper::fail($this->objDReceived->error(), ErrorCode::$dberror);
            }
            if (!empty($dbResult)){
                //渲染前缀
                foreach ($dbResult as $key => $value){
                    $dbResult[$key]['no'] = StatusCode::$noPrefix[17] . '-' . $value['no'];
                    if(!empty($value['sourceNo'])){
                        $dbResult[$key]['sourceNo'] = StatusCode::$noPrefix[1] . '-' . $value['sourceNo'];
                    }
                    $dbResult[$key]['extends'] = json_decode($dbResult[$key]['extends'],true);
                }
            }
            $receivedResult = array_merge($receivedResult, $dbResult);
        }

        $totalSql = 'SELECT COUNT(1) as count FROM ' .$this->objDReceivedIndex->get_Table() . $whereSql;
        $dbTotalResult = $this->objDReceivedIndex->query($totalSql);
        if ($dbTotalResult === false) {
            return ResultWrapper::fail($this->objDReceivedIndex->error(), ErrorCode::$dberror);
        }
        if(empty($dbTotalResult)){
            return ResultWrapper::success([]);
        }
        $return = [
            'data'  => self::format($receivedResult),
            'total' => $dbTotalResult[0]['count']
        ];
        //导出
        if($export){
            self::exportReceived($return['data']);
            exit;
        }
      
        return ResultWrapper::success($return);

    }

    public function format($data)
    {
        $financeTypeIds = [];
        foreach ($data as $key => $received) {
            $financeTypeIds[] = $received['financeTypeId'];
        }

        $financeTypeArr = [];
        if ($financeTypeIds) {
            $financeTypeResult = $this->objMFinanceType->getAllFinanceTypeNoPage(['id'=>array_unique(array_filter($financeTypeIds))]);
            if ($financeTypeResult->isSuccess()) {
                $financeTypeData = $financeTypeResult->getData();
                if (!empty($financeTypeData)) {
                    foreach ($financeTypeData as $financeType) {
                        $financeTypeArr[$financeType['id']] = $financeType['name'];
                    }
                }
            }
        }

        foreach ($data as $key => &$received) {
            $received['financeType'] = isset($financeTypeArr[$received['financeTypeId']]) ? $financeTypeArr[$received['financeTypeId']] : $received['financeType'];
        }

        return $data;
    }

    //搜索的where条件拼接
    public function setWhere($selectParams)
    {
        $defaultDSL = [
            'from' => $selectParams['offset'],
            'size' => $selectParams['limit'],
            'sort' => [
                'createTime' => [
                    'order' => 'desc'
                ],
            ],
        ];

        $dsl = [];
        $dsl['query']['bool']['must'][] = [
            'term' => ['enterpriseId' => $this->enterpriseId],
        ];

        if (isset($selectParams['keyword'])) {
            if (!empty($selectParams['keyword'])) {
                $dsl['query']['bool']['must'][] = [
                    'multi_match' => [
                        'fields'    => ['no', 'sourceNo', 'currentAccountName'],
                        'query'     => $selectParams['keyword'],
                        'fuzziness' => 'AUTO',
                    ]
                ];
            }
        }

        if (!empty($selectParams['start']) && !empty($selectParams['end'])) {
            $dsl['query']['bool']['must'][] = [
                'range' => [
                    'receiptTime' => [
                        'gte' => $selectParams['start'],
                        'lte' => strtotime(date('Y-m-d', $selectParams['end']) . '23:59:59'),
                    ]
                ]
            ];
        } else {
            if (!empty($selectParams['start'])) {
                $dsl['query']['bool']['must'][] = [
                    'range' => [
                        'receiptTime' => [
                            'gte' => $selectParams['start'],
                        ]
                    ]
                ];
            }

            if (!empty($selectParams['end'])) {
                $dsl['query']['bool']['must'][] = [
                    'range' => [
                        'receiptTime' => [
                            'lte' => strtotime(date('Y-m-d', $selectParams['end']) . '23:59:59'),
                        ]
                    ]
                ];
            }
        }

        if (isset($selectParams['customerId'])) {
            if (!empty($selectParams['customerId'])) {
                $dsl['query']['bool']['filter'][] =
                    ['term' => ['customerId' => $selectParams['customerId']]];
            }
        }

        if (isset($selectParams['auditStatus'])) {
            if (!empty($selectParams['auditStatus'])) {
                $dsl['query']['bool']['filter'][] =
                    ['term' => ['auditStatus' => $selectParams['auditStatus']]];
            }
        }

        if (isset($selectParams['financeTypeId'])) {
            if (!empty($selectParams['financeTypeId'])) {
                $dsl['query']['bool']['filter'][] =
                    ['term' => ['financeTypeId' => $selectParams['financeTypeId']]];
            }
        }

        $dsl = array_merge($defaultDSL, $dsl);
        return $dsl;
    }

//    public function search($selectParams)
//    {
//        $dsl = $this->setWhere($selectParams);
//        $result = $this->objDReceived->getSearchQueryDsl($dsl);
//
//        if (isset($result['status']) && $result['status'] == 400) {
//            if ($result['error']['reason'] == 'all shards failed') {
//                return ResultWrapper::success([
//                    'data'  => [],
//                    'total' => 0
//                ]);
//            }
//            return ResultWrapper::fail('获取应收数据失败' . $result['error']['reason'], ErrorCode::$apiNotResult);
//        }
//
//        if (!isset($result['hits']) || $result['hits']['total'] == 0) {
//            return ResultWrapper::success([
//                'data'  => [],
//                'total' => 0
//            ]);
//        }
//        $total = $result['hits']['total'];
//        $dbResult = $result['hits']['hits'];
//
//        $list = [];
//        foreach ($dbResult as $key => &$value) {
//            $data = [];
//            $data = $value['_source'];
//            $list[] = $data;
//        }
//
//        $return = [
//            'data'  => $list,
//            'total' => ($total) ? intval($total) : 0,
//        ];
//        return ResultWrapper::success($return);
//    }

    /**
     * 根据订单no查询应收单
     * @param $params
     * @return ResultWrapper
     * @throws \Exception
     */
    public function getReceivedByOrder($params)
    {
        $this->objDReceiveReceiptIndex->setTable('qianniao_receive_receipt_index_'.$this->enterpriseId);
        $dbResult = $this->objDReceiveReceiptIndex->select($params);
        if ($dbResult === false) {
            return ResultWrapper::fail($this->objDReceiveReceiptIndex->error(), ErrorCode::$dberror);
        }
        if(empty($dbResult)){
            return ResultWrapper::success($dbResult);
        }
        $receiveReceiptIndex = array_shift($dbResult);
        unset($dbResult);
        $tableName = 'qianniao_receive_receipt_'.$this->enterpriseId.'_'.date('Y', $receiveReceiptIndex['createTime']) . '_' . ceil(date('m', $receiveReceiptIndex['createTime']) / 3);
        $sql = 'select * from '.$tableName.' where id = '.$receiveReceiptIndex['id'];
        $dbResult = $this->objDReceiveReceiptIndex->query($sql);
        if($dbResult === false){
            return ResultWrapper::fail($this->objDReceiveReceiptIndex->error(), ErrorCode::$dberror);
        }
        $receiveReceipt = !empty($dbResult) ? array_shift($dbResult) : $dbResult;
        return ResultWrapper::success($receiveReceipt);
    }
    /**
     * 获取今日收款总额
     * @param null $shopId
     * @return ResultWrapper
     */
    public function getTodayReceivedMoney($shopId = null)
    {
        $result = $this->objOverviewCache->getBusinessOverview($this->enterpriseId, 'todayReceivedMoney', $shopId);
        //TODO:拿不到数据去ES筛选
        return $result ? $result : 0;
    }
    
    /**
     * 导出方法
     *
     * @param $receivedData
     */
    private static function exportReceived($receivedData)
    {
        //导出到本地
        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 ($receivedData as $v) {
            //循环数据
            $num++;
            if ($num == $limit) {
                ob_flush();//释放内存
                flush();
            }
            $rows['no'] = isset($v['no']) ? $v['no'] : '';//单据号
            $rows['sourceNo'] = isset($v['sourceNo']) ? $v['sourceNo'] : '';//原单据号
            $rows['createTime'] = isset($v['createTime']) ? date('Y-m-d H:i:s',$v['createTime']) : '';//单据日期
            $rows['customerName'] = isset($v['customerName']) ? $v['customerName'] : '';//客户
            $rows['financeType'] = isset($v['financeType']) ? $v['financeType'] : '';//收购款类型
            $rows['totalMoney'] = isset($v['totalMoney']) ? $v['totalMoney'] : '';//金额
            $rows['totalDiscountMoney'] = isset($v['totalDiscountMoney']) ? $v['totalDiscountMoney'] : '';//优惠金额
            $rows['totalFinalMoney'] = isset($v['totalFinalMoney']) ? $v['totalFinalMoney'] : '';//实收金额
            $rows['shopName'] = isset($v['shopName']) ? $v['shopName'] : '';//相关店铺
            $rows['auditStatus'] = $v['auditStatus'] === 1 ? '待审核' : '审核通过';//审核状态
     
            foreach ($rows as $kk => $vv) {
                $rs[$kk] = mb_convert_encoding($vv, 'GBK', 'utf-8');  //转译编码
            }
            fputcsv($fp, $rs);
            $rows = [];
        }
        exit;
    }


    /**
     * 收款查询核销记录
     */
    public function getAllReceivedOffset($params)
    {
        $receivedId = $params['receivedId'];

        $dbResult = $this->objDReceiveOffset->select(['receivedId'=>$receivedId]);
        if($dbResult === false){
            return ResultWrapper::fail($this->objDReceiveOffset->error(), ErrorCode::$dberror);
        }
        if(empty($dbResult)){
            return ResultWrapper::success([]);
        }

        foreach ($dbResult as $key => $value){
            $suffix = date('Y', $value['receiveCreateTime']) . '_' . ceil(date('m', $value['receiveCreateTime']) / 3);
            $this->objDReceive->setTable('qianniao_receive_receipt_' . $this->enterpriseId . '_' . $suffix);

            $this->objDReceived->setTable('qianniao_received_' . $this->enterpriseId . '_' . date('Y', $value['createTime']) . '_' . ceil(date('m', $value['createTime']) / 3));
            //查询应收
            $receiveDate = $this->objDReceive->get($value['receiveReceiptId']);
            if($receiveDate === false){
                return ResultWrapper::fail($this->objDReceive->error(), ErrorCode::$dberror);
            }
            //查询收款
            $receivedDate = $this->objDReceived->get($value['receivedId']);
            if($receiveDate === false){
                return ResultWrapper::fail($this->objDReceive->error(), ErrorCode::$dberror);
            }
            if(!empty($receiveDate)){
                $dbResult[$key]['receiveId'] = $value['receiveReceiptId'];
                $dbResult[$key]['no'] = StatusCode::$noPrefix[16].'-'.$receiveDate['no'];
                $dbResult[$key]['offsetMoney'] = $value['offsetMoney'];
                $dbResult[$key]['notOffsetMoney'] = $receiveDate['notOffsetMoney'];
                $dbResult[$key]['money'] = $receivedDate['totalFinalMoney'];
                $dbResult[$key]['originId'] = $receiveDate['originId'];
                $dbResult[$key]['originNo'] = StatusCode::$noPrefix[1].'-'.$receiveDate['originNo'];
                $dbResult[$key]['customerName'] = $receiveDate['customerName'];
                $dbResult[$key]['customerId'] = $receiveDate['customerId'];
            }
        }
        return ResultWrapper::success($dbResult);

    }


}