<?php

/**
 * @desc 财务处理类
 */
class Process_Financial
{
    protected $_date = "";
    protected $_userId = "";

    public function __construct()
    {
        $this->_userId = Service_User::getUserId();
        $this->_date = date('Y-m-d H:i:s');
    }

    /**
     * @desc 验证帐户信息
     * @param string $soCode
     * @param string $payerCode
     * @return array|mixed
     * @throws Exception
     */
    public function checkAccount($soCode = '', $payerCode = '')
    {
        $row = array();
        switch (strtolower($soCode)) {
            case 'cm':
                $row = Service_Customer::getByField($payerCode, 'customer_code');
                if (empty($row)) {
                    throw new Exception("客户代码不存在");
                }
                //统一
                $row['currency_code'] = $row['customer_currency'];
                break;
            case 'su':
                $row = Process_SupplierFeeProcess::getSupplier($payerCode);
                if (empty($row)) {
                    throw new Exception("供应商代码不存在");
                }
                break;
            case 'sp':
                $row = Service_ServiceProvider::getByField($payerCode, 'sp_code');
                if (empty($row)) {
                    throw new Exception("服务商代码不存在");
                }
                break;
            default:
                throw new Exception("结算对象类型异常");
                break;
        }
        return $row;
    }

    /**
     * @desc 我司收款操作,写入收款通知
     * @param array $param
     * @param array $attach
     * @return array
     */
    public function receiptTransaction($param = array(), $attach = array())
    {
        $result = array("state" => 0, "message" => "", "data" => array());
        $result['data']['code'] = $param['payer_code'];

        $db = Common_Common::getAdapter();
        $db->beginTransaction();
        try {
            //验证帐户信息
            $this->checkAccount($param['so_code'], $param['payer_code']);
            //判断支付方式
            if (strtolower($param['pm_code']) == 'cash') {
                $attach = array();
            }
            $param['ftr_creator_id'] = isset($param['ftr_creator_id']) ? $param['ftr_creator_id'] : $this->_userId;
            $param['ftr_add_time'] = $this->_date;

            if (!$ftrId = Service_FeeTransferRecords::add($param)) {
                throw new Exception("保存数据异常");
            }
            //保存帐户信息
            if (!empty($attach)) {
                //是否保存付款方帐号信息
                if (isset($attach['save_payment_account']) && $attach['save_payment_account'] == '1') {
                    $paArr = array(
                        "payer_code" => $param['payer_code'],
                        "so_code" => $param['so_code'],
                        "fpa_payer_bank_name" => $attach['ftra_payer_bank_name'],
                        "fpa_payer_account_name" => $attach['ftra_payer_account_name'],
                        "fpa_payer_account" => $attach['ftra_payer_account'],
                        "fpa_creator_id" => $this->_userId,
                        "fpa_add_time" => $this->_date,
                        "fpa_update_time" => $this->_date,
                    );
                    if (isset($attach['fpa_id']) && $attach['fpa_id'] != '') {
                        unset($paArr['fpa_add_time']);
                        Service_FeePaymentAccount::update($paArr, $attach['fpa_id']);
                    } else {
                        Service_FeePaymentAccount::add($paArr);
                    }
                }

                $addAttach['ftr_id'] = $ftrId;
                $addAttach['ftra_payer_bank_name'] = $attach['ftra_payer_bank_name'];
                $addAttach['ftra_payer_account_name'] = $attach['ftra_payer_account_name'];
                $addAttach['ftra_payer_account'] = $attach['ftra_payer_account'];
                $addAttach['ftra_update_time'] = $this->_date;
                Service_FeeTransferRecordAttach::add($addAttach);
            }

            $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
     * @param array $attach
     * @return array
     */
    public function paymentTransaction($param = array(), $attach = array())
    {
        $result = array("state" => 0, "message" => "", "data" => array());
        $result['data']['code'] = $param['payer_code'];

        $db = Common_Common::getAdapter();
        $db->beginTransaction();
        try {
            //验证帐户信息
            $this->checkAccount($param['so_code'], $param['payer_code']);
            //判断支付方式
            if (strtolower($param['pm_code']) == 'cash') {
                $attach = array();
            }
            $param['fpr_creator_id'] = isset($param['fpr_creator_id']) ? $param['fpr_creator_id'] : $this->_userId;
            $param['fpr_add_time'] = $this->_date;
            $param['fpr_confirm_time'] = $this->_date; //直接确认
            //金额
            if ($param['fpr_amount'] == '0' || $param['fpr_amount'] < 0) {
                throw new Exception("金额异常");
            }
            //判断金额是否超出
            switch (strtolower($param['so_code'])) {
                case 'sp':
                    if ($param['bill_id'] != '') {
                        $billRow = Service_BilServeBill::getByField($param['bill_id'], 'bsb_id');
                        if (empty($billRow)) {
                            throw new Exception("没有找到匹配的帐单");
                        }
                        if ($billRow['bsb_writeoff_sign'] == 'y') {
                            throw new Exception("帐单已核销");
                        }
                        //已核销金额
                        $payAmount = Table_BilServeBillBalanceRecords::getInstance()->getTotal($param['bill_id']);
                        $payAmount = empty($payAmount) ? 0 : $payAmount;
                        //已申请未支付金额
                        $noPay = Table_FeePaymentRecords::getInstance()->getTotalByBill($param['bill_id'], array(1));
                        $noPay = empty($noPay) ? 0 : $noPay;

                        $applyAmount = $billRow['bsb_amount'] - $noPay - $payAmount;
                        if (round($param['fpr_amount'], 3) > round($applyAmount, 3)) {
                            throw new Exception("支付金额不允许超出未支付金额:" . $applyAmount);
                        }
                        $param['bill_id'] = ','.$param['bill_id'].',';
                    }
                    
                    break;
            }

            if (!$ftrId = Service_FeePaymentRecords::add($param)) {
                throw new Exception("保存数据异常");
            }
            //保存帐户信息
            if (!empty($attach)) {
                //是否保存付款方帐号信息
                if (isset($attach['save_payment_account']) && $attach['save_payment_account'] == '1') {
                    $paArr = array(
                        "payer_code" => $param['payer_code'],
                        "so_code" => $param['so_code'],
                        "fpa_payer_bank_name" => $attach['ftra_payer_bank_name'],
                        "fpa_payer_account_name" => $attach['ftra_payer_account_name'],
                        "fpa_payer_account" => $attach['ftra_payer_account'],
                        "fpa_creator_id" => $this->_userId,
                        "fpa_add_time" => $this->_date,
                        "fpa_update_time" => $this->_date,
                    );
                    if(strtolower($param['so_code'])=='cm'){
                        $condition=array(
                            'payer_code'=>$param['payer_code']
                        );
                        $showFields=array(
                            'fpa_id'
                        );
                        $table_obj=new Service_FeePaymentAccount();
                        $rows=$table_obj->getByCondition($condition,$showFields);
                        if(count($rows)){
                            Service_FeePaymentAccount::update($paArr, $rows[0]['fpa_id']);
                        }else{
                            Service_FeePaymentAccount::add($paArr);
                        }
                    }else{
                        if (isset($attach['fpa_id']) && $attach['fpa_id'] != '') {
                            unset($paArr['fpa_add_time']);
                            Service_FeePaymentAccount::update($paArr, $attach['fpa_id']);
                        } else {
                            Service_FeePaymentAccount::add($paArr);
                        }
                    }
                }

                $addAttach['fpr_id'] = $ftrId;
                $addAttach['fpra_payee_bank_name'] = $attach['ftra_payer_bank_name'];
                $addAttach['fpra_payee_account_name'] = $attach['ftra_payer_account_name'];
                $addAttach['fpra_payee_account'] = $attach['ftra_payer_account'];
                $addAttach['fpra_update_time'] = $this->_date;
                Service_FeePaymentRecordAttach::add($addAttach);
            }

            $db->commit();
            $result['state'] = 1;
            $result['message'] = '操作成功';
        } catch (Exception $e) {
            $db->rollBack();
            $result['state'] = 0;
            $result['message'] = $e->getMessage();
        }
        return $result;
    }
	
    /**
     * 批量付款事物 - simple 08-28
     * @param array $param 付款通知信息数组
     * @param array $attach	银行卡信息数组
     * @throws Exception
     * @return array $result 状态信息数组
     */
	public function bulkPaymentTransaction($param = array(), $attach = array())
    {
        $result = array("state" => 0, "message" => "", "data" => array());
        $result['data']['code'] = $param['payer_code'];

        $db = Common_Common::getAdapter();
        $db->beginTransaction();
        try {
            //验证帐户信息
            $this->checkAccount($param['so_code'], $param['payer_code']);
            //判断支付方式--银行卡信息保存标志
            if (strtolower($param['pm_code']) == 'cash') {
                $attach = array();
            }
            $param['fpr_creator_id'] = isset($param['fpr_creator_id']) ? $param['fpr_creator_id'] : $this->_userId;
            $param['fpr_add_time'] = $this->_date;
            $param['fpr_confirm_time'] = $this->_date; //直接确认--填入确认时间
            //金额
            if ($param['fpr_amount'] == '0' || $param['fpr_amount'] < 0) {
                throw new Exception("金额异常");
            }
            //判断金额是否超出
            switch (strtolower($param['so_code'])) {
                case 'sp':
                    if ($param['bill_id'] != '') {
                    	//去除两边的逗号
                    	//$param['bill_id'] = trim($param['bill_id'], ',');
                    	//多个对账单
                    	$billIds = explode(',', trim($param['bill_id'],','));
                    	if(!empty($billIds) && is_array($billIds)){
                    		$applyAmounts = array();
                    		foreach ($billIds as $billKey=>$billId){
		                        $billRow = Service_BilServeBill::getByField($billId, 'bsb_id');
		                        if (empty($billRow)) {
		                            throw new Exception("没有找到ID为".$billId."匹配的帐单!");
		                        }
		                        if ($billRow['bsb_writeoff_sign'] == 'y') {
		                            throw new Exception("帐单ID为".$billId."的账单已核销!");
		                        }
		                        //已核销金额
		                        $payAmount = Table_BilServeBillBalanceRecords::getInstance()->getTotal($billId);
		                        $payAmount = empty($payAmount) ? 0 : $payAmount;
		                        //已申请未支付金额
		                        $noPay = Table_FeePaymentRecords::getInstance()->getTotalByBill($billId, array(1));
		                        $noPay = empty($noPay) ? 0 : $noPay;
		                        
		                        $applyAmount = $billRow['bsb_amount'] - $noPay - $payAmount;
		                        $applyAmounts[] = $applyAmount;
                    		}
                    		if (round($param['fpr_amount'], 3) > round(array_sum($applyAmounts), 3)) {
                    			throw new Exception("支付金额不允许超出未支付金额:" . $applyAmount);
                    		}
                    	}
                    }
                    break;
            }
            if (!$ftrId = Service_FeePaymentRecords::add($param)) {
                throw new Exception("保存数据异常");
            }
            //保存帐户信息
            if (!empty($attach)) {
                //是否保存付款方帐号信息
                /*
            	if (isset($attach['save_payment_account']) && $attach['save_payment_account'] == '1') {
                    $paArr = array(
                        "payer_code" => $param['payer_code'],
                        "so_code" => $param['so_code'],
                        "fpa_payer_bank_name" => $attach['ftra_payer_bank_name'],
                        "fpa_payer_account_name" => $attach['ftra_payer_account_name'],
                        "fpa_payer_account" => $attach['ftra_payer_account'],
                        "fpa_creator_id" => $this->_userId,
                        "fpa_add_time" => $this->_date,
                        "fpa_update_time" => $this->_date,
                    );
                    if (isset($attach['fpa_id']) && $attach['fpa_id'] != '') {
                        unset($paArr['fpa_add_time']);
                        Service_FeePaymentAccount::update($paArr, $attach['fpa_id']);
                    } else {
                        Service_FeePaymentAccount::add($paArr);
                    }
                }
                */
                $addAttach['fpr_id'] = $ftrId;
                $addAttach['fpra_payee_bank_name'] = $attach['ftra_payer_bank_name'];
                $addAttach['fpra_payee_account_name'] = $attach['ftra_payer_account_name'];
                $addAttach['fpra_payee_account'] = $attach['ftra_payer_account'];
                $addAttach['fpra_update_time'] = $this->_date;
                Service_FeePaymentRecordAttach::add($addAttach);
            }
            $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 transferRecordsVerifyTransaction($param = array())
    {
        $result = array("state" => 0, "message" => "", "data" => array(), 'param' => $param);

        $db = Common_Common::getAdapter();
        $db->beginTransaction();
        try {
            $opType = $param['opType'];
            $ftrId = $param['ftr_id'];
            $desc = $param['desc'];
            //$amount = $param['amount'];
            $amount_real = $param['amount_real'];

            $ffrRow = Service_FeeTransferRecords::getJoinLeftByField($ftrId);
            if (empty($ffrRow)) {
                throw new Exception("数据异常");
            }

            if ($ffrRow['ftr_status'] != '1') {
                throw new Exception("状态异常不允许操作");
            }

            switch ($opType) {
                case '1': //审核通过
                    //if (!is_numeric($amount) || $amount < 0) {
                    //    throw new Exception("金额异常");
                    //}
                    if (!is_numeric($amount_real) || $amount_real < 0) {
                        throw new Exception("实收金额异常");
                    }
                    //验证帐户信息
                    $accountRow = $this->checkAccount($ffrRow['so_code'], $ffrRow['payer_code']);
                    $currencyCode = $accountRow['currency_code'];
                    if ($currencyCode == '') {
                        throw new Exception("币种异常");
                    }

                    //更新收款通知状态
                    $upRow = array(
                        'ftr_status' => 2,
                        'ftr_amount_real' => $amount_real,
                        'ftr_desc' => $desc,
                        'ftr_verify_id' => $this->_userId,
                        'ftr_update_time' => $this->_date,
                        'ftr_verify_time' => $this->_date,
                    );
                    Service_FeeTransferRecords::update($upRow, $ffrRow['ftr_id'], 'ftr_id');

                    //将金额转为客户币种
                    $cArr = self::changeCurrency($amount_real, $ffrRow['ftr_currency_code'], $currencyCode);
                    if (!is_array($cArr)) {
                        throw new Exception($cArr);
                    }
                    $value = $cArr['value'];
                    $addArr = array(
                        'apr_type' => 1,
                        'payer_code' => $ffrRow['payer_code'],
                        'so_code' => $ffrRow['so_code'],
                        'pm_code' => $ffrRow['pm_code'],
                        'apr_transaction_no' => $ffrRow['ftr_transaction_no'],
                        'ba_id' => $ffrRow['ba_id'],
                        'ftr_id' => $ffrRow['ftr_id'],
                        'apr_amount' => $value,
                        'apr_org_amount' => $amount_real,
                        'apr_currency_code' => $ffrRow['ftr_currency_code'],
                        'apr_settle_sign' => strtolower($ffrRow['so_code']) == 'cm' ? 'y' : 'n', //只有客户的收款参考帐单核销
                        'apr_inneroffset_sign' => strtolower($ffrRow['so_code']) == 'cm' ? 'n' : 'y', //非客户时用于内部核销
                        'apr_currency_rate' => $cArr['org_rate'],
                        'apr_note' => $desc,
                        'apr_creator_id' => $this->_userId,
                        'bill_id' => '',
                        'apr_create_type' => 0,
                        'apr_transaction_time' => $ffrRow['ftr_payin_time'],
                        'apr_add_time' => $this->_date,
                        'apr_update_time' => $this->_date,
                    );
                    if (!$apr_id = Service_AccountPaymentRecords::add($addArr)) {
                        throw new Exception("写入收款数据错误");
                    }

                    if (isset($ffrRow['ftra_id']) && $ffrRow['ftra_id'] != '') {
                        $attachArr = array(
                            'apr_id' => $apr_id,
                            'apra_payee_bank_name' => $ffrRow['ftra_payer_bank_name'],
                            'apra_payee_account_name' => $ffrRow['ftra_payer_account_name'],
                            'apra_payee_account' => $ffrRow['ftra_payer_account'],
                            'apra_update_time' => $this->_date,
                        );
                        Service_AccountPaymentRecordsAttach::add($attachArr);
                    }
                    //操作余额
                    switch (strtolower($ffrRow['so_code'])) {
                        case 'cm':
                            //客户入款应在
                            $fee[] = array(
                                'cbl_type' => '3',
                                'cbl_value' => $value,
                                'currency_code' => $currencyCode,
                                'release_value' => '0',
                                'currency_rate' => '',
                                'user_id' => $this->_userId,
                                'cbl_refer_code' => $addArr['apr_transaction_no'],
                                'application_code' => 'Verify',
                                'fee_id' => '0',
                                'cbl_note' => ''
                            );
                            $feeObj = new Common_CustomerFeeProcess();
                            $feeReturn = $feeObj->payment($ffrRow['payer_code'], $fee, 1);
                            if ($feeReturn['state'] != '1') {
                                throw new Exception(isset($feeReturn['message']) ? $feeReturn['message'] : 'Payment Fee Fail.');
                            }
                            break;
                        case 'su':
                            $fee[] = array(
                                'spbl_type' => '1', //入款
                                'spbl_value' => $value,
                                'spbl_currency_code' => $currencyCode,
                                'spbl_currency_rate' => '',
                                'user_id' => $this->_userId,
                                'spbl_refer_code' => $addArr['apr_transaction_no'],
                                'application_code' => '',
                                'spbl_note' => 'Verify',
                                'spbl_transaction_number' => '',
                            );
                            $feeObj = new Process_SupplierFeeProcess();
                            $feeReturn = $feeObj->payment($ffrRow['payer_code'], $fee);
                            if ($feeReturn['state'] != '1') {
                                throw new Exception(isset($feeReturn['message']) ? $feeReturn['message'] : 'Payment Fee Fail.');
                            }
                            break;
                        case 'sp':
                            $fee[] = array(
                                'spbl_type' => '1',
                                'spbl_value' => $value,
                                'spbl_currency_code' => $currencyCode,
                                'spbl_currency_rate' => '',
                                'user_id' => $this->_userId,
                                'spbl_refer_code' => $addArr['apr_transaction_no'],
                                'application_code' => '',
                                'spbl_note' => 'Verify',
                                'spbl_transaction_number' => '',
                            );
                            $feeObj = new Process_ServiceProviderFeeProcess();
                            $feeReturn = $feeObj->payment($ffrRow['payer_code'], $fee);
                            if ($feeReturn['state'] != '1') {
                                throw new Exception(isset($feeReturn['message']) ? $feeReturn['message'] : 'Payment Fee Fail.');
                            }
                            break;
                    }
                    break;

                case '2': //作废收款通知状态
                    $upRow = array(
                        'ftr_status' => 0,
                        'ftr_amount_real' => $amount_real,
                        'ftr_desc' => $desc,
                        'ftr_dishonour_id' => $this->_userId,
                        'ftr_update_time' => $this->_date,
                        'ftr_dishonour_time' => $this->_date,
                    );
                    Service_FeeTransferRecords::update($upRow, $ftrId, 'ftr_id');
                    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 $value 转换金额
     * @param $orgCode 原始货币CODE
     * @param $disCode 目的货币CODE
     * @param int $orgRate 自定义原货币汇率
     * @param int $disRate 自定义目的原货币汇率
     * @return array/string  string=>则表示转换失败
     */
    public static function changeCurrency($value, $orgCode, $disCode, $orgRate = 0, $disRate = 0)
    {
        $orgCode = strtoupper($orgCode);
        $disCode = strtoupper($disCode);
        $currencyRows = Service_Currency::getByCondition(array(), array('currency_code', 'currency_rate'));
        foreach ($currencyRows as $key => $val) {
            $currencyRows[$val['currency_code']] = $val['currency_rate'];
        }
        if ($orgRate != 0 && $orgRate != '') {
            $org_rate = $orgRate;
        } else {
            $org_rate = isset($currencyRows[$orgCode]) ? $currencyRows[$orgCode] : 0;
        }
        if ($disRate != 0 && $disRate != '') {
            $dis_rate = $disRate;
        } else {
            $dis_rate = isset($currencyRows[$disCode]) ? $currencyRows[$disCode] : 0;
        }
        if ($orgCode == $disCode) {
            $result['value'] = $value;
            $result['currency_code'] = $disCode;
            $result['org_code'] = $orgCode;
            $result['org_rate'] = $org_rate;
            $result['dis_rate'] = $org_rate;
            $result['rate'] = 1;
            return $result;
        }

        if (!isset($currencyRows[$orgCode]) || !isset($currencyRows[$disCode])) {
            $result = 'Can not find origin/destination currency code';
        } else {
            //取小数后两位，不作四舍五入
            $result['org_rate'] = $org_rate;
            $result['dis_rate'] = $dis_rate;
            $result['rate'] = sprintf("%.5f", $org_rate / $dis_rate);
            $result['value'] = sprintf("%.3f", $value * $result['rate']);
            $result['currency_code'] = $disCode;
            $result['org_code'] = $orgCode;
        }
        return $result;
    }


    /**
     * @desc 审核付款通知、通过审核转入客户余额 \写入客户付款记录
     * @param array $param
     * @return array
     */
    public function paymentRecordsVerifyTransaction($param = array())
    {
        $result = array("state" => 0, "message" => "", "data" => array(), 'param' => $param);

        $db = Common_Common::getAdapter();
        $db->beginTransaction();
        try {
            $opType = $param['opType'];
            $fId = $param['fpr_id'];
            $desc = $param['desc'];
            $amount = $param['amount'];

            $ffrRow = Service_FeePaymentRecords::getJoinLeftByField($fId);
            if (empty($ffrRow)) {
                throw new Exception("数据异常");
            }
            if ($ffrRow['fpr_status'] != '1') {
                throw new Exception("状态异常不允许操作");
            }
            $amount = $ffrRow['fpr_amount'];
            switch ($opType) {
            	//审核通过--确认付款
                case '1': 
                    //验证帐户信息
                    $accountRow = $this->checkAccount($ffrRow['so_code'], $ffrRow['payer_code']);
                    $currencyCode = $accountRow['currency_code'];
                    if ($currencyCode == '') {
                        throw new Exception("币种异常");
                    }
                    //更新付款通知状态
                    $upRow = array(
                        'fpr_status' => 2,
                        'fpr_desc' => $desc,
                        'fpr_payer_id' => $this->_userId,
                        'fpr_update_time' => $this->_date,
                        'fpr_payin_time' => $this->_date,
                    );
                    Service_FeePaymentRecords::update($upRow, $ffrRow['fpr_id'], 'fpr_id');

                    //将金额转为客户币种
                    $cArr = self::changeCurrency($amount, $ffrRow['fpr_currency_code'], $currencyCode);
                    if (!is_array($cArr)) {
                        throw new Exception($cArr);
                    }

                    $fpr_payin_time = strtotime($ffrRow['fpr_payin_time']);

                    $value = $cArr['value'];
                    $addArr = array(
                        'apr_type' => 2, //付款
                        'payer_code' => $ffrRow['payer_code'],
                        'so_code' => $ffrRow['so_code'],
                        'pm_code' => $ffrRow['pm_code'],
                        'apr_transaction_no' => $ffrRow['fpr_transaction_no'],
                        'ba_id' => $ffrRow['ba_id'],
                        'ftr_id' => $ffrRow['fpr_id'], //来源ID
                        'apr_amount' => $value,
                        'apr_org_amount' => $amount,
                        'apr_currency_code' => $ffrRow['fpr_currency_code'],
                        'apr_settle_sign' => strtolower($ffrRow['so_code']) == 'cm' ? 'n' : 'y', ////非客户时 才能进行核销
                        'apr_inneroffset_sign' => strtolower($ffrRow['so_code']) == 'cm' ? 'y' : 'n', //非客户时用于内部核销
                        'apr_currency_rate' => $cArr['org_rate'],
                        'apr_note' => $desc,
                        'apr_creator_id' => $this->_userId,
                        'bill_id' => trim($ffrRow['bill_id'],','),
                        'apr_create_type' => 0,
                        'apr_transaction_time' => $fpr_payin_time == '' ? $this->_date : $ffrRow['fpr_payin_time'],
                        'apr_add_time' => $this->_date,
                        'apr_update_time' => $this->_date,
                    );
                    if (!$apr_id = Service_AccountPaymentRecords::add($addArr)) {
                        throw new Exception("写入付款数据错误");
                    }

                    if (isset($ffrRow['fpra_id']) && $ffrRow['fpra_id'] != '') {
                        $attachArr = array(
                            'apr_id' => $apr_id,
                            'apra_payee_bank_name' => $ffrRow['fpra_payee_bank_name'],
                            'apra_payee_account_name' => $ffrRow['fpra_payee_account_name'],
                            'apra_payee_account' => $ffrRow['fpra_payee_account'],
                            'apra_update_time' => $this->_date,
                        );
                        Service_AccountPaymentRecordsAttach::add($attachArr);
                    }
                    
                    //操作余额
                    switch (strtolower($ffrRow['so_code'])) {
                        case 'cm':
                            $fee[] = array(
                                'cbl_type' => '2', //扣款
                                'cbl_value' => $value,
                                'currency_code' => $currencyCode,
                                'release_value' => '0',
                                'currency_rate' => '',
                                'user_id' => $this->_userId,
                                'cbl_refer_code' => $addArr['apr_transaction_no'],
                                'application_code' => 'Verify',
                                'fee_id' => '0',
                                'cbl_note' => ''
                            );
                            $feeObj = new Common_CustomerFeeProcess();
                            $feeReturn = $feeObj->payment($ffrRow['payer_code'], $fee);
                            if ($feeReturn['state'] != '1') {
                                throw new Exception(isset($feeReturn['message']) ? $feeReturn['message'] : 'Payment Fee Fail.');
                            }
                            //自动抵消
                            Process_Financial::accountInternalBalance($ffrRow['payer_code'], 'cm');
                            break;
                        case 'su':
                            $fee[] = array(
                                'spbl_type' => '2', //入款
                                'spbl_value' => $value,
                                'spbl_currency_code' => $currencyCode,
                                'spbl_currency_rate' => '',
                                'user_id' => $this->_userId,
                                'spbl_refer_code' => $addArr['apr_transaction_no'],
                                'application_code' => '',
                                'spbl_note' => 'Verify',
                                'spbl_transaction_number' => '',
                            );
                            $feeObj = new Process_SupplierFeeProcess();
                            $feeReturn = $feeObj->payment($ffrRow['payer_code'], $fee);
                            if ($feeReturn['state'] != '1') {
                                throw new Exception(isset($feeReturn['message']) ? $feeReturn['message'] : 'Payment Fee Fail.');
                            }
                            //更新采购单
                            $feeReturn = $feeObj->excuteConfirmPurchasePayment($ffrRow['fpr_id']);
                            if ($feeReturn['state'] != '1') {
                                throw new Exception(isset($feeReturn['message']) ? $feeReturn['message'] : 'Payment Fee Fail.');
                            }
                            break;
                        case 'sp':
                            $fee[] = array(
                                'spbl_type' => '2', //入款
                                'spbl_value' => $value,
                                'spbl_currency_code' => $currencyCode,
                                'spbl_currency_rate' => '',
                                'user_id' => $this->_userId,
                                'spbl_refer_code' => $addArr['apr_transaction_no'],
                                'application_code' => '',
                                'spbl_note' => 'Verify',
                                'spbl_transaction_number' => '',
                            );
                            $feeObj = new Process_ServiceProviderFeeProcess();
                            $feeReturn = $feeObj->payment($ffrRow['payer_code'], $fee);
                            if ($feeReturn['state'] != '1') {
                                throw new Exception(isset($feeReturn['message']) ? $feeReturn['message'] : 'Payment Fee Fail.');
                            }

                            //自动核销
                            if (!empty($ffrRow['bill_id']) && $ffrRow['bill_id'] != '0') {
                                $billIds = explode(',', trim($ffrRow['bill_id'], ','));
                                foreach ($billIds as $billId){
                                    $bilRow = Service_BilServeBill::getByField($billId, 'bsb_id');
                                    $oParam = array(
                                            'apr_id' => $apr_id,
                                            'code' => $bilRow['bsb_code'],
                                    );
                                    $obj = new Process_ServeBill();
                                    $wResult = $obj->writeOffBill($oParam);
                                    if ($wResult['state'] != '1') {
                                        throw new Exception($wResult['message']);
                                    }
                                }

                            	//多条核销
                            	/*if(strpos($ffrRow['bill_id'], ',') && !empty($ffrRow['bill_id_all']) && strpos($ffrRow['bill_id_all'], ',')){
                            		$billIds = explode(',', trim($ffrRow['bill_id'], ','));
                            		foreach ($billIds as $billId){
                            			$bilRow = Service_BilServeBill::getByField($billId, 'bsb_id');
                            			$oParam = array(
                            					'apr_id' => $apr_id,
                            					'code' => $bilRow['bsb_code'],
                            			);
                            			$obj = new Process_ServeBill();
                            			$wResult = $obj->writeOffBill($oParam);
                            			if ($wResult['state'] != '1') {
                            				throw new Exception($wResult['message']);
                            			}
                            		}
                            	//单条核销
                            	}else {
	                                $bilRow = Service_BilServeBill::getByField(trim($ffrRow['bill_id'],','), 'bsb_id');
	                                $oParam = array(
	                                    'apr_id' => $apr_id,
	                                    'code' => $bilRow['bsb_code'],
	                                );
	                                $obj = new Process_ServeBill();
	                                $wResult = $obj->writeOffBill($oParam);
	                                if ($wResult['state'] != '1') {
	                                    throw new Exception($wResult['message']);
	                                }
                            	}*/
                            }
                            break;
                    }
                    break;

                case '2': //作废收款通知状态
                    $upRow = array(
                        'fpr_status' => 0,
                        'fpr_desc' => $desc,
                        'fpr_dishonour_id' => $this->_userId,
                        'fpr_update_time' => $this->_date,
                        'fpr_dishonour_time' => $this->_date,
                    );
                    Service_FeePaymentRecords::update($upRow, $fId, 'fpr_id');
                    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 string $payerCode
     * @param string $soCode
     * @return bool
     * @throws Exception
     */
    public static function accountInternalBalance($payerCode = '', $soCode = 'cm')
    {
        $condition = array(
            'payer_code' => $payerCode,
            'so_code' => $soCode,
            'apr_type' => 2,
            'apr_writeoff_sign' => 'n',
        );

        $aprPaymentRows = Table_AccountPaymentRecords::getInstance()->getInternalBalanceByCondition($condition, '*', 0);

        if (empty($aprPaymentRows)) {
            return true;
        }
        $date = date("Y-m-d H:i:s");
        //余额
        $customerBalanceArr = Table_AccountPaymentRecords::getInstance()->getTotal($soCode, $payerCode, 1);
        $amount = empty($customerBalanceArr['amount']) || !isset($customerBalanceArr['amount']) ? 0 : $customerBalanceArr['amount'];
        $holdAmount = empty($customerBalanceArr['writeoff_amount']) || !isset($customerBalanceArr['writeoff_amount']) ? 0 : $customerBalanceArr['writeoff_amount'];
        $balance = $amount - $holdAmount;
        if ($balance <= 0) {
            return true;
        }
        //先执行内部核销
        foreach ($aprPaymentRows as $aprRow) {
            $billAmount = $aprRow['apr_amount'] - $aprRow['apr_writeoff_amount'];
            //核销应付金额
            $oCondition = array(
                'apr_type' => '1',
                'so_code' => $aprRow['so_code'],
                'payer_code' => $aprRow['payer_code'],
                'apr_settle_sign' => 'y',
                'apr_writeoff_sign' => 'n',
            );
            $writeoff_sign = $aprRow['apr_writeoff_sign'];
            $aprRows = Service_AccountPaymentRecords::getByCondition($oCondition, '*', 0, 0, array("apr_transaction_time asc"));
            foreach ($aprRows as $aRow) {
                $break = false;
                $aprAmount = $aRow['apr_amount'] - $aRow['apr_writeoff_amount'];
                //异常
                if (!$aprAmount) {
                    throw new Exception("金额异常");
                }
                if ($billAmount <= $aprAmount) {
                    $apr_writeoff_sign = $billAmount == $aprAmount ? 'y' : 'n';
                    $aprAmount = $billAmount;
                    $break = true;
                    //已扣完
                    $billAmount = 0;
                    $writeoff_sign = 'y';
                    Service_AccountPaymentRecords::update(array('apr_writeoff_amount' => ($aRow['apr_writeoff_amount'] + $aprAmount), 'apr_writeoff_sign' => $apr_writeoff_sign), $aRow['apr_id'], 'apr_id');
                } else {
                    $billAmount -= $aprAmount;
                    $writeoff_sign = 'n';
                    Service_AccountPaymentRecords::update(array('apr_writeoff_amount' => ($aRow['apr_writeoff_amount'] + $aprAmount), 'apr_writeoff_sign' => 'y'), $aRow['apr_id'], 'apr_id');
                }

                //核销记录
                $brArr = array(
                    'bibr_amount' => $aprAmount,
                    'apr_id' => $aRow['apr_id'],
                    'to_apr_id' => $aprRow['apr_id'],
                    'bibr_surplus_amount' => $balance - $aprAmount,
                    'bibr_creator_id' => 0,
                    'bibr_add_time' => $date,
                );
                Service_AccountInternalBalanceRecords::add($brArr);

                if ($break) {
                    break;
                }
            }
            //已核销金额
            $billAmount = $billAmount == 0 ? $aprRow['apr_amount'] : abs($aprRow['apr_amount'] - $billAmount);
            Service_AccountPaymentRecords::update(array('apr_writeoff_amount' => $billAmount, 'apr_writeoff_sign' => $writeoff_sign), $aprRow['apr_id'], 'apr_id');
            if ($writeoff_sign != 'y') {
                break;
            }
        }
    }


}