<?php

/**
 * @desc 业务处理类
 */
class Process_BusinessPayment
{
    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 服务商非逻辑，当业务产生新应收费用时，是否需要审核
     * @return int 0:不需要审核  1:需要审核
     */
    public static function incomeFeeConfig()
    {
        return 0;
    }


    /**
     * @desc 服务商非逻辑，当业务产生新应付费用时，是否需要审核
     * @return int 0:不需要审核  1:需要审核
     */
    public static function paymentFeeConfig()
    {
        return 1;
    }

    /**
     * @desc 服务商非逻辑费用，什么状态下费用可编辑、删除
     * @return array
     */
    public static function editBusinessPaymentFeeConfig()
    {
        return array(1);
    }

    /**
     * @desc 获取业务单号
     * @param string $code
     * @return string
     */
    public static function getBusinessReferNo($code = '')
    {
        return Common_GetNumber::getCode('VIRTUAL_BUSINESS', $code, 'VF');
    }

    /**
     * @param $param
     * @return mixed
     * @throws Exception
     */
    private function editBusinessFeeValidation($param)
    {
        if (!isset($param['sp_code']) || $param['sp_code'] == '') {
            throw new Exception("服务商代码不能为空");
        }
        if ($param['amount'] == '' || !is_numeric($param['amount']) || $param['amount'] <= 0) {
            throw new Exception("金额异常");
        }
        if ($param['currency_code'] == '') {
            throw new Exception("币种不能为空");
        }
        if (!in_array($param['rp_type'], array('0', '1'))) {
            throw new Exception("收付类型异常");
        }
        return $param;
    }

    /**
     * @desc 新增(编辑)业务费用(非逻辑) \\ 不影响余额
     * @param array $param
     * @return array
     */
    public function editBusinessFeeTransaction($param = array())
    {
        $result = array("state" => 0, "message" => "", "data" => array());

        $db = Common_Common::getAdapter();
        $db->beginTransaction();
        try {
            $this->editBusinessFeeValidation($param);

            $spCode = $param['sp_code'];
            $type = $param['rp_type'];
            $amount = abs($param['amount']);
            $currency_code = $param['currency_code'];
            $note = $param['note'];
            $bp_id = $param['bp_id'];
            $bt_code = $param['bt_code'];
            $charge_time = (!isset($param['charge_time']) || empty($param['charge_time']) ? $this->_date : $param['charge_time']);

            $row = Service_ServiceProvider::getByField($spCode, 'sp_code');
            if (empty($row)) {
                throw new Exception("服务商代码：" . $spCode . "不存在");
            }

            //编辑时
            if (!empty($bp_id)) {
                $bilPaymentRow = Service_BilPayment::getByField($bp_id, 'bp_id');
                if (empty($bilPaymentRow)) {
                    throw new Exception("没有找到匹配的数据");
                } elseif (!in_array($bilPaymentRow['bp_status'], self::editBusinessPaymentFeeConfig())) {
                    $bilPaymentStatusArr = Process_BillConfig::bilPaymentStatus('auto');
                    throw new Exception("状态为[" . $bilPaymentStatusArr[$bilPaymentRow['bp_status']] . '],不允许操作');
                }
                //更新业务表
                $businessForUp = array();
                $businessArr = Service_BilBusiness::getAttrByField($bilPaymentRow['bb_id'], 'bb_id');
                if (strtolower($businessArr['bb_status']) == 'n') {
                    throw new Exception("此业务费用已作废,不允许操作");
                }
                $businessForUp['bb_charge_time'] = $charge_time;
                $businessForUp['bb_declared_time'] = $charge_time;
                if (strtolower($businessArr['bt_code']) != strtolower($bt_code)) {
                    $businessForUp['bt_code'] = strtoupper($bt_code);
                }

                $code = $businessArr['bb_refer_code'];

                //转为服务商币种
                $cArr = Process_Financial::changeCurrency($amount, $currency_code, $row['currency_code']);
                if (!is_array($cArr)) {
                    throw new Exception($cArr);
                }

                //应付表更新
                $biUpArr = array(
                    'bp_amount' => ($type == '1' ? $cArr['value'] : $cArr['value'] * -1),
                    'currency_code' => $currency_code, //原币种
                    'currency_rate' => $cArr['org_rate'], //原币种汇率
                    'bp_rp_type' => $type,
                    'bp_note' => $note,
                    'bp_withdraw_sign' => 'n', //是否回退
                    'bp_update_time' => $this->_date,
                    'bp_chargeable_time' => $charge_time,
                );
                Service_BilPayment::update($biUpArr, $bilPaymentRow['bp_id'], 'bp_id');

                //业务更新
                if (!empty($businessForUp)) {
                    $businessForUp['bb_update_time'] = $this->_date;
                    Service_BilBusiness::update($businessForUp, $businessArr['bb_id'], 'bb_id');
                }

            } else {
                //写入业务主表
                $businessArr = array(
                    'bt_code' => strtoupper($param['bt_code']),
                    'ds_code' => 'vf', //非逻辑
                    'customer_code' => '', //无
                    'warehouse_id' => (isset($param['warehouse_id']) ? $param['warehouse_id'] : 0),
                    'sm_code' => (isset($param['sm_code']) ? $param['sm_code'] : ''),
                    'bb_charge_time' => $charge_time,
                    'bb_declared_time' => $charge_time,
                    'bb_sales_id' => 0, //销售员
                    'bb_charge_sign' => 'y',
                    'bb_balance_sign' => 'y',
                    'bb_add_time' => $this->_date,
                );
                if (!$bb_id = Service_BilBusiness::add($businessArr)) {
                    throw new Exception("写入业务数据异常");
                }
                //附加表
                $code = self::getBusinessReferNo($spCode);
                if ($code == '') {
                    throw new Exception("无法获取业务单号");
                }
                $attachArr = array(
                    'bb_id' => $bb_id,
                    'bb_refer_code' => $code,
                );
                if (!Service_BilBusinessAttach::add($attachArr)) {
                    throw new Exception("写入业务附加数据异常");
                }

                //按收付类型添加费用
                $config = $type == '0' ? self::incomeFeeConfig() : self::paymentFeeConfig();
                //转为客户币种
                $cArr = Process_Financial::changeCurrency($amount, $currency_code, $row['currency_code']);
                if (!is_array($cArr)) {
                    throw new Exception($cArr);
                }
                $feeArr = array(
                    'bb_id' => $bb_id,
                    'sp_code' => $spCode,
                    'ft_code' => (isset($param['ft_code']) ? $param['ft_code'] : ''),
                    'sm_code' => (isset($param['sm_code']) ? $param['sm_code'] : ''),
                    'bp_creator_id' => (isset($param['bp_creator_id']) ? $param['bp_creator_id'] : $this->_userId),
                    'bp_amount' => ($type == '1' ? $cArr['value'] : $cArr['value'] * -1),
                    'bp_org_amount' => ($type == '1' ? $amount : $amount * -1),
                    'bp_note' => $note,
                    'bp_create_type' => 1,
                    'bp_status' => 1,
                    'bp_rp_type' => $type,
                    'currency_code' => $currency_code,
                    'currency_rate' => $cArr['org_rate'],
                    'bp_add_time' => $this->_date,
                    'bp_chargeable_time' => $charge_time,
                );
                //是否需要审核
                if ($config == '0') {
                    $feeArr['bp_status'] = 2;
                    $feeArr['bp_verify_time'] = $this->_date;
                    $feeArr['bp_verifier_id'] = $this->_userId;
                }
                if (!Service_BilPayment::add($feeArr)) {
                    throw new Exception("写入业务费用异常");
                }
            }

            $db->commit();
            $result['state'] = 1;
            $result['message'] = '操作成功';
            $result['code'] = $code;
        } catch (Exception $e) {
            $db->rollBack();
            $result['state'] = 0;
            $result['message'] = $e->getMessage();
        }
        return $result;
    }

