<?php

/**
 * @desc 业务应收处理类
 */
class Process_BusinessIncome
{
    protected $_date = "";
    protected $_userId = "";
    protected $_bb_id = ""; //业务ID
    protected $_businessArr = array();

    public function __construct()
    {
        $this->_userId = Service_User::getUserId();
        $this->_date = date('Y-m-d H:i:s');
    }


    /**
     * @desc 重新计费 事务处理
     * @param array $param array("refer_code","createType","ds_code","rp_type"=>收付类型 0:只处理应收 1:同时处理实付)
     * @return array
     */
    public function readjustmentTransaction($param = array(), $selfweight=0)
    {
        $result = array("state" => 0, "message" => "", "code" => '');
        $result['code'] = isset($param['refer_code']) ? $param['refer_code'] : '';
        $db = Common_Common::getAdapter();
        $db->beginTransaction();
        try {
            //根据类型处理
            switch (strtolower($param['ds_code'])) {
                case 'so':
                    $this->readjustmentForOrder($param,$selfweight);
                    break;
                case 'lo':
                    $this->readjustmentForOutsideOrder($param,$selfweight);
                    break;
                case 'asn':
                    //后续补全
                    throw new Exception("此业务类型不支持重新计费");
                    break;
                default:
                    throw new Exception("此业务类型不支持重新计费");
                    break;

            }
            $db->commit();
            //$db->rollBack();
            $result['state'] = 1;
            $result['message'] = '操作成功';
        } catch (Exception $e) {
            $db->rollBack();
            $result['state'] = 0;
            $result['message'] = $e->getMessage();
        }
        return $result;
    }


