<?php
class Service_OrderDispatchProcess
{
    private $_orderArr = array();
    private $_orderCode = '';
    private $_orderId = '';
    private $_fee = 0;
    private $_currencyCode = null;
    public $_error = array();
    public $_date = '';
    public $_userId = -1;

    public function __construct()
    {
        $this->_date = date('Y-m-d H:i:s');
        $this->_userId = Service_User::getUserId();
    }

    /**
     * @desc 判断参考号是否重复
     * @param string $referenceNo
     * @param string $customerCode
     * @return bool true=>重复,false=>不存在
     */
    public static function checkReferenceNo($referenceNo = '', $customerCode = '')
    {
        if ($referenceNo == '') {
            return false;
        }
        $orders = Service_Orders::getByCondition(array('customer_code' => $customerCode, 'reference_no' => $referenceNo, 'order_status_neq' => '0'), '*', 1, 1);
        if (!empty($orders)) {
            return true;
        }
        return false;
    }

    private function validator()
    {
        $result = Validate_FactoryValidate::factoryMethod($this->_orderArr);
        return $result;
    }

    /**
     * @desc 获取订单号 事物处理
     * @param $orderArr
     */
    private function setOrderCodeTransaction($orderArr = array())
    {
        if ((!isset($orderArr['order_id']) || $orderArr['order_id'] == '') && $this->_orderCode == '') {
            $db = Service_Orders::getModelInstance()->getAdapter();
            $db->beginTransaction();
            $this->_orderCode = Common_GetNumbers::getCode('order', $orderArr['customer_code'], 'SO', false);
            $db->commit();
        }
    }

    /**
     * @desc 初始化订单数据
     * @param array $orderArr
     * @return array
     */
    private function setData($orderArr = array(), $addressArr = array(), $orderProductArr = array())
    {
        $orderKeys = array(
            'order_id' => '',
            'order_code' => '',
            'customer_id' => '',
            'customer_code' => '',
            'warehouse_id' => '',
            'order_type' => '',
            'sm_code' => '',
            'parcel_declared_value' => '',
            'currency_code' => '', //如果为空，用客户自定币种
            'parcel_contents' => '',
            'reference_no' => '',
            'remark' => '',
        );

        $addressKeys = array(
            'oab_firstname' => '',
            'oab_lastname' => '',
            'oab_company' => '',
            'oab_country_id' => '',
            'oab_zone_id' => '',
            'oab_postcode' => '',
            'oab_state' => '',
            'oab_city' => '',
            'oab_suburb' => '',
            'oab_street_address1' => '',
            'oab_street_address2' => '',
            'oab_phone' => '',
            'oab_cell_phone' => '',
            'oab_fax' => '',
            'oab_email' => '',
            'oab_note' => '',
        );

        $orderProductKeys = array(
            'product_id' => '',
            'product_barcode' => '',
            'op_quantity' => '',
            'op_category' => '',
            'op_ref_tnx' => '',
            'op_ref_item_id' => '',
            'op_ref_buyer_id' => '',
            'op_ref_paydate' => '',
        );

        foreach ($orderArr as $key => $val) {
            $orderKeys[$key] = $val;
        }
        foreach ($addressKeys as $key => $val) {
            $addressKeys[$key] = isset($addressArr[$key]) ? $addressArr[$key] : '';
        }
        if ($orderKeys['currency_code'] == '' && $orderKeys['customer_code'] != '') {
            $customerRow = Table_Customer::getInstance()->getByField($orderKeys['customer_code'], 'customer_code', array('customer_code', 'customer_currency'));
            $orderKeys['currency_code'] = isset($customerRow['customer_currency']) ? $customerRow['customer_currency'] : '';
        }
        $this->_orderArr = $orderKeys;
        $this->_orderArr['order_address_book'] = $addressKeys;
        $this->_orderArr['order_product'] = $orderProductArr;
    }

    /**
     * @desc 订单内件数量
     * @param $orderProduct
     * @return int
     */
    public static function getParcelQuantity($orderProduct = array())
    {
        $qty = 0;
        foreach ($orderProduct as $product) {
            $qty += isset($product['op_quantity']) ? $product['op_quantity'] : 0;
        }
        return $qty;
    }

    /**
     * @desc 下架类型
     * @param array $orderProduct
     * @return int
     */
    public static function getOrderPickType($orderProduct = array())
    {
        $i = 0;
        $j = 0;
        foreach ($orderProduct as $product) {
            $j += isset($product['op_quantity']) ? $product['op_quantity'] : 0;
            $i++;
        }
        if ($i == 1 && $j == 1) return 0;
        if ($i == 1 && $j > 1) return 1;
        if ($i > 1 && $j > 1) return 2;
        return -1;
    }