    /**
     * @desc 新增业务费用(非逻辑)
     * @tips 用于批量上传
     * @param array $param
     * @throws Exception
     */
    private function addBusinessFee($param = array())
    {
        $this->editBusinessFeeValidation($param);

        $spCode = $param['sp_code'];
        $type = $param['rp_type'];
        $amount = $param['amount'];
        $currency_code = $param['currency_code'];
        $note = $param['note'];
        $charge_time = (!isset($param['charge_time']) || empty($param['charge_time']) ? $this->_date : $param['charge_time']);


        $row = Service_ServiceProvider::getByField($spCode, 'sp_code');
        if (empty($row)) {
            throw new Exception("服务商代码：" . $spCode . "不存在");
        }

        //写入业务主表
        $businessArr = array(
            //  'bt_code' => strtoupper($param['bt_code']),
            'ds_code' => 'vf', //非逻辑
            'customer_code' => '',
            'warehouse_id' => (isset($param['warehouse_id']) ? $param['warehouse_id'] : 0),
            'sm_code' => (isset($param['sm_code']) ? $param['sm_code'] : ''),
            'bb_charge_time' => $charge_time,
            'bb_declared_time' => $charge_time,
            'bb_sales_id' => 0, //销售员
            'bb_charge_sign' => 'y',
            'bb_balance_sign' => 'y',
            'bb_add_time' => $this->_date,
        );
        if (!$bb_id = Service_BilBusiness::add($businessArr)) {
            throw new Exception("写入业务数据异常");
        }
        //附加表
        $code = self::getBusinessReferNo($spCode);
        if ($code == '') {
            throw new Exception("无法获取业务单号");
        }
        $attachArr = array(
            'bb_id' => $bb_id,
            'bb_refer_code' => $code,
        );
        if (!Service_BilBusinessAttach::add($attachArr)) {
            throw new Exception("写入业务附加数据异常");
        }

        //按收付类型添加费用
        $config = $type == '0' ? self::incomeFeeConfig() : self::paymentFeeConfig();
        //转为客户币种
        $cArr = Process_Financial::changeCurrency($amount, $currency_code, $row['currency_code']);
        if (!is_array($cArr)) {
            throw new Exception($cArr);
        }
        $feeArr = array(
            'bb_id' => $bb_id,
            'sp_code' => $spCode,
            'ft_code' => (isset($param['ft_code']) ? $param['ft_code'] : ''),
            'sm_code' => (isset($param['sm_code']) ? $param['sm_code'] : ''),
            'bp_creator_id' => (isset($param['bp_creator_id']) ? $param['bp_creator_id'] : $this->_userId),
            'bp_amount' => ($type == '1' ? $cArr['value'] : $cArr['value'] * -1),
            'bp_org_amount' => ($type == '1' ? $amount : $amount * -1),
            'bp_note' => $note,
            'bp_create_type' => 1,
            'bp_status' => 1,
            'bp_rp_type' => $type,
            'currency_code' => $currency_code,
            'currency_rate' => $cArr['org_rate'],
            'bp_add_time' => $this->_date,
            'bp_chargeable_time' => $charge_time,
        );
        //是否需要审核
        if ($config == '0') {
            $feeArr['bp_status'] = 2;
            $feeArr['bp_verify_time'] = $this->_date;
            $feeArr['bp_verifier_id'] = $this->_userId;
        }
        if (!Service_BilPayment::add($feeArr)) {
            throw new Exception("写入业务费用异常");
        }

    }


    /**
     * @desc 删除业务费用(非逻辑)
     * @param array $param
     * @return array
     */
    public function clearBusinessFeeTransaction($param = array())
    {
        $result = array("state" => 0, "message" => "", "code" => '', "amount" => 0);

        $db = Common_Common::getAdapter();
        $db->beginTransaction();
        try {
            $note = $param['note'];
            $bp_id = $param['bp_id'];

            $bilPaymentRow = Service_BilPayment::getByField($bp_id, 'bp_id');
            if (empty($bilPaymentRow)) {
                throw new Exception("没有找到匹配的数据");
            }
            //更新业务表
            $businessForUp = array();
            $businessArr = Service_BilBusiness::getAttrByField($bilPaymentRow['bb_id'], 'bb_id');

            $result['code'] = $businessArr['bb_refer_code'];
            $result['amount'] = $bilPaymentRow['bp_amount'];

            if (!in_array($bilPaymentRow['bp_status'], self::editBusinessPaymentFeeConfig())) {
                $bilStatusArr = Process_BillConfig::bilPaymentStatus('auto');
                throw new Exception("状态为[" . $bilStatusArr[$bilPaymentRow['bp_status']] . '],不允许操作');
            }
            if (strtolower($businessArr['bb_status']) == 'n') {
                throw new Exception("此业务费用已作废,不允许操作");
            }
            //获取客户币种
            $row = Service_ServiceProvider::getByField($bilPaymentRow['sp_code'], 'sp_code');

            //应付表
            $biUpArr = array(
                'bp_status' => 0,
                'bp_note' => $note,
                'bp_update_time' => $this->_date,
                'bp_verifier_id' => $this->_userId,
                'bp_verify_time' => $this->_date,
            );
            Service_BilPayment::update($biUpArr, $bilPaymentRow['bp_id'], 'bp_id');

            //作废业务表单据
            $businessForUp['bb_status'] = 'n';
            $businessForUp['bb_update_time'] = $this->_date;
            Service_BilBusiness::update($businessForUp, $businessArr['bb_id'], 'bb_id');


            $db->commit();
            $result['state'] = 1;
            $result['message'] = '操作成功';
        } catch (Exception $e) {
            $db->rollBack();
            $result['state'] = 0;
            $result['message'] = $e->getMessage();
        }
        return $result;
    }


    /**
     * @desc 删除业务费用(非逻辑)
     * @param array $param
     * @return array
     */
    public function deleteBusinessFeeTransaction($param = array())
    {
        $result = array("state" => 0, "message" => "", "code" => '', "amount" => 0);

        $db = Common_Common::getAdapter();
        $db->beginTransaction();
        try {

            $bp_id = $param['bp_id'];

            $bilPaymentRow = Service_BilPayment::getByField($bp_id, 'bp_id');
            if (empty($bilPaymentRow)) {
                throw new Exception("没有找到匹配的数据");
            }

            $businessArr = Service_BilBusiness::getAttrByField($bilPaymentRow['bb_id'], 'bb_id');

            $result['code'] = $businessArr['bb_refer_code'];
            $result['amount'] = $bilPaymentRow['bp_amount'];

            if (!in_array($bilPaymentRow['bp_status'], self::editBusinessPaymentFeeConfig())) {
                $bilStatusArr = Process_BillConfig::bilPaymentStatus('auto');
                throw new Exception("状态为[" . $bilStatusArr[$bilPaymentRow['bp_status']] . '],不允许操作');
            }
            if (strtolower($businessArr['bb_status']) == 'n') {
                throw new Exception("此业务费用已作废,不允许操作");
            }
            //删除数据
            Service_BilPayment::delete($bilPaymentRow['bp_id'], 'bp_id');
            Service_BilBusiness::delete($businessArr['bb_id'], 'bb_id');
            Service_BilBusinessAttach::delete($businessArr['bb_id'], 'bb_id');

            $db->commit();
            $result['state'] = 1;
            $result['message'] = '操作成功';
        } catch (Exception $e) {
            $db->rollBack();
            $result['state'] = 0;
            $result['message'] = $e->getMessage();
        }
        return $result;
    }


    /**
     * @desc 审核业务费用(非逻辑)
     * @param array $param
     * @return array
     */
    public function verifyBusinessFeeTransaction($param = array())
    {
        $result = array("state" => 0, "message" => "", "code" => '', "amount" => 0, "opType" => 0);

        $db = Common_Common::getAdapter();
        $db->beginTransaction();
        try {
            $note = $param['note'];
            $bp_id = $param['bp_id'];
            $opType = $param['opType'];

            $bilPaymentRow = Service_BilPayment::getByField($bp_id, 'bp_id');
            if (empty($bilPaymentRow)) {
                throw new Exception("没有找到匹配的数据");
            }
            //更新业务表
            $businessForUp = array();
            $businessArr = Service_BilBusiness::getAttrByField($bilPaymentRow['bb_id'], 'bb_id');

            $result['code'] = $businessArr['bb_refer_code'];
            $result['amount'] = $bilPaymentRow['bp_amount'];

            if ($bilPaymentRow['bp_status'] != '1') {
                $bilStatusArr = Process_BillConfig::bilPaymentStatus('auto');
                throw new Exception("状态为[" . $bilStatusArr[$bilPaymentRow['bp_status']] . '],不允许操作');
            }
            if (strtolower($businessArr['bb_status']) == 'n') {
                throw new Exception("此业务费用已作废,不允许操作");
            }
            //应付表
            $biUpArr = array(
                'bp_status' => $opType == '1' ? 2 : 1,
                'bp_withdraw_sign' => $opType == '1' ? 'n' : 'y',
                'bp_update_time' => $this->_date,
                'bp_verifier_id' => $this->_userId,
                'bp_verify_time' => $this->_date,
                'bp_note' => $bilPaymentRow['bp_note'].'<br/>'.$note,
            );
            Service_BilPayment::update($biUpArr, $bilPaymentRow['bp_id'], 'bp_id');

            $db->commit();
            $result['state'] = 1;
            $result['message'] = '操作成功';
        } catch (Exception $e) {
            $db->rollBack();
            $result['state'] = 0;
            $result['message'] = $e->getMessage();
        }
        return $result;
    }