    /**
     * @desc 订单 重新计费
     * @param array $param
     * @throws Exception
     */
    public function readjustmentForOrder($param = array(), $selfweight)
    {
        //参数
        $code = isset($param['refer_code']) ? $param['refer_code'] : '0';
        $createType = isset($param['createType']) ? $param['createType'] : '0';
        $rpType = isset($param['rp_type']) ? $param['rp_type'] : '0'; // 收付类型

        $businessArr = Service_BilBusiness::getAttrByRefCode($code);
        if(empty($businessArr)){
            throw new Exception("业务订单数据不存在");
        }
        if (strtolower($businessArr['ds_code']) != 'so') {
            throw new Exception("业务必须为订单");
        }

        if (strtolower($businessArr['bb_status']) == 'n') {
            throw new Exception("此业务费用已作废,不允许操作");
        }
        
        //重量未更新，无须重新计费
        $aShipOrder = Service_ShipOrder::getByField($businessArr['bb_refer_code'], 'order_code');
        if($selfweight == '1'){
            //根据仓库自己计费重量重新计算
            //$aShipOrder['so_service_provider_weight'] = $aShipOrder['so_weight'];
            if(empty($aShipOrder['so_service_provider_weight'])){
                $aShipOrder['so_service_provider_weight'] = $aShipOrder['so_service_provider_weight'] > $aShipOrder['so_weight'] ? $aShipOrder['so_service_provider_weight'] : $aShipOrder['so_weight'];
            }
        }else{
            if($aShipOrder['so_service_provider_weight'] <= $aShipOrder['so_weight']){
                throw new Exception('订单'.$businessArr['bb_refer_code'].'服务商重量未更新，无须重新计费');
            }
        }
        
        //删除数据
        $create_type_arr = $createType == '0' ? array(0) : array(0, 1);
        $iCondition = array(
            'bb_id' => $businessArr['bb_id'],
            'bi_status_arr' => array(2, 3), //考虑到可能部分已出帐的问题
            'bi_create_type_arr' => $create_type_arr,
            'bi_return_sign' => 'n', //未回退过
        );
        $customerRow = Service_Customer::getByField($businessArr['customer_code'], 'customer_code', array('customer_code', 'customer_id', 'customer_currency'));

        //费用集合
        $feeArr = array();
        $iRows = Service_BilIncome::getByCondition($iCondition, '*', 0, 0);
        $apr_amount = 0;
        if (!empty($iRows)) {
            foreach ($iRows as $iRow) {
                //$feeTypeRow = Service_FeeType::getByField($iRow['ft_code'], 'ft_code');
                $feeTypeRow = Service_OtherFee::getByField($iRow['ft_code'], 'fee_code');
                if(empty($feeTypeRow)){
                    $fee_id = Service_OtherFee::getFeeId($iRow['ft_code'],$aShipOrder['so_weight']);
                    $feeTypeRow['fee_id'] = $fee_id;
                }
                switch ($iRow['bi_status']) {
                    case '2':
                        $feeArr[] = array(
                            'cbl_type' => $iRow['bi_rp_type'] == '0' ? 3 : 2, //反向退回
                            'cbl_value' => abs($iRow['bi_amount']),
                            'currency_code' => $customerRow['customer_currency'],
                            'release_value' => '0',
                            'currency_rate' => '',
                            'user_id' => $this->_userId,
                            'cbl_refer_code' => $businessArr['bb_refer_code'],
                            'application_code' => 'readjustment',
                            'fee_id' => $feeTypeRow['fee_id'],
                            'cbl_note' => '费用调整，回退费用'
                        );
                        //删除
                        Service_BilIncome::delete($iRow['bi_id'], 'bi_id');
                        break;
                    case '3':
                        //针对退回已出帐应收，插入收款记录抵销上次核销记录
                        if ($iRow['bi_return_sign'] == 'n') {
                            $apr_amount += $iRow['bi_amount'];
                            Service_BilIncome::update(array('bi_return_sign' => 'y', 'bi_update_time' => $this->_date), $iRow['bi_id'], 'bi_id');
                        }
                        break;
                }
            }
            //回退
            if (!empty($feeArr)) {
                $feeObj = new Common_CustomerFeeProcess();
                $feeReturn = $feeObj->payment($businessArr['customer_code'], $feeArr, 1); //强制扣款
                if ($feeReturn['state'] != '1') {
                    throw new Exception(isset($feeReturn['message']) ? $feeReturn['message'] : 'Payment Fee Fail.');
                }
            }
            //针对退回已出帐应收，插入收款记录抵销上次核销记录
            if (abs($apr_amount)) {
                $cArr = Service_Currency::getByField($customerRow['customer_currency'], 'currency_code', array("currency_rate"));
                $addArr = array(
                    'apr_type' => $apr_amount > 0 ? 1 : 2,
                    'payer_code' => $businessArr['customer_code'],
                    'so_code' => 'cm',
                    'pm_code' => '',
                    'apr_transaction_no' => $businessArr['bb_refer_code'],
                    'ba_id' => 0,
                    'ftr_id' => 0,
                    'apr_amount' => abs($apr_amount),
                    'apr_currency_code' => $customerRow['customer_currency'],
                    'apr_settle_sign' => 'y',
                    'apr_inneroffset_sign' => 'y', //用于内部核销
                    'apr_currency_rate' => $cArr['currency_rate'],
                    'apr_note' => '重新计费,回退费用',
                    'apr_creator_id' => $this->_userId,
                    'bill_id' => '',
                    'apr_create_type' => 0,
                    'apr_transaction_time' => $this->_date,
                    'apr_add_time' => $this->_date,
                    'apr_update_time' => $this->_date,
                );
                if (!Service_AccountPaymentRecords::add($addArr)) {
                    throw new Exception("写入收款数据错误");
                }
                //自动抵消
                if ($addArr['apr_type'] == '2') {
                    Process_Financial::accountInternalBalance($businessArr['customer_code'], 'cm');
                }
            }
        }
        //重新计费
        if($aShipOrder['so_service_provider_weight']>0){
            $realWeight = $aShipOrder['so_service_provider_weight'] > $aShipOrder['so_weight'] ? $aShipOrder['so_service_provider_weight'] : $aShipOrder['so_weight'];
        $realWeight = ($realWeight > $aShipOrder['so_vol_weight']) ? $realWeight : $aShipOrder['so_vol_weight'];
        }else {
            //$realWeight = $aShipOrder['so_service_provider_weight'];
            $realWeight = $aShipOrder['so_service_provider_weight'] > $aShipOrder['so_weight'] ? $aShipOrder['so_service_provider_weight'] : $aShipOrder['so_weight'];
            $realWeight = ($realWeight > $aShipOrder['so_vol_weight']) ? $realWeight : $aShipOrder['so_vol_weight'];
        }
        /*
        $volArr = array(
            'realWeight' => $realWeight,
            'weight'=>$aShipOrder['so_weight'],//以实重计算的
            'length' => $aShipOrder['so_length'],
            'width' => $aShipOrder['so_width'],
            'height' => $aShipOrder['so_height'],
        );
        */
        
        $volArr = array();
		$volArr['volArr'][] = array(
				'weight'=>$aShipOrder['so_weight'],//以实重计算的
				'length' => $aShipOrder['so_length'],
				'width' => $aShipOrder['so_width'],
				'height' => $aShipOrder['so_height']
		);
		$volArr['realWeight'] = $realWeight;
		
        $result = Service_ShipOrderProcess::shipFee($businessArr['bb_refer_code'], $volArr, 1, 1);
        if($result!==true){
            throw new Exception($result);
        }
    }