    private function editOrder()
    {
        $orderInfoArr = array(
            'order_id' => $this->_orderArr['order_id'],
            'warehouse_id' => $this->_orderArr['warehouse_id'],
            'order_type' => $this->_orderArr['order_type'],
            'sm_code' => $this->_orderArr['sm_code'],
            'parcel_declared_value' => $this->_orderArr['parcel_declared_value'],
            'currency_code' => $this->_orderArr['currency_code'],
            'parcel_contents' => $this->_orderArr['parcel_contents'],
            'reference_no' => $this->_orderArr['reference_no'],
            'remark' => $this->_orderArr['remark'],
            'update_time' => $this->_date,
        );
        $orderInfoArr['order_pick_type'] = self::getOrderPickType($this->_orderArr['order_product']);
        $orderInfoArr['parcel_quantity'] = self::getParcelQuantity($this->_orderArr['order_product']);

        $orderInfoAddressArr = $this->_orderArr['order_address_book'];
        $orderInfoAddressArr['oab_update_time'] = $this->_date;

        $orderInfoProduct = $this->_orderArr['order_product'];

        if ($orderInfoArr['order_id'] != '') {
            $orderRow = Service_Orders::getByField($orderInfoArr['order_id'], 'order_id');
            if (empty($orderRow)) {
                throw new Exception('Order data anomalies.');
            }
            if ($orderRow['order_status'] > 3) {
                throw new Exception('The state is not allowed.');
            }
            $this->_orderId = $orderRow['order_id'];
            $this->_orderCode = $orderRow['order_code'];

            if (!Service_Orders::update($orderInfoArr, $this->_orderId, 'order_id')) {
                throw new Exception('Update the order failed.');
            }
            //更新地址
            if (!Service_OrderAddressBook::update($orderInfoAddressArr, $this->_orderId, 'order_id')) {
                throw new Exception('Update order address failed.');
            }
            //清除产品
            Service_OrderProduct::delete($this->_orderId, 'order_id');

        } else {
            if ($this->_orderCode == '') {
                $this->_orderCode = Common_GetNumbers::getCode('order', $this->_orderArr['customer_code'], 'SO');
            }
            unset($orderInfoArr['order_id']);
            $orderInfoArr['customer_id'] = $this->_orderArr['customer_id'];
            $orderInfoArr['customer_code'] = $this->_orderArr['customer_code'];
            $orderInfoArr['add_time'] = $this->_date;
            $orderInfoArr['order_code'] = $this->_orderCode;
            if (!$this->_orderId = Service_Orders::add($orderInfoArr)) {
                throw new Exception('Failed to create the order.');
            }
            $orderInfoAddressArr['order_id'] = $this->_orderId;
            $orderInfoAddressArr['order_code'] = $this->_orderCode;
            if (!Service_OrderAddressBook::add($orderInfoAddressArr)) {
                throw new Exception(' Failed to create the recipient information.');
            }
        }
        //添加订单产品
        foreach ($orderInfoProduct as $key => $product) {
            $product['order_id'] = $this->_orderId;
            $product['order_code'] = $this->_orderCode;
            $product['op_add_time'] = $this->_date;
            if (!Service_OrderProduct::add($product)) {
                throw new Exception('Add order product failure.' . $key);
            }
        }
    }

    /**
     * @desc 扣库存
     */
    private function holdInventory()
    {
        $piObj = new Service_ProductInventoryProcess();
        foreach ($this->_orderArr['order_product'] as $key => $val) {
            //库存
            $row = array(
                'product_id' => $val['product_id'],
                'quantity' => $val['op_quantity'],
                'operationType' => 5,
                'warehouse_id' => $this->_orderArr['warehouse_id'],
                'reference_code' => $this->_orderCode, //操作单号
                'application_code' => 'submitOrder', //操作类型
                'note' => ''
            );
            $piReturn = $piObj->update($row);
            if (!isset($piReturn['state']) || $piReturn['state'] != '1') {
                $this->_error[] = 'SKU:' . $val['product_barcode'] . ',Insufficient inventory available.';
            }
        }
    }

    /**
     * @desc 扣除物流费用
     * return state 0:获取运费失败;1:成功扣款;2:支付失败
     */
    private function logisticsFees()
    {
        //return 1;
        $state = 1;
        $totalWeight = 0;
        foreach ($this->_orderArr['order_product'] as $key => $val) {
            $totalWeight += $val['op_weight'] * $val['op_quantity'];
        }
        //设置最小重量
        $totalWeight = $totalWeight < 0.01 ? $totalWeight = 0.01 : $totalWeight;
        $obj = new Common_CalculateShipping();
        $keys = array(
            'warehouseId' => $this->_orderArr['warehouse_id'],
            'countryId' => $this->_orderArr['order_address_book']['oab_country_id'],
            'smCode' => $this->_orderArr['sm_code'],
            'weight' => $totalWeight
        );
        $obj->setParams($keys);
        $costArr = $obj->getRate();
        if (isset($costArr['state']) && $costArr['state'] == '1') {
            $feeObj = new Common_CustomerFeeProcess();
            //转成订单的币种
            $feeArr = $feeObj->changeCurrency($costArr['data']['cost']['totalCost'], $costArr['data']['cost']['currency_code'], $this->_orderArr['currency_code']);
            $this->_fee = $feeArr['value'];
            $feeDetail[] = array(
                'cbl_type' => '0',
                'cbl_value' => $this->_fee,
                'currency_code' => $this->_orderArr['currency_code'],
                'release_value' => '0',
                'currency_rate' => '',
                'user_id' => '',
                'cbl_refer_code' => $this->_orderCode,
                'application_code' => 'Submit Order',
                'fee_id' => '0',
                'cbl_note' => 'logisticsFees'
            );
            $feeReturn = $feeObj->payment($this->_orderArr['customer_code'], $feeDetail);
            if ($feeReturn['state'] != '1') {
                $state = 2;
                $this->_error[] = isset($feeReturn['message']) ? $feeReturn['message'] : 'Payment Fee Fail.';
            }
        } else {
            $this->_error = isset($costArr['error']) ? $costArr['error'] : array();
            $state = 0;
        }
        return $state;
    }