    /**
     * @desc 批量导入费用（非逻辑）
     */
    public function uploadFeeTransaction($file)
    {
         require_once APPLICATION_PATH . '/../libs/PHPExcel/IOFactory.php';
        $return = array(
            'state' => 0,
            'message' => array()
        );
        if ($file['error']) {
            $return['message'] = array('请选择xls文件');
            return $return;
        }
        $fileName = $file['name'];
        $filePath = $file['tmp_name'];
        $pathinfo = pathinfo($fileName);
        if (!isset($pathinfo["extension"]) && $pathinfo["extension"] != "xls") {
            $return['message'] = array('请选择xls文件');
            return $return;
        }

        $fileData = Common_Upload::readUploadFile($fileName, $filePath);
        if (!isset($fileData[1]) || !is_array($fileData[1])) {
            $result['message'] = array('上传失败，无法解析文件内容;');
            return $result;
        }
        /**
         * 格式化数据
         */
         $loaderObj = PHPExcel_IOFactory::load($filePath); // 加载Excel文件
        $sheetObj= $loaderObj->getSheet(0); 
        $keys = array(
            '服务商代码' => 'sp_code',
            '仓库代码' => 'warehouse_code',
            '运输方式代码' => 'sm_code',
            '费用类型代码' => 'ft_code',
            '金额' => 'amount',
            '币种' => 'currency_code',
            '计费时间' => 'charge_time',
            '备注' => 'note',
        );

        $data = $error = array();
        foreach ($fileData as $key => $val) {
            $newVal = array();
            foreach ($keys as $k => $v) {
            	if($v != 'note' && $v !='sm_code'){
	                if(!isset($val[$k])){
					//	$error[] = '第 ' . $key . ' 行,无法识别'.'$key=>'.$key.'$v=>'.$v.'$k=>'.$k;
	                	$error[] = '第 ' . $key . ' 行,无法识别';
						continue;
	                }
            	}
                $newVal[$v] = isset($val[$k]) ? trim($val[$k]) : '';
            }
            
            $spCode = preg_replace('/([0-9a-zA-Z]+)\s+.*/', '\\1', $newVal['sp_code']);
            if (empty($spCode)) {
                $error[] = '第 ' . $key . ' 行,服务商代码不能为空';
                continue;
            }

            $whCode = preg_replace('/([0-9a-zA-Z]+)\s+.*/', '\\1', $newVal['warehouse_code']);

            if (!empty($newVal['sm_code'])) {
                $smRow = Service_ShippingMethod::getByField($newVal['sm_code'], 'sm_code', array('sm_code'));
                if (empty($smRow)) {
                    $error[] = '第 ' . $key . ' 行,运输代码不存在或无法识别';
                    continue;
                }
            }
            if (empty($newVal['ft_code'])) {
                $error[] = '第 ' . $key . ' 行,费用类型代码不能为空';
                continue;
            }

            if (empty($newVal['currency_code'])) {
                $error[] = '第 ' . $key . ' 行,币种不能为空';
                continue;
            }
             $cell =$sheetObj->getCellByColumnAndRow('4',$key+1);  
           if($cell->getDataType()==PHPExcel_Cell_DataType::TYPE_NUMERIC){
                 $cellstyleformat=$cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat();  
                 $formatcode=$cellstyleformat->getFormatCode(); 
                  if (preg_match('/^(\[\$[A-Z]*-[0-9A-F]*\])*[hmsdy]/i', $formatcode)){
                        $error[] = '第 ' . $key . ' 行,金额异常,单元格格式不正确';
                         continue;
                  }
           }
          
            if (!is_numeric($newVal['amount'])) {
                $error[] = '第 ' . $key . ' 行,金额异常';
                continue;
            }
            $chargTimeCell =$sheetObj->getCellByColumnAndRow('6',$key+1);  
           if($chargTimeCell->getDataType()==PHPExcel_Cell_DataType::TYPE_NUMERIC){
                 $cellstyleformat=$cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat();  
                 $formatcode=$cellstyleformat->getFormatCode(); 
                  if (preg_match('/^(\[\$[A-Z]*-[0-9A-F]*\])*[hmsdy]/i', $formatcode)){
                        $error[] = '第'.$key.'行计费时间列格式不正确，正确格式如2015/10/10且单元格格式为文本格式';
                         continue;
                  }elseif($formatcode=='General'){
                      if(!preg_match('/^\d{4}\/{1}\d{1,2}\/{1}\d{1,2}$/',$newVal['charge_time'])){
                              $error[] = '第'.$key.'行计费时间列格式不正确，正确格式如2015/10/10且单元格格式为文本格式';
                            continue;
                         }
                  }
           }else{
               if(!preg_match('/^\d{4}\/{1}\d{1,2}\/{1}\d{1,2}$/',$newVal['charge_time'])){
                       $error[] = '第'.$key.'行计费时间列格式不正确，正确格式如2015/10/10且单元格格式为文本格式';
                     continue;
               }
           }
           $dateSplide=  explode('/', $newVal['charge_time']);
           if(!checkdate($dateSplide[1], $dateSplide[2], $dateSplide[0])){
               $error[] = '第 ' . $key . ' 行,非法的计费时间，请检查时间是否正确';
                continue;
           }
            if (!empty($whCode)) {
                $whRow = Service_Warehouse::getByField($whCode, 'warehouse_code', array('warehouse_code', 'warehouse_id'));
                if (empty($whRow)) {
                    $error[] = '第 ' . $key . ' 行,仓库代码不存在或无法识别';
                    continue;
                }
            }

            $ftRow = Service_FeeType::getByField($newVal['ft_code'], 'ft_code');
            if (empty($ftRow)) {
                $error[] = '第 ' . $key . ' 行,费用类型代码不存在或无法识别';
                continue;
            }
            
            $currencyRow = Service_Currency::getByField($newVal['currency_code'], 'currency_code');
            if (empty($currencyRow)) {
                $error[] = '第 ' . $key . ' 行,币种不存在或无法识别';
                continue;
            }

            $spRow = Service_ServiceProvider::getByField($spCode, 'sp_code');

            if (empty($spRow)) {
                $error[] = '第 ' . $key . ' 行,服务商代码：' . $spCode . '不存在或无法识别';
                continue;
            }

            $data[$key]['warehouse_id'] = isset($whRow['warehouse_id']) ? $whRow['warehouse_id'] : 0;
            $data[$key]['sm_code'] = empty($newVal['sm_code']) ? '' : strtoupper($newVal['sm_code']);
            $data[$key]['ft_code'] = $ftRow['ft_code'];
            $data[$key]['currency_code'] = $currencyRow['currency_code'];
            $data[$key]['amount'] = abs($newVal['amount']);
            $data[$key]['rp_type'] = $newVal['amount'] < 0 ? 0 : 1; //类型
            $data[$key]['note'] = $newVal['note'];
            $data[$key]['sp_code'] = $spRow['sp_code'];
            $data[$key]['charge_time'] = Process_ImportDataProcess::excelTime($newVal['charge_time']);

        }
        unset($fileData, $newVal);
        if (!empty($error) || empty($data)) {
            $return['state'] = 0;
            $return['message'] = $error;
            return $return;
        }

        $db = Common_Common::getAdapter();
        $db->beginTransaction();
        try {
            foreach ($data as $key => $row) {
                $this->addBusinessFee($row);
            }
            $db->commit();
            $return['state'] = 1;
            $return['message'] = array('操作成功');
        } catch (Exception $e) {
            $db->rollBack();
            $return['message'] = array($e->getMessage());
        }
        return $return;
    }

    /**
     * @desc 设置业务数据
     * @param string $code
     */
    private function setBusiness($code = '')
    {
        $businessArr = Service_BilBusinessAttach::getByField($code, 'bb_refer_code');
        if (!empty($businessArr)) {
            $this->_bb_id = $businessArr['bb_id'];
            $this->_businessArr['business'] = Service_BilBusiness::getByField($businessArr['bb_id'], 'bb_id');
            $this->_businessArr['attach'] = $businessArr;
            $this->_businessArr['income'] = Service_BilIncome::getByCondition(array('bb_id' => $businessArr['bb_id']), '*', 0);
            $this->_businessArr['payment'] = Service_BilPayment::getByCondition(array('bb_id' => $businessArr['bb_id']), '*', 0);
        }
    }