    /**
     * @desc 全部重新计费
     */
    public function batchReadjustmentIncome($condition = array())
    {
        $result = array('success' => 0, 'fail' => 0, 'params' => array());
        $condition['bi_status'] = 2;
        $condition['bi_create_type'] = '0';
        $condition['ds_code_arr'] = array('so','lo');
        $successCnt = 0;
        $failCnt = 0;

        $total = Table_BilIncome::getInstance()->getGroupByCondition($condition, "count(*)");

        $loop = 0;
        $pageSize = 200; //每次三百,遍历处理
        $pageCount = ceil($total / $pageSize);

        $obj = new Process_BusinessIncome();
        while ($loop < $pageCount) {
            $loop++;
            $rows = Table_BilIncome::getInstance()->getGroupByCondition($condition, array('bil_business_attach.bb_refer_code', 'bil_business.ds_code'), $pageSize, 1);
            foreach ($rows as $row) {
                $param = array(
                    'refer_code' => $row['bb_refer_code'],
                    'ds_code' => $row['ds_code'],
                );
                $result1 = $obj->readjustmentTransaction($param);
                if (isset($result1['state']) && $result1['state'] == '1') {
                    $successCnt++;
                } else {
                    $failCnt++;
                    $result['message'] = $result1['message'];
                }
            }
        }
        $result['success'] = $successCnt;
        $result['fail'] = $failCnt;
        $result['params'] = $condition;
        return $result;
    }