    /**
     * @desc 提取订单中的所有产品，主要是提取组合产品中的普通产品
     * @param $ordersCode
     * @return array
     */
    public function getOrderProductUnique($ordersCode)
    {
        $orderProduct = Service_OrderProduct::getByCondition(array("order_code" => $ordersCode));
        $orderProducts = array();
        foreach ($orderProduct as $v) { //提取所有产品（判断有无组合产品）
            $product = Service_Product::getByField($v['product_id'], 'product_id');
            if ($product['product_type'] == 1) { //组合产品
                $con = array('product_id' => $product['product_id']);
                $productCombine = Service_ProductCombineRelation::getByCondition($con, "*");
                foreach ($productCombine as $sub) {
                    $subProduct = Service_Product::getByField($sub['pcr_product_id'], 'product_id');
                    if (isset($orderProducts[$sub['pcr_product_id']])) {
                        $orderProducts[$sub['pcr_product_id']]['op_quantity'] += $sub['pcr_quantity'] * $v['op_quantity'];
                    } else {
                        $orderProducts[$sub['pcr_product_id']] = array(
                            'order_code' => $ordersCode,
                            'op_id' => $v['op_id'],
                            'product_id' => $subProduct['product_id'],
                            'product_sku' => $subProduct['product_sku'],
                            'product_barcode' => $subProduct['product_barcode'],
                            'customer_id' => $subProduct['customer_id'],
                            'op_quantity' => $sub['pcr_quantity'] * $v['op_quantity'],
                            'op_weight' => $subProduct['product_weight'],
                            'op_unit_price' => $subProduct['product_declared_value'],
                        );
                    }
                }
            } else {
                if (isset($orderProducts[$v['product_id']])) {
                    $orderProducts[$v['product_id']]['op_quantity'] += $v['op_quantity'];
                } else {
                    $orderProducts[$v['product_id']] = array(
                        'order_code' => $ordersCode,
                        'op_id' => $v['op_id'],
                        'product_id' => $product['product_id'],
                        'product_sku' => $product['product_sku'],
                        'product_barcode' => $product['product_barcode'],
                        'customer_id' => $product['customer_id'],
                        'op_quantity' => $v['op_quantity'],
                        'op_weight' => $product['product_weight'],
                        'op_unit_price' => $product['product_declared_value'],
                    );
                }
            }
        }
        return $orderProducts;
    }

    /**
     * @desc 操作节点
     * @param string $operationType
     */
    private function orderOperationNode($operationType = '', $note = '')
    {
        $nodeArr = array(
            'order_id' => $this->_orderId,
            'order_code' => $this->_orderCode,
            'oon_add_time' => $this->_date,
            'oon_note' => $note,
            'user_id' => $this->_userId ? $this->_userId : '-1'
        );
        switch ($operationType) {
            case -2:
                $nodeArr['oot_code'] = 'confirmstop';
                break;
            case -1:
                $nodeArr['oot_code'] = 'stop';
                break;
            case 0:
                $nodeArr['oot_code'] = 'delete';
                break;
            case 1:
                $nodeArr['oot_code'] = 'add';
                break;
            case 2:
                $nodeArr['oot_code'] = 'confirm';
                break;
            case 3:
                $nodeArr['oot_code'] = 'abnormal';
                break;
            case 4:
                $nodeArr['oot_code'] = 'submit';
                break;
            default:
                break;
        }
        if (isset($nodeArr['oot_code'])) {
            Service_OrderOperationNode::add($nodeArr);
        }
    }


    /**
     * @param array $orderArr
     * @param array $addressArr
     * @param array $orderProductArr
     * @return array
     * @throws Exception
     */
    public function createOrder($orderArr = array(), $addressArr = array(), $orderProductArr = array())
    {
        $result = array('state' => 0, 'orderCode' => '', 'errorMessage' => array());
        try {
            if (!is_array($orderArr) || !is_array($addressArr) || !is_array($orderProductArr)) {
                throw new Exception('Invalid Argument Exceptions.');
            }
            $this->setData($orderArr, $addressArr, $orderProductArr);
            $error = $this->validator($this->_orderArr);
            if (!empty($error)) {
                $result['errorMessage'] = $error;
                return $result;
            }
            $this->editOrder();
            $this->orderOperationNode(1, 'API');
            $result['state'] = 1;
            $result['orderCode'] = $this->_orderCode;
        } catch (Exception $e) {
            $result['errorMessage'][] = $e->getMessage();
        }
        return $result;
    }