    /**
     * @desc 新增业务费用(逻辑)
     * @param array $businessArr
     * @param array $incomeArr
     * @param array $paymentArr
     * @throws Exception
     */
    private function createBusinessFee($businessArr = array(), $incomeArr = array(), $paymentArr = array())
    {
        //附加表
        $attachArr = array(
            'bb_refer_code' => $businessArr['bb_refer_code'],
            'bb_service_number' => $businessArr['bb_service_number'],
            'bb_reference_no' => $businessArr['bb_reference_no'],
        );
        //业务表
        $businessArr['bb_add_time'] = $this->_date;
        unset($businessArr['bb_refer_code'], $businessArr['bb_service_number'], $businessArr['bb_reference_no']);
        if (!$bbId = Service_BilBusiness::add($businessArr)) {
            throw new Exception("建立业务数据错误");
        }
        $attachArr['bb_id'] = $bbId;
        Service_BilBusinessAttach::add($attachArr);

        //应收
        if (!empty($incomeArr)) {

            foreach ($incomeArr as $row) {
                $row['bb_id'] = $bbId;
                $row['bi_status'] = 2;
                $row['customer_code'] = $businessArr['customer_code'];
                $row['bi_rp_type'] = $row['bi_amount'] > 0 ? 0 : 1;
                $row['bi_add_time'] = $this->_date;
                $row['bi_verify_time'] = $this->_date;
                $row['bi_chargeable_time'] = isset($row['bi_chargeable_time']) ? $row['bi_chargeable_time'] : $businessArr['bb_charge_time'];
                //汇率为空
                if (!isset($currencyArr[$row['currency_code']])) {
                    $cArr = Service_Currency::getByField($row['currency_code'], 'currency_code');
                    $currencyArr[$row['currency_code']] = $cArr['currency_rate'];
                }
                $row['currency_rate'] = $currencyArr[$row['currency_code']];
                Service_BilIncome::add($row);
            }
        }
        //应付
        if (!empty($paymentArr)) {
            foreach ($paymentArr as $row) {
                $row['bb_id'] = $bbId;
                $row['bp_status'] = 2;
                $row['bp_rp_type'] = $row['bp_amount'] < 0 ? 0 : 1;
                $row['bp_add_time'] = $this->_date;
                $row['bp_verify_time'] = $this->_date;
                $row['bp_chargeable_time'] = isset($row['bp_chargeable_time']) ? $row['bp_chargeable_time'] : isset($businessArr['bb_declared_time']) ? $businessArr['bb_declared_time'] : $businessArr['bb_charge_time'];
                //汇率为空
                if (!isset($currencyArr[$row['currency_code']])) {
                    $cArr = Service_Currency::getByField($row['currency_code'], 'currency_code', 'currency_rate');
                    $currencyArr[$row['currency_code']] = $cArr['currency_rate'];
                }
                $row['currency_rate'] = $currencyArr[$row['currency_code']];
                Service_BilPayment::add($row);
            }
        }
    }


    /**
     * @desc 编辑业务费用(逻辑)
     * @param array $businessArr
     * @param array $incomeArr
     * @param array $paymentArr
     * @throws Exception
     */
    private function editBusinessFee($businessArr = array(), $incomeArr = array(), $paymentArr = array())
    {
        //业务表
        $businessUpArr['bb_update_time'] = $this->_date;
        foreach ($this->_businessArr['attach'] as $key => $val) {
            if (isset($businessArr[$key])) {
                $businessUpArr[$key] = $val;
            }
        }
        unset($businessUpArr['bb_id']);
        if (!Service_BilBusiness::update($businessUpArr, $this->_bb_id, 'bb_id')) {
            throw new Exception("建立业务错误");
        }
        //附加表
        $attachArr['bba_update_time'] = $this->_date;
        foreach ($this->_businessArr['attach'] as $key => $val) {
            $attachArr[$key] = isset($businessArr[$key]) ? $businessArr[$key] : $val;
        }
        unset($attachArr['bb_id'], $attachArr['bb_refer_code']);
        Service_BilBusinessAttach::update($attachArr, $this->_bb_id, 'bb_id');
        //应收
        if (!empty($incomeArr)) {
            $income = false;
            $incomeArray = array();
            if (!empty($this->_businessArr['income'])) {
                foreach ($this->_businessArr['income'] as $iRow) {
                    if ($iRow['bi_status'] == '3') {
                        $income = true;
                        if (!isset($incomeArray[$iRow['ft_code']])) {
                            $incomeArray[$iRow['ft_code']] = $iRow['bi_amount'];
                        } else {
                            $incomeArray[$iRow['ft_code']] += $iRow['bi_amount'];
                        }
                    }
                }
            }
            //判断是否已存在出帐
            if ($income) {
                //汇总各类型费用
                $incomeNewArray = array();
                foreach ($incomeArr as $iRow) {
                    if (isset($incomeNewArray[$iRow['ft_code']])) {
                        $incomeNewArray[$iRow['ft_code']]['bi_amount'] += $iRow['bi_amount'];
                    } else {
                        $incomeNewArray[$iRow['ft_code']] = $iRow;
                    }
                }
                //多还少补
                foreach ($incomeNewArray as $code => $row) {
                    $oAmount = isset($incomeArray[$code]['bi_amount']) ? $incomeArray[$code]['bi_amount'] : 0;
                    $amount = $row['bi_amount'] - $oAmount;
                    if ($amount == 0) {
                        continue;
                    }
                    $row['bb_id'] = $this->_bb_id;
                    $row['bi_status'] = 2;
                    $row['customer_code'] = $this->_businessArr['customer_code'];
                    $row['bi_rp_type'] = $amount > 0 ? 0 : 1;
                    $row['bi_add_time'] = $this->_date;
                    $row['bi_verify_time'] = $this->_date;
                    $row['bp_update_time'] = $this->_date;
                    $row['bi_chargeable_time'] = isset($row['bi_chargeable_time']) ? $row['bi_chargeable_time'] : $businessArr['bb_charge_time'];
                    Service_BilIncome::add($row);
                }
            } else {
                //清理原费用
                Service_BilIncome::delete($this->_bb_id, 'bb_id');
                foreach ($incomeArr as $row) {
                    $row['bb_id'] = $this->_bb_id;
                    $row['bi_status'] = 2;
                    $row['customer_code'] = $businessArr['customer_code'];
                    $row['bi_rp_type'] = $row['bi_amount'] > 0 ? 0 : 1;
                    $row['bi_add_time'] = $this->_date;
                    $row['bi_verify_time'] = $this->_date;
                    $row['bi_chargeable_time'] = isset($row['bi_chargeable_time']) ? $row['bi_chargeable_time'] : $businessArr['bb_charge_time'];
                    Service_BilIncome::add($row);
                }
            }
        }
        //应付
        if (!empty($paymentArr)) {
            $payment = false;
            $paymentArray = array();
            if (!empty($this->_businessArr['payment'])) {
                foreach ($this->_businessArr['payment'] as $iRow) {
                    if ($iRow['bp_status'] == '3') {
                        $payment = true;
                        if (!isset($paymentArray[$iRow['ft_code']])) {
                            $paymentArray[$iRow['ft_code']] = $iRow['bp_amount'];
                        } else {
                            $paymentArray[$iRow['ft_code']] += $iRow['bp_amount'];
                        }
                    }
                }
            }

            if ($payment) {
                //多还少补
                foreach ($paymentArr as $code => $row) {
                    $oAmount = isset($paymentArray[$code]['bp_amount']) ? $paymentArray[$code]['bp_amount'] : 0;
                    $amount = $row['bp_amount'] - $oAmount;
                    if ($amount == 0) {
                        continue;
                    }
                    $row['bb_id'] = $this->_bb_id;
                    $row['bp_status'] = 2;
                    $row['bp_amount'] = $amount;
                    $row['bp_rp_type'] = $amount < 0 ? 0 : 1;
                    $row['bp_add_time'] = $this->_date;
                    $row['bp_verify_time'] = $this->_date;
                    $row['bp_chargeable_time'] = isset($row['bp_chargeable_time']) ? $row['bp_chargeable_time'] : $businessArr['bb_declared_time'];
                    Service_BilPayment::add($row);
                }
            } else {
                //清理原费用
                Service_BilPayment::delete($this->_bb_id, 'bb_id');
                foreach ($paymentArr as $row) {
                    $row['bb_id'] = $this->_bb_id;
                    $row['bp_status'] = 2;
                    $row['bp_rp_type'] = $row['bp_amount'] < 0 ? 0 : 1;
                    $row['bp_add_time'] = $this->_date;
                    $row['bp_verify_time'] = $this->_date;
                    $row['bp_chargeable_time'] = isset($row['bp_chargeable_time']) ? $row['bp_chargeable_time'] : $businessArr['bb_declared_time'];
                    Service_BilPayment::add($row);
                }
            }

        }
    }