    /**
     * @desc 区外仓订单 重新计费
     * @param array $param
     * @throws Exception
     * TODO......
     */
    public function readjustmentForOutsideOrder($param = array())
    {
        //参数
        $code = isset($param['refer_code']) ? $param['refer_code'] : '0';
        $createType = isset($param['createType']) ? $param['createType'] : '0';
        $rpType = isset($param['rp_type']) ? $param['rp_type'] : '0'; // 收付类型

        $businessArr = Service_BilBusiness::getAttrByRefCode($code);

        if (strtolower($businessArr['ds_code']) != 'lo') {
            throw new Exception("业务必须为区外仓订单");
        }

        if (strtolower($businessArr['bb_status']) == 'n') {
            throw new Exception("此业务费用已作废,不允许操作");
        }

        //重量未更新，无须重新计费
        $aLoOrder = Service_ReceivingBatchOrder::getByField($businessArr['bb_refer_code'], 'logistics_code');
        if($aLoOrder['lo_service_provider_weight'] <= $aLoOrder['weight']){
            throw new Exception('订单'.$businessArr['bb_refer_code'].'服务商重量未更新，无须重新计费');
        }

        //删除数据
        $create_type_arr = $createType == '0' ? array(0) : array(0, 1);
        $iCondition = array(
            'bb_id' => $businessArr['bb_id'],
            'bi_status_arr' => array(2, 3), //考虑到可能部分已出帐的问题
            'bi_create_type_arr' => $create_type_arr,
            'bi_return_sign' => 'n', //未回退过
        );
        $customerRow = Service_Customer::getByField($businessArr['customer_code'], 'customer_code', array('customer_code', 'customer_id', 'customer_currency'));

        //费用集合
        $feeArr = array();
        $iRows = Service_BilIncome::getByCondition($iCondition, '*', 0, 0);
        $apr_amount = 0;
        if (!empty($iRows)) {
            foreach ($iRows as $iRow) {
                $feeTypeRow = Service_FeeType::getByField($iRow['ft_code'], 'ft_code');
                if(empty($feeTypeRow)){
                    $feeTypeRow['fee_id'] = 0;
                }
                switch ($iRow['bi_status']) {
                    case '2':
                        $feeArr[] = array(
                            'cbl_type' => $iRow['bi_rp_type'] == '0' ? 3 : 2, //反向退回
                            'cbl_value' => abs($iRow['bi_amount']),
                            'currency_code' => $customerRow['customer_currency'],
                            'release_value' => '0',
                            'currency_rate' => '',
                            'user_id' => $this->_userId,
                            'cbl_refer_code' => $businessArr['bb_refer_code'],
                            'application_code' => 'readjustment',
                            'fee_id' => $feeTypeRow['fee_id'],
                            'cbl_note' => '费用调整，回退费用'
                        );
                        //删除
                        Service_BilIncome::delete($iRow['bi_id'], 'bi_id');
                        break;
                    case '3':
                        //针对退回已出帐应收，插入收款记录抵销上次核销记录
                        if ($iRow['bi_return_sign'] == 'n') {
                            $apr_amount += $iRow['bi_amount'];
                            Service_BilIncome::update(array('bi_return_sign' => 'y', 'bi_update_time' => $this->_date), $iRow['bi_id'], 'bi_id');
                        }
                        break;
                }
            }
            //回退
            if (!empty($feeArr)) {
                $feeObj = new Common_CustomerFeeProcess();
                $feeReturn = $feeObj->payment($businessArr['customer_code'], $feeArr, 1); //强制扣款
                if ($feeReturn['state'] != '1') {
                    throw new Exception(isset($feeReturn['message']) ? $feeReturn['message'] : 'Payment Fee Fail.');
                }
            }
            //针对退回已出帐应收，插入收款记录抵销上次核销记录
            if (abs($apr_amount)) {
                $cArr = Service_Currency::getByField($customerRow['customer_currency'], 'currency_code', array("currency_rate"));
                $addArr = array(
                    'apr_type' => $apr_amount > 0 ? 1 : 2,
                    'payer_code' => $businessArr['customer_code'],
                    'so_code' => 'cm',
                    'pm_code' => '',
                    'apr_transaction_no' => $businessArr['bb_refer_code'],
                    'ba_id' => 0,
                    'ftr_id' => 0,
                    'apr_amount' => abs($apr_amount),
                    'apr_currency_code' => $customerRow['customer_currency'],
                    'apr_settle_sign' => 'y',
                    'apr_inneroffset_sign' => 'y', //用于内部核销
                    'apr_currency_rate' => $cArr['currency_rate'],
                    'apr_note' => '重新计费,回退费用',
                    'apr_creator_id' => $this->_userId,
                    'bill_id' => '',
                    'apr_create_type' => 0,
                    'apr_transaction_time' => $this->_date,
                    'apr_add_time' => $this->_date,
                    'apr_update_time' => $this->_date,
                );
                if (!Service_AccountPaymentRecords::add($addArr)) {
                    throw new Exception("写入收款数据错误");
                }
                //自动抵消
                if ($addArr['apr_type'] == '2') {
                    Process_Financial::accountInternalBalance($businessArr['customer_code'], 'cm');
                }
            }
        }
        //重新计费
        $realWeight = ($aLoOrder['lo_service_provider_weight'] > $aLoOrder['weight'])? $aLoOrder['lo_service_provider_weight'] : $aLoOrder['weight'];
        Service_ShipOrderProcess::shipLogisticsFee($businessArr['bb_refer_code'], $customerRow['customer_id'], $realWeight, '', 1);
    }

}