    /**
     * @desc 创建订单到指定状态 事务处理
     * @param array $orderArr
     * @param array $addressArr
     * @param array $orderProductArr
     * @param int $orderStatus
     * @param bool $abnormal true=>遇到异常将状态转为3 false=>全部失败回滚
     */
    public function createOrderTransaction($orderArr = array(), $addressArr = array(), $orderProductArr = array(), $orderStatus = 1, $abnormal = true)
    {
        $result = array('state' => 0, 'orderCode' => '', 'orderStatus' => $orderStatus, 'errorMessage' => array());
        $orderStatusArray = array(1, 2, 4); //限制状态避免太多操作
        if (!in_array($orderStatus, $orderStatusArray)) {
            $result['orderStatus'] = '';
            $result['errorMessage'][] = 'This state cannot be modified.';
            return $result;
        }
        $this->setOrderCodeTransaction($orderArr);
        $db = Service_Orders::getModelInstance()->getAdapter();
        $db->beginTransaction();
        try {
            //专属创建订单
            unset($orderArr['order_id']);
            $return = $this->createOrder($orderArr, $addressArr, $orderProductArr);
            if (!isset($return['state']) || $return['state'] != '1') {
                $result['orderStatus'] = '';
                $result['errorMessage'] = $return['errorMessage'];
                $db->rollBack();
                return $result;
            }
            //创建日志
            $log['ol_type'] = 0;
            $log['order_status_from'] = 1;
            $log['order_status_to'] = $orderStatus;
            $log['ol_comments'] = 'API Create Order,Status 1 to ' . $orderStatus;
            $this->addOrderLog($log);
            $result['state'] = 1;
            $result['orderCode'] = $orderCode = $return['orderCode'];
            switch ($orderStatus) {
                case 1:
                    $db->commit();
                    break;
                case 2:
                    $this->orderOperationNode(2, 'API');
                    $db->commit();
                    break;
//                case 3:
//                    break;
                case 4:
                    $this->orderOperationNode(2, 'API');
                    $this->_orderArr['order_product'] = $this->getOrderProductUnique($orderCode);
                    $this->holdInventory();
                    if (!empty($this->_error)) {
                        if ($abnormal) {
                            $this->orderOperationNode(3, 'Insufficient inventory available.');
                            Service_Orders::update(array('order_status' => 3, 'problem_status' => 1, 'underreview_status' => 2), $this->_orderId, 'order_id');
                            $result['orderStatus'] = 3;
                            $db->commit();
                            return $result;
                        } else {
                            $result = array('state' => 0, 'orderCode' => '', 'orderStatus' => '', 'errorMessage' => $this->_error);
                            $db->rollBack();
                            return $result;
                        }
                    }
                    $state = $this->logisticsFees();
                    if ($state == '1') {
                        $this->orderOperationNode(4, '');
                        Service_Orders::update(array('order_status' => 4, 'shipping_fee_estimate' => $this->_fee), $this->_orderId, 'order_id');
                        $result['orderStatus'] = 4;
                        $db->commit();
                        return $result;
                    } elseif ($state == '2' && $abnormal) {
                        $this->orderOperationNode(3, 'Insufficient balance.');
                        $result = array('state' => 1, 'orderCode' => $orderCode, 'orderStatus' => 3, 'errorMessage' => $this->_error);
                        $db->commit();
                        return $result;
                    }
                    $result = array('state' => 0, 'orderCode' => '', 'orderStatus' => '', 'errorMessage' => $this->_error);
                    $db->rollBack();
                    return $result;
                    break;
                default:
                    $result = array('state' => 0, 'orderCode' => '', 'orderStatus' => '', 'errorMessage' => '');
                    throw new Exception('This state cannot be modified.');
                    break;
            }
        } catch (Exception $e) {
            $db->rollBack();
            $result['errorMessage'][] = $e->getMessage();
        }
        return $result;
    }

    /**
     * @desc 截单操作 事务处理
     * @param string $orderCode
     * @return array
     * @throws Exception
     */
    public function stopOrderTransaction($orderCode = '', $note = '')
    {
        $result = array('state' => 0, 'orderCode' => $orderCode, 'message' => '');
        $orderStatusArray = array(10,11, 12, 13); //订单在此范围内不可截单
        $orderStatusArray2 = array(8,9);
        $allowStatus = array(4, 5, 6, 7,8,14); // 允许截单的订单状态
        $db = Common_Common::getAdapter();
        $db->beginTransaction();
        try {
            $orderRow = Service_Orders::getByField($orderCode, 'order_code');
            //$orderRow = Service_Orders::getByField($orderCode, 'order_code');
            /*if (in_array($orderRow['order_status'], $orderStatusArray)) {
                throw new Exception('拦截失败,订单已出库');
            }
            if(in_array($orderRow['order_status'], $orderStatusArray)){
                throw new Exception('拦截失败,订单已装袋');
            }*/
            if (0 !== (int) $orderRow['order_mode_type'] || !in_array((int) $orderRow['order_status'], $allowStatus, TRUE)) {
              throw new Exception('订单不满足拦截条件：备货并且未装袋前');
            }
            if($orderRow['underreview_status']=='3'){
                $db->commit();
                $result['state'] = 1;
                $result['message'] = '订单已申请拦截';
                return $result;
            }
            if($orderRow['intercept_status']!='0'){
                $db->commit();
                $result['state'] = 1;
                $result['message'] = '订单已申请拦截';
                return $result;
            }
            $this->_orderId = $orderRow['order_id'];
            $this->_orderCode = $orderRow['order_code'];
            $this->_orderArr = $orderRow;
            $updateRow = array('order_status' => 0, 'problem_status' => 0, 'underreview_status' => 0,'intercept_status'=>0, 'update_time' => $this->_date,'intercept_reason'=>$note);
            switch ($orderRow['order_status']) {
                case 0:
                    $this->orderOperationNode(-2, $note);
                    $db->commit();
                    $result['state'] = 1;
                    $result['message'] = '成功申请拦截,订单已移至删除';
                    return $result;
                    break;
                case 1:
                case 2:
                case 3:
                    $this->orderOperationNode(-2, $note);
                    $result['message'] = '成功申请拦截,订单已移至删除';
                    break;
                case 4:
                    $this->_orderArr['order_product'] = $this->getOrderProductUnique($orderCode);
                    $this->rollbackHoldInventory();
                    //环球的客户在提交订单时就直接扣费了。
                    if( Service_CustomerProcess::$HuanQiu == Service_CustomerProcess::getOwner( $orderRow['customer_code'] ) ) {
                        $this->returnSipFee();
                        //清除应收应付及其他相关记录
                        $this->clearBusiness();
                    } else{
                        $this->rollbackLogisticsFees();
                    }
                    $this->orderOperationNode(-2, $note);
                    $result['message'] = '成功申请拦截,订单已移至删除';
                    break;
                case 5:
                case 6:
                case 7:
                case 8:
                case 9:
                case 14:
                //case 10:
                    $this->orderOperationNode(-1,$note);
                    $updateRow = array('underreview_status' => 3,'intercept_status'=>1, 'update_time' => $this->_date,'intercept_reason'=>$note);
                    $result['message'] = '申请成功,订单已下架,等待产品重新上架';
                    break;
                default:
                    throw new Exception('拦截失败,订单已出库.');
                    break;
            }
            if (!Service_Orders::update($updateRow, $this->_orderId, 'order_id')) {
                throw new Exception('Update Order Status Fail');
            }
            $this->orderOperationTime(array('cutoff_time' => $this->_date, 'cutoff_user_id' => $this->_userId));
            $log['ol_type'] = 0;
            $log['order_status_from'] = $orderRow['order_status'];
            $log['order_status_to'] = isset($updateRow['order_status']) ? $updateRow['order_status'] : $orderRow['order_status'];
            $log['ol_comments'] = $note != '' ? "订单拦截,拦截原因:{$note}" : 'Operation stopOrder';
            $this->addOrderLog($log);
            $db->commit();
            $result['state'] = 1;
        } catch (Exception $e) {
            $db->rollBack();
            $result['message'] = $e->getMessage();
        }
        return $result;
    }