    /**
     * @desc 新增/编辑业务费用(逻辑)
     * @param array $businessArr
     * @param array $incomeArr
     * @param array $paymentArr
     * @return array
     */
    public function businessFee($businessArr = array(), $incomeArr = array(), $paymentArr = array())
    {
        $result = array("state" => 0, "message" => "", "data" => array());

        try {
            //主要参考
            $paramArr = array(
                'bt_code' => 'EX',
                'ds_code' => '',
                'customer_code' => '',
                'warehouse_id' => '0',
                'sm_code' => '',
                'bb_volume_weight' => 0,
                'bb_charge_weight' => 0,
                'bb_delivered_weight' => 0,
                'bb_pieces' => 0,
                'bb_declared_value' => 0,
                'bb_declared_currency_code' => 'USD',
                'country_code' => '',
                'bb_postcode' => '',
                'bb_charge_time' => '',
                'bb_declared_time' => '', //发货时间 此时间与服务商对接
                'bb_sales_id' => 0,

                'bb_refer_code' => '',
                'bb_service_number' => '',
                'bb_reference_no' => '',
            );

            if (!isset($businessArr['ds_code'])) {
                throw new Exception("业务类型不能为空");
            }
            if (!isset($businessArr['bb_refer_code']) || $businessArr['bb_refer_code'] == '') {
                throw new Exception("业务单号不能为空");
            }
            $businessArr['ds_code'] = strtolower($businessArr['ds_code']);
            if (!in_array($businessArr['ds_code'], array('so', 'lo', 'asn'))) {
                throw new Exception("业务类型异常");
            }
            //设置业务
            $this->setBusiness($businessArr['bb_refer_code']);

            //主要信息
            foreach ($paramArr as $key => $val) {
                $paramArr[$key] = isset($businessArr[$key]) ? $businessArr[$key] : $val;
            }
            //判断是否为新增
            if ($this->_bb_id == '') {
                $this->createBusinessFee($paramArr, $incomeArr, $paymentArr);
            } else {
                $this->editBusinessFee($paramArr, $incomeArr, $paymentArr);
            }

            $result['state'] = 1;
            $result['message'] = '操作成功';

        } catch (Exception $e) {
            $result['state'] = 0;
            $result['message'] = $e->getMessage();
        }
        return $result;
    }