    /**
     * @desc 订单操作时间
     * @param array $row 注意匹配字段
     * @throws Exception
     */
    private function orderOperationTime($row = array())
    {
        $ootObj = new Service_OrderOperationTime();
        $ootRow = $ootObj->getByField($this->_orderId, 'order_id');
        $row['order_id'] = $this->_orderId;
        $row['order_code'] = $this->_orderCode;
        if (empty($ootRow)) {
            $result = $ootObj->add($row);
        } else {
            $result = $ootObj->update($row, $this->_orderId, 'order_id');
        }
        if (!$result) {
            throw new Exception('Update Order Operation Time Fail');
        }
    }

    /**
     * @desc 回退库存
     */
    private function rollbackHoldInventory()
    {
        $piObj = new Service_ProductInventoryProcess();
        foreach ($this->_orderArr['order_product'] as $key => $val) {
            //库存
            $row = array(
                'product_id' => $val['product_id'],
                'quantity' => $val['op_quantity'],
                'operationType' => 9,
                'warehouse_id' => $this->_orderArr['warehouse_id'],
                'reference_code' => $this->_orderCode, //操作单号
                'application_code' => 'stopOrder', //操作类型
                'note' => '拦截订单',
            );
            $piReturn = $piObj->update($row);
            if (!isset($piReturn['state']) || $piReturn['state'] != '1') {
                $this->_error[] = 'SKU:' . $val['product_barcode'] . ',Freeze the inventory shortage.';
            }
        }
    }


    /**
     * @desc 回退物流费用
     */
    private function rollbackLogisticsFees()
    {
        //if ($this->_orderArr['shipping_fee_estimate'] > 0) {
            $feeObj = new Common_CustomerFeeProcess();
            $condition = array(
                'cbl_refer_code'=>$this->_orderArr['order_code'],
                'cbl_type'=>'0',
            );

            $aCustomer = Service_Customer::getByField($this->_orderArr['customer_id']);
            $aBalance = Service_CustomerBalance::getByField($this->_orderArr['customer_id'], 'customer_id');

            $financeLog = Service_CustomerBalanceLog::getByCondition($condition,"*",0,0,'cbl_id desc');
            $feeDetail = array();
            $feeTotal = 0;
            foreach($financeLog as $k=>$v){

                $aBalanceLog['customer_code'] = $v['customer_code'];
                $aBalanceLog['customer_id'] = $v['customer_id'];
                $aBalanceLog['cbl_transaction_value'] = $v['cbl_transaction_value'];
                $aBalanceLog['cbl_value'] = $v['cbl_value'];
                $aBalanceLog['cbl_current_value'] = $v['cbl_current_value']+$v['cbl_transaction_value'];
                $aBalanceLog['cbl_current_hold_value'] = $v['cbl_current_hold_value']-$v['cbl_transaction_value'];
                $aBalanceLog['currency_code'] = $v['currency_code'];
                $aBalanceLog['fee_id'] = $v['fee_id'];
                $aBalanceLog['application_code'] = 1;
                $aBalanceLog['cbl_refer_code'] = $this->_orderCode;
                $aBalanceLog['cbl_type'] = 1;
                $aBalanceLog['cbl_note'] = "订单拦截,解冻余额";
                $aBalanceLog['user_id'] = '0';
                $aBalanceLog['cbl_add_time'] = date("Y-m-d H:i:s");
                $feeTotal = $feeTotal + $v['cbl_transaction_value'];
                $aResult = Service_CustomerBalanceLog::add($aBalanceLog);

                /*$Arr = array(
                    'cbl_type' => '1',
                    'cbl_value' => $v['cbl_transaction_value'],
                    'currency_code' => $v['currency_code'],
                    'release_value' => '0',
                    'currency_rate' =>'',
                    'user_id' => '',
                    'cbl_refer_code' => $this->_orderCode,
                    'application_code' => 'StopOrder',
                    'fee_id' => $v['fee_id'],
                    'cbl_note' => 'rollback logistics Fees'
                );
                $feeDetail[] = $Arr;*/
            }
            /*$feeDetail[] = array(
                'cbl_type' => '1',
                'cbl_value' => $this->_orderArr['shipping_fee_estimate'],
                'currency_code' => $this->_orderArr['currency_code'],
                'release_value' => '0',
                'currency_rate' => '',
                'user_id' => '',
                'cbl_refer_code' => $this->_orderCode,
                'application_code' => 'StopOrder',
                'fee_id' => '0',
                'cbl_note' => 'rollback logistics Fees'
            );*/
            $currencyRow = Service_Currency::getByField($aCustomer['customer_currency'],'currency_code',"*");
            $balanceRow = Service_CustomerBalance::getForUpdate($aBalance['cb_id']);
            $hold_value  = $balanceRow['cb_hold_value'] - $feeTotal/$currencyRow['currency_rate'];
            $uBalance['cb_hold_value'] = $hold_value;
            $uBalance['cb_update_time'] = date('Y-m-d H:i:s');
            $uBalance['cb_value'] = $balanceRow['cb_value'] + $feeTotal/$currencyRow['currency_rate'];
            $uResult = Service_CustomerBalance::update($uBalance, $balanceRow['cb_id']);

            /*$feeReturn = $feeObj->payment($this->_orderArr['customer_code'], $feeDetail);
            if ($feeReturn['state'] != '1') {
                throw new Exception('rollback Fee Fail. ' . $feeReturn['message']);
            }*/

        //}
    }