    /**
     * @desc 应付 重新计费 事务处理
     * @param array $param array("refer_code","createType","ds_code")
     * @return array
     */
    public function readjustmentPaymentTransaction($param = array())
    {
        $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);
                    break;
                case 'lo':
                    $this->readjustmentForOutsideOrder($param);
                    break;
                case 'asn':
                    //后续补全
                    throw new Exception("此业务类型不支持重新计费");
                    break;
                default:
                    throw new Exception("此业务类型不支持重新计费");
                    break;

            }
            $db->commit();
            $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())
    {
        //参数
        $code = isset($param['refer_code']) ? $param['refer_code'] : '0';
        $createType = isset($param['createType']) ? $param['createType'] : '0';


        $businessArr = Service_BilBusiness::getAttrByRefCode($code);

        if (strtolower($businessArr['ds_code']) != 'so') {
            throw new Exception("业务必须为订单");
        }

        if (strtolower($businessArr['bb_status']) == 'n') {
            throw new Exception("此业务费用已作废,不允许操作");
        }

        //重量未更新，无须重新计费
        $aShipOrder = Service_ShipOrder::getByField($code, 'order_code');
        if(($aShipOrder['so_service_provider_weight'] <= $aShipOrder['so_weight'])
            || ($aShipOrder['so_service_provider_weight'] <= $aShipOrder['so_vol_weight'])){
            throw new Exception('订单'.$code.'服务商重量未更新（未增大），无须重新计费');
        }

        //删除数据
        $create_type_arr = $createType == '0' ? array(0) : array(0, 1);
        $iCondition = array(
            'bb_id' => $businessArr['bb_id'],
            'bp_status' => 2, //考虑到可能部分已出帐的问题
            'bp_create_type_arr' => $create_type_arr,
        );
        //费用集合
        $feeArr = array();
        $pRows = Table_BilPayment::getInstance()->getByCondition($iCondition, '*', 0, 0);
        //清理原费用
        if (!empty($pRows)) {
            foreach ($pRows as $row) {
                Table_BilPayment::getInstance()->delete($row['bp_id'], 'bp_id');
            }
        }
        //新费用
        $this->shipCost($businessArr['bb_refer_code']);
    }


    /**
     * @desc 计算成本
     * @param string $order_code
     * @return bool|string
     * @throws Exception
     */
    public static function shipCost($order_code) {
        $userAuth                   = new Zend_Session_Namespace('userAuthorization');
        $aOrder                     = Service_Orders::getByField($order_code, 'order_code');
        $aShipOrder                 = Service_ShipOrder::getByField($order_code, 'order_code');
        $aAddress                   = Service_OrderAddressBook::getByField($order_code, 'order_code');
        $countryArr                 = Service_Country::getByField($aAddress['oab_country_id'],'country_id');
        $customerArr                = Service_Customer::getByField($aOrder['customer_code'],'customer_code',array('customer_saler_user_id','customer_currency'));
        $customerCurrencyRow        = Service_Currency::getByField($customerArr['customer_currency'],'currency_code',array('currency_code','currency_rate','currency_batch_number'));
        $shippingMethodArr          = Service_ShippingMethod::getByField($aOrder['sm_code'],'sm_code',array('sm_vol_rate','sm_is_volume'));
        $currency_batch_number      = $customerCurrencyRow['currency_batch_number']; /* 当前汇率编号 */
        $_otherfee_mix_arr          = Process_BillConfig::getOtherFeeArr();
        $fee_cost_detail            = array(); /* 费用及成本明细 */
        $spArr                      = array();
        $incomeArr                  = array(); /* 客户费用 应收 */
        $paymentArr                 = array(); /* 应付费用 */
        $realWeight                 = 0;
        $date                       = date('Y-m-d H:i:s');
        $remote_ip                  = Common_Common::getIP();

        //Begin 运输费用及成本计算
        //重新计算运费的情况 被 Process_BusinessIncome 所调用
        $_cbl_note              = '重新计费，扣';
        $objCalculate           = new Common_ReCalculateShipping(); /* 重新计费的方法差异很大，另写新类 */
        $realWeight             = $aShipOrder['so_service_provider_weight']; /* 调用之前已经检查 so_service_provider_weight 必须均大于出货重、体积重 */
        $logisticsCostRow       = Service_LogisticsCost::getByField($order_code, 'order_code', array('currency_code', 'currency_rate', 'smc_discount', 'price_batch_number', 'sm_baf', 'customer_currency_code', 'customer_currency_rate'));
        $costRecordingRow       = Service_CostRecording::getByField($order_code, 'order_code', array('currency_code', 'currency_rate', 'price_batch_number', 'currency_batch_number', 'sm_baf', 'provider_currency_code', 'provider_currency_rate'));
        $currency_batch_number  = $costRecordingRow['currency_batch_number'];
        $currencyLogRows        = Service_CurrencyLog::getByBatchnumber($currency_batch_number);
        $keys                   = array(
            'warehouseId'               => $aOrder['warehouse_id'],
            'countryId'                 => $aAddress['oab_country_id'],
            'smCode'                    => $aOrder['sm_code'],
            'weight'                    => $realWeight,
            'order_code'                => $order_code,
            'realWeight'                => $realWeight,
            'customerCode'              => $aOrder['customer_code'],
            'price_currency_code'       => $logisticsCostRow['currency_code'],          //运输价格币种
            'price_currency_rate'       => $logisticsCostRow['currency_rate'],          //运输价格币种汇率
            'smc_discount'              => $logisticsCostRow['smc_discount'],           //客户运输折扣
            'customer_currency_code'    => $logisticsCostRow['customer_currency_code'], //客户币种
            'customer_currency_rate'    => $logisticsCostRow['customer_currency_rate'], //客户币种汇率
            'provider_currency_code'    => $costRecordingRow['provider_currency_code'], //服务商币种 - costRecording
            'provider_currency_rate'    => $costRecordingRow['provider_currency_rate'], //服务商币种汇率 - costRecording
            'sm_baf'                    => $costRecordingRow['sm_baf'],                 //燃油费率，只对 CRE起作用 - costRecording
            'price_batch_number'        => $costRecordingRow['price_batch_number'],     //运输价格编号 - costRecording 或 logisticsCost
        );

        $objCalculate->setParams($keys);
        $aCalculate = $objCalculate->getRate();
        //End 运输费用及成本计算
        if($aCalculate['data']['sm']['sm_channel']=='0'){
        //Begin 非自有运输方式扣物流运输费、燃油附加费

            //记录应收、应付
            $incomeArr = $paymentArr = array();
            if($aCalculate['state'] == 0) {
                return is_array($aCalculate['error']) ? implode(',', $aCalculate['error']) : $aCalculate['error'];
            }
            $fee = $aCalculate['data']['cost']['totalCost'];

            //生成一条成本费用的记录
            $sm = $aCalculate['data']['sm'];
            //服务商货币及汇率
            $providerRow            = Service_ServiceProvider::getByField($sm['sp_code'], 'sp_code', array('currency_code'));
            if(empty($providerRow)){
                throw new Exception('运输方式'.$sm['sm_code'].'服务商未设置！');
            }
            $providerCurrencyRow    = Service_Currency::getByField( $providerRow['currency_code'], 'currency_code', array('currency_code','currency_rate'));
            //成本货币及汇率
            $costCurrencyRow        = Service_Currency::getByField($aCalculate['data']['cost']['cost_currency_code'], 'currency_code', array('currency_code','currency_rate'));
            //成本费
            $costFee                = $aCalculate['data']['cost']['cost'];
            //单票成本
            $ticket_fare_cost       = isset($aCalculate['data']['cost']['one_ticket_cbcost'])?$aCalculate['data']['cost']['one_ticket_cbcost']:0;
            //燃油附加费
            $fuel_addons            = $aCalculate['data']['cost']['cost_baf'];
            if($sm['sm_class_code']=="CRP"||$sm['sm_class_code']=="CPS"){
                $total          = $aCalculate['data']['cost']['cost'] + $ticket_fare_cost ;
                $fuel_addons    = 0;
            }else{
                $total          = $aCalculate['data']['cost']['cost'] + $fuel_addons;
            }

            $costRecording = array(
                'order_code'                => $order_code,
                'customer_code'             => $aOrder['customer_code'],
                'reference_no'              => $aOrder['reference_no'],
                'tracking_number'           => $aShipOrder['tracking_number'],
                'sm_code'                   => $aOrder['sm_code'],
                'country_id'                => $aAddress['oab_country_id'],
                'weight'                    => $realWeight,
                'cost_fee'                  => $costFee,
                'ticket_fare'               => $ticket_fare_cost,
                'fuel_addons'               => $fuel_addons,
                'total_fee'                 => $total,
                'price_batch_number'        => $aCalculate['data']['cost']['price_batch_number'],   //价格编号,用于重算
                'currency_batch_number'     => $currency_batch_number,                              //汇率编号，用于重算
                'sm_baf'                    => $aCalculate['data']['sm']['sm_baf'],                 //燃油附加费率,用于重算
                'currency_code'             => $costCurrencyRow['currency_code'],                   //成本币种
                'currency_rate'             => $costCurrencyRow['currency_rate'],                   //成本币种汇率
                'provider_currency_code'    => $providerCurrencyRow['currency_code'],               //服务商币种
                'provider_currency_rate'    => $providerCurrencyRow['currency_rate'],               //服务商币种汇率
                'add_time'                  => $date,
                'update_time'               => $date,
            );
            //重新计费的情况
            $cRow = Service_CostRecording::getByField($order_code, 'order_code');
            if (empty($cRow)) {
                unset($costRecording['update_time']);
                Service_CostRecording::add($costRecording);
            } else {
                unset($costRecording['add_time']);
                unset($costRecording['currency_code']);
                unset($costRecording['price_batch_number']);
                unset($costRecording['sm_baf']);
                unset($costRecording['currency_rate']);
                unset($costRecording['provider_currency_code']);
                unset($costRecording['provider_currency_rate']);
                unset($costRecording['add_time']);
                Service_CostRecording::update($costRecording, $cRow['cr_id'], 'cr_id');
            }

            /**
             * Begin 应付
             */

            //运费（未包括其它费用项）
            if ($costFee > 0) {
                if (!isset($spArr[$sm['sp_code']])) {
                    $spRow = Service_ServiceProvider::getByField($sm['sp_code'], 'sp_code');
                    $spArr[$sm['sp_code']] = $spRow['currency_code'];
                }
                $convert_fee = Service_Currency::converByCode($aCalculate['data']['cost']['cost_currency_code'], $spArr[$sm['sp_code']], $costFee);
                $paymentArr[] = array(
                    'sp_code'               => $sm['sp_code'], //服务商代码
                    'ft_code'               => 'shipping',
                    'ut_code'               => 'KG',
                    'sm_code'               => $aOrder['sm_code'],
                    'bp_amount'             => $convert_fee,
                    'bp_org_amount'         => $costFee, //原金额
                    'currency_code'         => $aCalculate['data']['cost']['cost_currency_code'],
                    'currency_rate'         => $aCalculate['data']['cost']['currency_rate'],
                    'bp_chargeable_time'    => $date,
                );
            }
            //单票
            if($ticket_fare_cost>0){
                if (!isset($spArr[$sm['sp_code']])) {
                    $spRow = Service_ServiceProvider::getByField($sm['sp_code'], 'sp_code');
                    $spArr[$sm['sp_code']] = $spRow['currency_code'];
                }
                $convert_fee = Service_Currency::converByCode($aCalculate['data']['cost']['cost_currency_code'], $spArr[$sm['sp_code']], $ticket_fare_cost);
                $paymentArr[]=array(
                    'sp_code'               => $sm['sp_code'],//服务商代码
                    'ft_code'               => 'one_ticket_fee',
                    'ut_code'               => 'PCE',
                    'sm_code'               => $aOrder['sm_code'],
                    'bp_amount'             => $convert_fee,
                    'bp_org_amount'         => $ticket_fare_cost, //原金额
                    'currency_code'         => $aCalculate['data']['cost']['cost_currency_code'],
                    'currency_rate'         => $aCalculate['data']['cost']['currency_rate'],
                    'bp_chargeable_time'    => $date,
                );
            }

            //附加费
            if($fuel_addons>0){
                if (!isset($spArr[$sm['sp_code']])) {
                    $spRow = Service_ServiceProvider::getByField($sm['sp_code'], 'sp_code');
                    $spArr[$sm['sp_code']] = $spRow['currency_code'];
                }
                $convert_fee = Service_Currency::converByCode($aCalculate['data']['cost']['cost_currency_code'], $spArr[$sm['sp_code']], $fuel_addons);
                $paymentArr[]=array(
                    'sp_code'               => $sm['sp_code'],//服务商代码
                    'ft_code'               => 'additional_fee',
                    'ut_code'               => 'PCE',
                    'sm_code'               => $aOrder['sm_code'],
                    'bp_amount'             => $convert_fee,
                    'bp_org_amount'         => $fuel_addons,//原金额
                    'currency_code'         => $aCalculate['data']['cost']['cost_currency_code'],
                    'currency_rate'         => $aCalculate['data']['cost']['currency_rate'],
                    'bp_chargeable_time'    => $date,
                );
            }
            /**
             * End  应付
             */

        //End 非自有运输方式扣物流运输费、燃油附加费
        }


        /* 扣其它费用 Begin */
        $objOtherCalculte           = new Common_CalculateOtherFee();
        $keys['receiving_weight']   = $aShipOrder['so_weight'];
        $objOtherCalculte->setParams($keys);
        $otherfeeArr                = $objOtherCalculte->getOtherFee();
        $_is_deduct                 = false;
        foreach($otherfeeArr['data']['otherFee'] as $otherfee_name => $otherfee_data){
            $cost_detail = array();
            switch($otherfee_name){
                case 'cangchu':
                case 'caozuo':
                case 'baoguan':
                case 'tihuo':
                case 'yunshu':
                case 'jianguanyunshu':
                case 'ruku':
                case 'wuliucaozuo':
                    $_is_deduct = true;
                    break;
                default:
                    $_is_deduct = false;
                    break;
            }
            if(isset($_otherfee_mix_arr[$otherfee_name]['smcode'])){
            /* 某些杂费只针对特定的运输方式，或者排除特定的运输方式 */
                if('DENY' == $_otherfee_mix_arr[$otherfee_name]['smcode']['type']){
                    if(isset($_otherfee_mix_arr[$otherfee_name]['smcode'][$aOrder['sm_code']])){
                        $_is_deduct = false;
                    }
                }
                if('ALLOW' == $_otherfee_mix_arr[$otherfee_name]['smcode']['type']){
                    if(!isset($_otherfee_mix_arr[$otherfee_name]['smcode'][$aOrder['sm_code']])){
                        $_is_deduct = false;
                    }
                }
            }
            if(false == $_is_deduct){
                continue; /* 不需要扣费 */
            }

            if(isset($otherfee_data['cost']) && $otherfee_data['cost'] > 0 && $otherfee_data['sp_code']!=''){
                if(!isset($spArr[$otherfee_data['sp_code']])){
                    $spRow = Service_ServiceProvider::getByField($otherfee_data['sp_code'],'sp_code');
                    $spArr[$otherfee_data['sp_code']] = $spRow['currency_code'];
                }

                $convert_fee    = Service_CurrencyLog::converByCode($otherfee_data['currency_code'],$spArr[$otherfee_data['sp_code']],$otherfee_data['cost'],$currency_batch_number);
                $otherfee_rate  = $currencyLogRows[$otherfee_data['currency_code']]['currency_rate'];

                //应付记录
                $paymentArr[] = array(
                    'sp_code'               => $otherfee_data['sp_code'],       //服务商代码
                    'ft_code'               => $_otherfee_mix_arr[$otherfee_name]['ftcode'],
                    'ut_code'               => $_otherfee_mix_arr[$otherfee_name]['utcode'],
                    'sm_code'               => $aOrder['sm_code'],
                    'bp_amount'             => $convert_fee,                    //服务商结算金额
                    'bp_org_amount'         => $otherfee_data['cost'],          //原金额
                    'currency_code'         => $otherfee_data['currency_code'], //原币种
                    'currency_rate'         => $otherfee_rate,
                    'bp_chargeable_time'    => $date,
                    'bp_note'               => $_otherfee_mix_arr[$otherfee_name]['binote'],
                );
                $cost_detail = array(
                    'cost_amount_org'               => $otherfee_data['cost'],                              //成本金额（原始）
                    'cost_currency_code_org'        => $otherfee_data['currency_code'],                     //成本币种（原始）
                    'cost_amount_sp'                => $convert_fee,                                        //成本金额（服务商）
                    'cost_currency_code_sp'         => $spArr[$otherfee_data['sp_code']],                   //成本币种（服务商）
                    'sp_code'                       => $otherfee_data['sp_code'],                           //服务商代码
                );
            }

            if(!empty($cost_detail)){
                $fee_cost_common    = array(
                    'code_number'                   => $order_code,                                         //单号
                    'code_type'                     => 1,                                                   //单号类型（1:区内单 2：区外单 3：ASN单）
                    'customer_code'                 => $aOrder['customer_code'],                            //客户代码
                    'reference_no'                  => $aOrder['reference_no'],                             //客户参考号
                    'tracking_number'               => $aShipOrder['tracking_number'],                      //服务商单号（跟踪号）
                    'sm_code'                       => $aOrder['sm_code'],                                  //运输方式代码
                    'country_code'                  => $countryArr['country_code'],                         //国际简称（二字码）
                    'fee_code'                      => $_otherfee_mix_arr[$otherfee_name]['ftcode'],        //费用编号
                    'fee_name'                      => $_otherfee_mix_arr[$otherfee_name]['binote'],        //费用名称
                    'fee_amount_org'                => $otherfee_data['price'],                             //费用金额（原始）
                    'fee_currency_code_org'         => $otherfee_data['currency_code'],                     //费用币种（原始）
                    'price_batch_number'            => $aCalculate['data']['cost']['price_batch_number'],   //运输价格编号
                    'currency_batch_number'         => $currency_batch_number,                              //货币汇率编号
                    'fee_time_recalculate'          => $date,                                               //重新扣费时间
                    'ip_recalculate'                => $remote_ip,                                          //重新扣费操作IP
                    'operator_recalculate'          => $userAuth->user['user_name'],                         //重新扣费操作人
                );
                $fee_cost_detail[]  = array_merge($cost_detail, $fee_cost_common);
            }
        }
        /* 扣其它费用 End */


        //业务数据
        $businessArr = array(
            'ds_code'                   => 'so',
            'customer_code'             => $aOrder['customer_code'],
            'warehouse_id'              => $aOrder['warehouse_id'],
            'sm_code'                   => $aOrder['sm_code'],
            'bb_volume_weight'          => $aShipOrder['so_vol_weight'],
            'bb_charge_weight'          => $aShipOrder['so_weight'],
            'bb_delivered_weight'       => $aShipOrder['so_weight'],
            'bb_pieces'                 => $aOrder['parcel_quantity'],
            'bb_declared_value'         => $aOrder['parcel_declared_value'],
            'bb_declared_currency_code' => 'USD',
            'country_code'              => $countryArr['country_code'],
            'bb_postcode'               => $aAddress['oab_postcode'],
            'bb_charge_time'            => $aOrder['add_time'],
            'bb_declared_time'          => $date, //发货时间 此时间与服务商对接
            'bb_sales_id'               => $customerArr['customer_saler_user_id'],
            'bb_refer_code'             => $aOrder['order_code'],
            'bb_service_number'         => $aOrder['ref_tracking_number'],//ref_tracking_number
            'bb_reference_no'           => $aOrder['reference_no'],
        );
        $bsObj          = new Process_Business();
        $businessResult = $bsObj->businessFee($businessArr, $incomeArr, $paymentArr);
        if($businessResult['state']!='1'){
            return $businessResult['message'];
        }
        //更新 费用及成本明细表
        $feecostdetailResult = Service_FeeCostDetail::updateMultiRows($fee_cost_detail);
        return true;

    }





    /**
     * @desc 全部重新计费
     */
    public function batchReadjustmentPayment($condition = array())
    {
        $result = array('success' => 0, 'fail' => 0, 'params' => array());
        $condition['bp_status'] = 2;
        $condition['bp_create_type'] = '0';
        $condition['ds_code_arr'] = array('so','lo');
        $successCnt = 0;
        $failCnt = 0;

        $total = Table_BilPayment::getInstance()->getGroupByCondition($condition, "count(*)");
        $loop = 0;
        $pageSize = 200; //每次三百,遍历处理
        $pageCount = ceil($total / $pageSize);

        $obj = new Process_BusinessPayment();
        while ($loop < $pageCount) {
            $loop++;
            $rows = Table_BilPayment::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'],
                );
                $result = $obj->readjustmentPaymentTransaction($param);
                if (isset($result['state']) && $result['state'] == '1') {
                    $successCnt++;
                } else {
                    $failCnt++;
                }
            }
        }
        $result['success'] = $successCnt;
        $result['fail'] = $failCnt;
        $result['params'] = $condition;
        return $result;
    }
    
    /**
     * @desc 区外订单 重新计费 应付
     * @param array $param
     * @throws Exception
     */
    public function readjustmentForOutsideOrder($param = array())
    {
        //参数
        $code = isset($param['refer_code']) ? $param['refer_code'] : '0';
        $createType = isset($param['createType']) ? $param['createType'] : '0';


        $businessArr = Service_BilBusiness::getAttrByRefCode($code);
        $customerArr = Service_Customer::getByField($businessArr['customer_code'], 'customer_code', array('customer_code', 'customer_id', 'customer_currency'));

        if (strtolower($businessArr['ds_code']) != 'lo') {
            throw new Exception("业务必须为区外订单");
        }

        if (strtolower($businessArr['bb_status']) == 'n') {
            throw new Exception("此业务费用已作废,不允许操作");
        }

        //重量未更新，无须重新计费
        $aLoOrder = Service_ReceivingBatchOrder::getByField($code, 'logistics_code');
        if($aLoOrder['lo_service_provider_weight'] <= $aLoOrder['weight']){
            throw new Exception('订单'.$code.'服务商重量未更新，无须重新计费');
        }

        //删除数据
        $create_type_arr = $createType == '0' ? array(0) : array(0, 1);
        $iCondition = array(
            'bb_id' => $businessArr['bb_id'],
            'bp_status' => 2, //考虑到可能部分已出帐的问题
            'bp_create_type_arr' => $create_type_arr,
        );
        //费用集合
        $feeArr = array();
        $pRows = Table_BilPayment::getInstance()->getByCondition($iCondition, '*', 0, 0);
        //清理原费用
        if (!empty($pRows)) {
            foreach ($pRows as $row) {
                Table_BilPayment::getInstance()->delete($row['bp_id'], 'bp_id');
            }
        }
        //新费用
        $this->outsideCost($businessArr['bb_refer_code']);
    }
    
    /**
     * @desc 计算区外仓订单成本
     * @param string $order_code
     * @return bool|string
     * @throws Exception
     */
    public function outsideCost($order_code = '')
    {
        $orderRow = Service_LogisticsOrder::getByField($order_code, 'logistics_code');
        $customer_id = $orderRow['customer_code'];
        $customerRow = Service_Customer::getByField($customer_id);
        $currencyRow = Service_Currency::getByField($customerRow['customer_currency'], 'currency_code');
        $addressRow = Service_LogisticsOrderAddress::getByField($order_code, 'logistics_code');
        $orderHsRow = Service_LogisticsOrderHs::getByField($order_code, 'logistics_code');
        $orderDetailRow = Service_ReceivingBatchOrder::getByField($order_code, 'logistics_code');
        $sDate = $orderDetailRow['add_time'];
        //取实际计费的那个重量值
        $realWeight = ($orderDetailRow['lo_service_provider_weight'] > $orderDetailRow['weight'])? $orderDetailRow['lo_service_provider_weight'] : $orderDetailRow['weight'];

        //国家简码
        $countryArr = Service_Country::getByField($addressRow['loa_country'],'country_id');
        //业务员
        $customerArr = Service_Customer::getByField($orderRow['customer_code'],'customer_code',array('customer_saler_user_id','customer_currency'));
        //运输方式
        $shippingMethodArr = Service_ShippingMethod::getByField($orderRow['sm_code'],'sm_code',array('sm_vol_rate'));

        //应付
        $paymentArr=array();
        
        //写入业务表
        $_bb_volumne_weight = (1 == $shippingMethodArr['sm_is_volume'])? (($orderDetailRow['length'] * $orderDetailRow['width'] * $orderDetailRow['height']) / $shippingMethodArr['sm_vol_rate']) : 0;
        $businessArr = array(
            'ds_code' => 'lo',
            'customer_code' => $orderRow['customer_code'],
            'warehouse_id' => $orderRow['warehouse_id'],
            'sm_code' => $orderRow['sm_code'],
            'bb_volume_weight' => $_bb_volumne_weight,
            'bb_charge_weight' => $orderRow['lo_weight'],
            'bb_delivered_weight' => $orderRow['lo_weight'],
            'bb_pieces' => $orderHsRow['loh_quantity'],
            'bb_declared_value' => $orderHsRow['loh_total_price'],
            'bb_declared_currency_code' => 'USD',
            'country_code' => $countryArr['country_code'],
            'bb_postcode' => $addressRow['loa_zipcode'],
            'bb_charge_time' => $orderRow['lo_create_time'],
            'bb_declared_time' => $sDate, //发货时间 此时间与服务商对接
            'bb_sales_id' => $customerArr['customer_saler_user_id'],
            'bb_refer_code' => $orderRow['logistics_code'],
            'bb_service_number' => $orderRow['ref_tracking_number'],//ref_tracking_number
            'bb_reference_no' => $orderRow['reference_no'],
        );

        $spArr = array();
        $objCalculate = new Common_CalculateShipping();

        $keys = array(
            'warehouseId' => $orderRow['warehouse_id'],
            'countryId' => $addressRow['loa_country'],
            'smCode' => $orderRow['sm_code'],
            'weight' => $realWeight,
            'customerCode' => $orderRow['customer_code'],
        );
        $objCalculate->setParams($keys);
        $aCalculate = $objCalculate->getRate();
        if($aCalculate['state'] == 0) {
            return is_array($aCalculate['error']) ? implode(',', $aCalculate['error']) : $aCalculate['error'];
        }
        $fee = $aCalculate['data']['cost']['totalCost'];

        //生成一条成本费用的记录
        $sm = $aCalculate['data']['sm'];;
        //成本费
        $costFee = $aCalculate['data']['cost']['cost'];
        //单票成本
        $ticket_cbcost = isset($aCalculate['data']['cost']['one_ticket_cbcost'])?$aCalculate['data']['cost']['one_ticket_cbcost']:0;
        //燃油附加费
        //$fuel_addons = $aCalculate['data']['cost']['cost']*$sm['sm_baf'];
        $fuel_addons = $aCalculate['data']['cost']['cost_baf'];
        if($sm['sm_class_code']=="CRP"||$sm['sm_class_code']=="CPS"){
            $total = $aCalculate['data']['cost']['cost'] + $ticket_cbcost ;
            $fuel_addons = 0;
        }else{
            $total = $aCalculate['data']['cost']['cost']  + $fuel_addons;
        }
        $costRecording = array(
            'order_code'=>$order_code,
            'customer_code'=>$orderRow['customer_code'],
            'reference_no'=>$orderRow['reference_no'],
            'tracking_number'=>$orderRow['ref_tracking_number'],
            'sm_code'=>$orderRow['sm_code'],
            'country_id'=>$addressRow['loa_country'],
            'weight'=>$realWeight,
            'cost_fee'=>$costFee,
            'ticket_fare'=>$ticket_cbcost,
            'fuel_addons'=>$fuel_addons,
            'total_fee'=>$total,
            'currency_code'=>$aCalculate['data']['cost']['cost_currency_code'],
            'add_time'=>$sDate,
        );
        //重新计费的情况
        $cRow = Service_CostRecording::getByField($order_code, 'order_code');
        if (empty($cRow)) {
            Service_CostRecording::add($costRecording);
        } else {
            Service_CostRecording::update($costRecording, $cRow['cr_id'], 'cr_id');
        }
        
        //区外仓理论上不存在自有运输方式，都将进入这个非自有逻辑判断
        if('0' == $aCalculate['data']['sm']['sm_channel']){
            /**
            * 1、应付
            */
            //运费（未包括其它费用项）
            if ($costFee > 0) {
                if (!isset($spArr[$sm['sp_code']])) {
                    $spRow = Service_ServiceProvider::getByField($sm['sp_code'], 'sp_code');
                    $spArr[$sm['sp_code']] = $spRow['currency_code'];
                }
                $convert_fee = Service_Currency::converByCode($aCalculate['data']['cost']['cost_currency_code'], $spArr[$sm['sp_code']], $costFee);
                $paymentArr[] = array(
                    'sp_code' => $sm['sp_code'], //服务商代码
                    'ft_code' => 'shipping',
                    'ut_code' => 'KG',
                    'sm_code' => $orderRow['sm_code'],
                    'bp_amount' => $convert_fee,
                    'bp_org_amount' => $costFee, //原金额
                    'currency_code' => $aCalculate['data']['cost']['cost_currency_code'],
                    'currency_rate' => $aCalculate['data']['cost']['currency_rate'],
                    'bp_chargeable_time' => $sDate,
                );
            }

            //单票
            if($ticket_cbcost > 0){
                if (!isset($spArr[$sm['sp_code']])) {
                    $spRow = Service_ServiceProvider::getByField($sm['sp_code'], 'sp_code');
                    $spArr[$sm['sp_code']] = $spRow['currency_code'];
                }
                $convert_fee = Service_Currency::converByCode($aCalculate['data']['cost']['cost_currency_code'], $spArr[$sm['sp_code']], $ticket_cbcost);
                $paymentArr[]=array(
                    'sp_code'=>$sm['sp_code'],//服务商代码
                    'ft_code'=>'one_ticket_fee',
                    'ut_code'=>'PCE',
                    'sm_code'=>$orderRow['sm_code'],
                    'bp_amount'=>$convert_fee,
                    'bp_org_amount' => $ticket_cbcost, //原金额
                    'currency_code'=>$aCalculate['data']['cost']['cost_currency_code'],
                    'currency_rate'=>$aCalculate['data']['cost']['currency_rate'],
                    'bp_chargeable_time'=>$sDate,
                );
            }

            //燃油附加费用
            if($fuel_addons>0){
                if (!isset($spArr[$sm['sp_code']])) {
                    $spRow = Service_ServiceProvider::getByField($sm['sp_code'], 'sp_code');
                    $spArr[$sm['sp_code']] = $spRow['currency_code'];
                }
                $convert_fee = Service_Currency::converByCode($aCalculate['data']['cost']['cost_currency_code'], $spArr[$sm['sp_code']], $fuel_addons);
                $paymentArr[]=array(
                    'sp_code'=>$sm['sp_code'],//服务商代码
                    'ft_code'=>'additional_fee',
                    'ut_code'=>'PCE',
                    'sm_code'=>$orderRow['sm_code'],
                    'bp_amount'=>$convert_fee,
                    'bp_org_amount'=>$fuel_addons,//原金额
                    'currency_code'=>$aCalculate['data']['cost']['cost_currency_code'],
                    'currency_rate'=>$aCalculate['data']['cost']['currency_rate'],
                    'bp_chargeable_time'=>$sDate,
                );
            }
            /**
             * End 应付
             */
            
             //业务数据
            $bsObj = new Process_Business();
            $businessResult=$bsObj->businessFee($businessArr,array(),$paymentArr);
            if($businessResult['state']!='1'){
                return $businessResult['message'];
            }
        }

        return true;

    }


}