    /* @desc 返回费用
     *
     */
    protected function returnSipFee() {
        $condition = array(
            'cbl_refer_code' => $this->_orderArr['order_code'],
            'cbl_type'=> 2 ,
        );

        $aBalance = Service_CustomerBalance::getByField($this->_orderArr['customer_id'], 'customer_id');

        $financeLog = Service_CustomerBalanceLog::getByCondition($condition,"*",0,0 );

        if( $financeLog ) {
            $balanceRow = Service_CustomerBalance::getForUpdate($aBalance['cb_id']);
            $balanceRow['old_cb_value'] = $balanceRow['cb_value'];

            foreach($financeLog as $value){
                if( $value['cbl_note'] == '提交订单，扣取运费' ) {
                    $note = '拦截订单，返还运费';
                } else {
                    $feeItem = array();
                    if( $value['fee_id'] )
                        $feeItem = Service_OtherFee::getByField( $value['fee_id'] );

                    $note = $feeItem ? '拦截订单，返还'.$feeItem['fee_name'] : '拦截订单，返还费用';
                }

                $balanceRow['cb_value'] += $value['cbl_transaction_value'];

                $aBalanceLog['customer_code'] = $value['customer_code'];
                $aBalanceLog['customer_id'] = $value['customer_id'];
                $aBalanceLog['cbl_transaction_value'] = $value['cbl_transaction_value'];
                $aBalanceLog['cbl_value'] = $value['cbl_value'];
                $aBalanceLog['cbl_current_value'] = $balanceRow['cb_value'];
                $aBalanceLog['cbl_current_hold_value'] = $balanceRow['cb_hold_value'];
                $aBalanceLog['currency_code'] = $value['currency_code'];
                $aBalanceLog['fee_id'] = $value['fee_id'];
                $aBalanceLog['application_code'] = $value['application_code'];
                $aBalanceLog['cbl_refer_code'] = $value['cbl_refer_code'];
                $aBalanceLog['cbl_type'] = 3;
                $aBalanceLog['cbl_note'] = $note;
                $aBalanceLog['user_id'] = '0';
                $aBalanceLog['cbl_add_time'] = date("Y-m-d H:i:s");

                $aResult = Service_CustomerBalanceLog::add( $aBalanceLog );
                if( !$aResult )
                    throw new Exception('退费失败');
            }
            if( $balanceRow['cb_value'] != $balanceRow['old_cb_value'] ) {
                $uBalance = array(
                    'cb_update_time' => date('Y-m-d H:i:s'),
                    'cb_value' => $balanceRow['cb_value']
                );
                $uResult = Service_CustomerBalance::update( $uBalance, $balanceRow['cb_id'] );
                if( !$uResult )
                    throw new Exception('退费失败');
            }

        }
    }

    protected function clearBusiness() {
        //删除应收应付
        $businessBill = Service_BilBusinessAttach::getByField( $this->_orderArr['order_code'], 'bb_refer_code' );
        if( $businessBill ) {
            //应付应收不一定有记录
            Service_BilIncome::delete( $businessBill['bb_id'], 'bb_id' );

            Service_BilPayment::delete( $businessBill['bb_id'], 'bb_id' );

            $result = Service_BilBusinessAttach::delete( $businessBill['bb_id'], 'bb_id' );
            if( !$result )
                throw new Exception('退费失败1');

            $result = Service_BilBusiness::delete( $businessBill['bb_id'], 'bb_id' );
            if( !$result )
                throw new Exception('退费失败2');
        }
        //非自有渠道才会有
        Service_CostRecording::delete( $this->_orderArr['order_code'], 'order_code');
        Service_LogisticsCost::delete( $this->_orderArr['order_code'], 'order_code' );

        //有应收或应付 才会有数据
        Service_FeeCostDetail::delete( $this->_orderArr['order_code'], 'code_number' );
    }

    /**
     * @desc 创建订单操作日志
     */
    private function addOrderLog($row)
    {
        $row['order_id'] = $this->_orderId;
        $row['order_code'] = $this->_orderCode;
        $row['user_id'] = $this->_userId;
        $row['ol_ip'] = Common_Common::getIP();
        Service_OrderLog::add($row);
    }

    /**
     * @desc 判断库存是否充足将订单转为正常
     * @param string $orderCode
     * @return array
     * @throws Exception
     */
    public static function updateOrderStatus($orderCode = '')
    {
        $result = array('state' => 0, 'orderCode' => $orderCode, 'message' => '');
        $orderRow = Service_Orders::getByField($orderCode, 'order_code');
        if ($orderRow['order_status'] != '3') {
            $result['message'] = 'orderStatus err.';
            return $result;
        }
        $userId = Service_User::getUserId();
        $date = date('Y-m-d H:i:s');
        $db = Common_Common::getAdapter();
        $db->beginTransaction();
        try {
            if (!Service_Orders::update(array('order_status' => 4, 'underreview_status' => 0, 'update_time' => $date), $orderCode, 'order_code')) {
                throw new Exception('Update Order err.');
            }
            //拆分组合产品
            $orderProductRows = self::getOrderProductUnique($orderCode);
            if (empty($orderProductRows)) {
                throw new Exception('get OrderProduct err.');
            }
            $piObj = new Service_ProductInventoryProcess();
            foreach ($orderProductRows as $key => $val) {
                $row = array(
                    'product_id' => $val['product_id'],
                    'quantity' => $val['op_quantity'],
                    'operationType' => 5,
                    'warehouse_id' => $orderRow['warehouse_id'],
                    'reference_code' => $orderCode, //操作单号
                    'application_code' => 'submitOrder', //操作类型
                    'note' => ''
                );
                $piReturn = $piObj->update($row);
                if (!isset($piReturn['state']) || $piReturn['state'] != '1') {
                    throw new Exception('SKU:' . $val['product_barcode'] . ',Insufficient inventory available.');
                }
            }
            //订单节点
            $orderNode = array(
                'order_id' => $orderRow['order_id'],
                'order_code' => $orderRow['order_code'],
                'oot_code' => 'submit',
                'oon_note' => 'abnormal to submit',
                'user_id' => $userId,
            );
            Service_OrderOperationNode::add($orderNode);
            $db->commit();
            $result['state'] = 1;
            $result['message'] = 'Operation Successfully Completed';
        } catch (Exception $e) {
            $db->rollBack();
            $result['message'] = $e->getMessage();
        }
        return $result;
    }

    /**
     * @desc 异常订单自动转为正常
     * @return array
     */
    public static function scanAbnormalOrders()
    {
        $pageSize = 20;
        $page = 1;
        $result = array();
        $orderRows = Service_Orders::getByCondition(array('order_status' => 3), array('order_code'), $pageSize, $page, array('order_id asc'));
        while (count($orderRows) > 1 && $page < 20) {
            $page++;
            //echo $page . '---';
            foreach ($orderRows as $orderArr) {
                $result[] = self::updateOrderStatus($orderArr['order_code']);
            }
            $orderRows = Service_Orders::getByCondition(array('order_status' => 3), array('order_code'), $pageSize, $page, array('order_id asc'));
        }
        return $result;
    }

    /**
     * @desc 返回批次库存,清除核销记录
     */
    private function clearInventoryBatchOutbound()
    {
        $pickingDetail = Service_PickingDetail::getByCondition(array('order_code' => $this->_orderCode));
        if (empty($pickingDetail)) {
            throw new Exception('找不到下架记录.');
        }
        $ip = Common_Common::getIP();
        $obj = new Table_InventoryBatchOutbound();
        $logObj = new Table_InventoryBatchOutboundLog();
        foreach ($pickingDetail as $val) {
            if (!$obj->delete($val['ibo_id'], 'ibo_id')) {
                throw new Exception('清除出库核销信息失败.');
            }
            $row = array(
                'lc_code' => $val['lc_code'],
                'ibo_id' => $val['ibo_id'],
                'ib_id' => $val['ib_id'],
                'reference_no' => $val['order_code'],
                'application_code' => 'pickup',
                'ibol_quantity' => $val['pd_quantity'],
                'user_id' => $this->_userId,
                'ibol_ip' => $ip,
                'ibol_add_time' => $this->_date,
                'ibol_note' => 'ConfirmStopOrders',
            );
            $logObj->add($row);
        }
    }

    /**
     * @desc 截单完成，产品已重新上架
     * @param string $orderCode
     */
    public function confirmStopOrder($orderCode = '')
    {
        $result = array('state' => 0, 'orderCode' => $orderCode, 'message' => '', 'data' => array());
        $orderRow = Service_Orders::getByField($orderCode, 'order_code');
        if(empty($orderRow) || empty($orderCode)){
            $result['message'] = '订单不存在,请核对输入的订单号';
            return $result;
        }
        /*if ($orderRow['underreview_status'] != '3') {
            $result['message'] = '订单不是拦截状态';
            return $result;
        }*/
        if ($orderRow['intercept_status'] != '2') {
            $result['message'] = '拦截状态,不是[拦截处理中],不允许操作';
            return $result;
        }
        //初始化订单数据
        $this->_orderId = $orderRow['order_id'];
        $this->_orderCode = $orderRow['order_code'];
        $this->_orderArr = $orderRow;
        $this->_orderArr['order_product'] = $this->getOrderProductUnique($orderCode);
        $date = date('Y-m-d H:i:s');
        $db = Common_Common::getAdapter();
        $db->beginTransaction();
        try {
            if (!Service_Orders::update(array('order_status' => 0, 'underreview_status' => 0, 'intercept_status' => 3, 'update_time' => $date), $orderCode, 'order_code')) {
                throw new Exception('Update Order err.');
            }
            Service_Precaution::delete($orderRow['reference_no'], 'precaution_value');
            $orderLog = array(
                'order_id'=>$orderRow['order_id'],
                'order_code' => $orderRow['order_code'],
                'ol_type'=>'0',
                'order_status_from'=>$orderRow['order_status'],
                'order_status_to' => 0,
                'ol_add_time' => date('Y-m-d H:i:s',time()),
                'user_id'=> '-1',
                'ol_ip'=>$this->_userId,
                'ol_comments'=>"订单完成拦截"
            );
            Service_OrderLog::add($orderLog);
            $this->rollbackHoldInventory();
            //环球的客户是提交订单时就扣费的，所以直接退钱
            if( Service_CustomerProcess::$HuanQiu == Service_CustomerProcess::getOwner( $orderRow['customer_code'] ) ) {
                $this->returnSipFee();
                //清除应收应付及其他相关记录
                $this->clearBusiness();
            } else {
                $this->rollbackLogisticsFees();
            }
            $this->clearInventoryBatchOutbound();
            $this->orderOperationNode('-2');
            //解除绑定关系
            $orderPicking = Service_PickingDetail::getByCondition(array('order_code' => $orderRow['order_code']));
            $productCount = 0;
            $pickingCode  = '';
            
            //扣除总出货量
            if ($orderPicking) {
                foreach ($orderPicking as $item) {
                    if ('' === $pickingCode) {
                        $pickingCode = $item['picking_code'];
                    }
            
                    $productCount += $item['pd_quantity'];
                }
            
                $picking = Service_Picking::getByField($pickingCode, 'picking_code');
            
                if ($picking) {
                    Service_Picking::update(array(
                    'picking_order_cnt' => $picking['picking_order_cnt'] - 1,
                    'picking_item_cnt'  => $picking['picking_item_cnt'] - $productCount,
                    ), $picking['picking_id'], 'picking_id');
                }
            
                Service_PickingDetail::delete($orderRow['order_code'], 'order_code');
            }
            $db->commit();
            //$db->rollBack();
            $result['state'] = 1;
            $result['message'] = '操作成功';
        } catch (Exception $e) {
            $db->rollBack();
            $result['message'] = $e->getMessage();
        }

        return $result;
    }

    /**
     * @desc 拦截处理中,重新上架
     * @param array $ordersCodes
     */
    public function stopOrderProcess($ordersCodes = array())
    {
        $result = array('state' => 0, 'message' => array(), 'data' => array());
        if (!is_array($ordersCodes)) {
            $result['message'][] = '参数异常,请重新提交';
            return $result;
        }
        $date = date('Y-m-d H:i:s');
        $data = array();
        foreach ($ordersCodes as $key => $orderCode) {
            $orderRow = Service_Orders::getByField($orderCode, 'order_code');
            if (empty($orderRow)) {
                $result['message'][] = '订单号:' . $orderCode . ' 不存在';
                continue;
            }
            if ($orderRow['intercept_status'] != '1' && $orderRow['intercept_status'] != '2') {
                $result['message'][] = '订单号:' . $orderCode . ' 不是拦截状态';
                continue;
            }
            if ($orderRow['intercept_status'] == '1') {
                Service_Orders::update(array('intercept_status' => 2, 'update_time' => $date), $orderRow['order_id'], 'order_id');
            }
            $data[$key]['orderCode'] = $orderCode;
            $data[$key]['pick'] = Service_PickingDetail::getLeftJoinOrderProductByCondition(array('order_code' => $orderCode));
        }
        if (!empty($data)) {
            $result['state'] = 1;
            $result['data'] = $data;
        }
        return $result;
    }

    /**
     * @desc 将拦截失败的订单,取消拦截
     * @param array $orderCode
     */
    public function cancelStopOrder($orderCode = '', $note = '')
    {
        $result = array('state' => 0, 'message' => '', 'orderCode' => $orderCode);
        if (empty($orderCode)) {
            $result['message'] = '订单号不能为空';
            return $result;
        }
        $date = date('Y-m-d H:i:s');
        $ip = Common_Common::getIP();
        $orderRow = Service_Orders::getByField($orderCode, 'order_code');
        if (empty($orderRow)) {
            $result['message'] = '订单号:' . $orderCode . ' 不存在';
            return $result;
        }
        if ($orderRow['intercept_status'] != '1') {
            $result['message'] = '订单号:' . $orderCode . ' 不是拦截状态';
            return $result;
        }
        if ($orderRow['intercept_status'] == '2') {
            $result['message'] = '订单号:' . $orderCode . ' 拦截处理中,不允许操作';
            return $result;
        }
        $orderUpdate = Service_Orders::update(array('intercept_status' => 0, 'underreview_status' => 0, 'update_time' => $date), $orderRow['order_id'], 'order_id');
        if ($orderUpdate) {
            $row = array(
                'order_id' => $orderRow['order_id'],
                'order_code' => $orderRow['order_code'],
                'oot_code' => 'cancelstop',
                'oon_note' => $note,
                'oon_add_time' => $this->_date,
                'user_id' => $this->_userId,
            );
            Service_OrderOperationNode::add($row);
            $row = array(
                'order_id' => $orderRow['order_id'],
                'order_code' => $orderRow['order_code'],
                'ol_type' => 0,
                'order_status_from' => $orderRow['order_status'],
                'order_status_to' => $orderRow['order_status'],
                'user_id' => $this->_userId,
                'ol_ip' => $ip,
                'ol_comments' => '取消拦截',
            );
            Service_OrderLog::add($row);
        }
        $result['state'] = 1;
        $result['message'] = '操作成功';
        return $result;
    }


}