<?php
/**
 * 对于自有渠道集货小包类运输方式，在订单状态时同时完成收货动作
 * 
 * 先决条件：
 * 是否为自有渠道；是否为小包运输方式；订单是否为已提交状态；ASN单是否为在途或收货中状态
 */
class Service_BR {
  public static $orderInfo = array(); // 保存订单信息
  public static $asnInfo   = array(); // 保存ASN单信息
  public static $rodInfo   = array(); // ASN单订单列表订单信息
  public static $isValid   = FALSE; // 订单、ASN单验证结果

  /**
   * 判定运输方式是否为小包类
   * 
   * @param array $method    运输方式相关信息数组
   * @return boolean         是小包类运输方式返回TRUE，否则返回FALSE
   */
  public static function isPacket($method) {
    if (!is_array($method)) {
      return FALSE;
    }

    $default = array(
      'sm_code'       => '', // 运输方式代码
      'sm_class_code' => '', // 运输方式类型：CRE（快递）、CRP（挂号）、CPS（平邮）
      'sm_channel'    => 0, // 是否自有运输方式：0否；1是
      'sm_status'     => 0, // 运输方式是否可用：0不可用；1可用
      'packet_type'   => 0, // 是否小包类：0不是；1是
    );
    $default = array_merge($default, $method);
    $default = array(
      'sm_code'       => trim($default['sm_code']),
      'sm_class_code' => trim($default['sm_class_code']),
      'sm_channel'    => (int) $default['sm_channel'],
      'sm_status'     => (int) $default['sm_status'],
      'packet_type'   => (int) $default['packet_type'],
    );

    // 不是自有方式或运输方式不可用或不是小包类运输方式
    if (!$default['sm_channel'] || 1 !== $default['sm_status'] || 1 !== (int) $default['packet_type']) {
      return FALSE;
    }

    return TRUE;
  }

  /**
   * 是否采用订单装袋同时进行收货动作
   * 
   * 判定标准：
   * 自有渠道；小包运输方式；集货模式已提交状态订单；集货模式在途或收货中状态ASN单
   * 
   * @param array $method    运输方式信息
   * @param array $order     订单信息
   * @return boolean
   */
  public static function isBrMode($method, $order) {
    self::$isValid = FALSE; // 初始化

    if (!self::isPacket($method) || !is_array($order)) {
      return FALSE;
    }

    $default = array(
      'order_code'      => '', // 订单号
      'order_status'    => 0, // 订单状态：4已提交
      'order_mode_type' => 0, // 订单模式：0备货；1集货
      'warehouse_id'    => 0, // 订单所属仓库
      'sm_code'         => '', // 运输方式
    );
    $default = array_merge($default, $order);
    $default = array(
      'order_code'      => trim($default['order_code']),
      'order_status'    => (int) $default['order_status'],
      'order_mode_type' => (int) $default['order_mode_type'],
      'warehouse_id'    => (int) $default['warehouse_id'],
      'sm_code'         => strtoupper(trim($default['sm_code'])),
    );

    // 订单运输方式与验证的运输方式不同
    if ($default['sm_code'] !== strtoupper(trim($method['sm_code']))) {
      return FALSE;
    }

    // 订单不是集货模式或已提交状态的订单
    if (1 !== $default['order_mode_type'] || 4 !== $default['order_status']) {
      return FALSE;
    }

    // 仓库不匹配
    if (self::getWarehouseId() !== $default['warehouse_id']) {
      return FALSE;
    }

    $asn = Service_ReceivingOrderDetail::getByField($default['order_code'], 'order_code');

    // 找不到ASN单订单列表或ASN单订单列表订单状态不对
    if (empty($asn) || !in_array((int) $asn['rd_status'], array(0, 1), TRUE)) {
      return FALSE;
    }

    self::$rodInfo = $asn;
    $asn           = Service_Receiving::getByField((int) $asn['receiving_id'], 'receiving_id');

    // 找不到ANS单或ASN单不是集货模式或ASN单状态不对
    if (empty($asn) || 1 !== (int) $asn['receive_model_type'] || !in_array((int) $asn['receiving_status'], array(5, 6), TRUE)) {
      return FALSE;
    }

    self::$isValid   = TRUE;
    self::$orderInfo = $order;
    self::$asnInfo   = $asn;

    // 到这里，没有其他情况，应该返回TRUE
    return TRUE;
  }

  /**
   * 获取当前登录用户仓库ID
   * 
   * @return integer
   */
  public static function getWarehouseId() {
    $user = new Zend_Session_Namespace('userAuthorization');

    if (isset($user->warehouseId)) {
      return (int) $user->warehouseId;
    }

    return 0;
  }

  /**
   * 返回已通过验证的订单单（最后一个，若有多个验证的话）
   * 
   * @return array
   */
  public static function getOrderInfo() {
    return self::$orderInfo;
  }

  /**
   * 返回已通过验证的ASN单（最后一个，若有多个验证的话）
   * 
   * @return array
   */
  public static function getAsnInfo() {
    return self::$asnInfo;
  }

  /**
   * 返回已通过验证的ASN单订单列表订单信息（最后一个，若有多个验证的话）
   * 
   * @return array
   */
  public static function getRodInfo() {
    return self::$rodInfo;
  }

  /**
   * 返回已通过验证的结果（最后一个，若有多个验证的话）
   * 
   * @return boolean
   */
  public static function isValid() {
    return self::$isValid;
  }

  /**
   * 对整个ASN单进行轮候查询
   * 
   * @param string  $asnCode    ASN单号
   * @param boolean $asnDo      是否执行ASN收货动作
   */
  private static function asnPolling($asnCode, $asnDo = FALSE) {
    $asn           = Service_Receiving::getByField(trim($asnCode), 'receiving_code');
    $user          = new Zend_Session_Namespace('userAuthorization');
    $operationTime = date('Y-m-d H:i:s');

    if (7 === (int) $asn['receiving_status']) { // 已收完货
      return ;
    }

    if (5 === (int) $asn['receiving_status']) { // 把ASN在途状态更新为收货中状态
      // 更新ASN单状态
      $asnRow = array(
        'receiving_status'      => 6,
        'receiving_update_time' => $operationTime,
      );
      Service_Receiving::update($asnRow, $asn['receiving_id'], 'receiving_id');

      // 添加ASN日志
      $asnLog = array(
        'receiving_id'   => (int) $asn['receiving_id'],
        'receiving_code' => $asn['receiving_code'],
        'user_id'        => (int) $user->userId,
        'customer_code'  => $asn['customer_code'],
        'rl_note'        => '收货中',
        'rl_status_from' => 5,
        'rl_status_to'   => 6,
        'rl_add_time'    => $operationTime,
        'rl_ip'          => Common_Common::getIP(),
      );
      Service_ReceivingLog::add($asnLog);

      // 更新收货时间
      Service_ReceivingAttribute::update(array(
        'receiving_time' => $operationTime,
      ), (int) $asn['receiving_id'], 'receiving_id');

      self::$asnInfo['receiving_status']      = 6;
      self::$asnInfo['receiving_update_time'] = $operationTime;
    }

    $asnWeight = $asn['roughweight']; // ASN毛重
    $rod       = Service_ReceivingOrderDetail::getByCondition(array('receiving_code' => $asn['receiving_code']));
    $piece     = count($rod);

    // 总件数小于1或不是最后一个收货的订单
    if ($piece < 1 || !$asnDo) {
      return ;
    }

    // 更新ASN单订单列表状态
    Service_ReceivingOrderDetail::update(array(
      'rd_status' => 2, // 处理完成
    ), (int) $asn['receiving_id'], 'receiving_id');

    foreach ($rod as $item) {
      $packProcess = new Service_PackProcess();
      $order = Service_Orders::getByField($item['order_code'], 'order_code');
      $packProcess->jhpack($order['order_code'], '', $order['order_pick_type'], NULL);
    }

    // 更新ASN单状态
    Service_Receiving::update(array(
      'receiving_status'      => 7, // 收货完成
      'receiving_update_time' => $operationTime,
    ), (int) $asn['receiving_id'], 'receiving_id');

    // 添加ASN单日志
    $asnLog = array(
      'receiving_id'   => (int) $asn['receiving_id'],
      'receiving_code' => $asn['receiving_code'],
      'user_id'        => (int) $user->userId,
      'customer_code'  => $asn['customer_code'],
      'rl_note'        => '收货中->收货完成',
      'rl_status_from' => 6,
      'rl_status_to'   => 7,
      'rl_add_time'    => $operationTime,
      'rl_ip'          => Common_Common::getIP(),
    );
    Service_ReceivingLog::add($asnLog);

    // 完成收货时间
    Service_ReceivingAttribute::update(array(
      'complete_received_time' => $operationTime,
    ), (int) $asn['receiving_id'], 'receiving_id');

    // 需要提货的，扣除提货费
    if (1 === (int) $asn['is_delivery']) {
      $income      = array(); // 应收
      $payment     = array(); // 应付
      $keys        = array(
        'warehouseId'      => (int) $asn['warehouse_id'],
        'receiving_weight' => $asnWeight,
        'receiving_code'   => $asn['receiving_code'],
      );
      $otherFeeObj = new Common_CalculateOtherFee();

      $otherFeeObj->setParams($keys);
      $otherFee      = $otherFeeObj->getOtherFee('TIHUO');
      $otherFeeTihuo = $otherFee['data']['otherFee']['tihuo'];

      $asnOrder               = $asn;
      $asnOrder['order_code'] = $asn['receiving_code'];
      $customer               = Service_Customer::getByField($asnOrder['customer_code'], 'customer_code', array(
        'customer_saler_user_id',
        'customer_currency',
      ));

      if ($otherFeeTihuo['price'] > 0) {
        $tihuoFee = Service_OtherFee::getByField('TIHUO', 'fee_code');

        if (!empty($tihuoFee)) { // 解冻提货费
          Service_CustomerBalanceProcess::unfreezeOtherFeeById($asnOrder, $tihuoFee['fee_id'], 'ASN收货,解冻提货费');
        }

        // 扣除提货费
        Service_CustomerBalanceProcess::deductFee($asnOrder['customer_id'], $otherFeeTihuo, 'ASN收货，扣提货费', $asnOrder['receiving_code'], 'TIHUO', $otherFeeTihuo['fee_id']);
        // 转换为客户的币种
        $customerFee = Service_Currency::converByCode($otherFeeTihuo['currency_code'], $customer['customer_currency'], $otherFeeTihuo['price']);
        // 应收
        $income[] = array(
          'customer_code'      => $asnOrder['customer_code'],
          'ft_code'            => 'TIHUO',
          'ut_code'            => 'PCE',
          'sm_code'            => '',
          'bi_amount'          => $customerFee,
          'bi_org_amount'      => $otherFeeTihuo['price'],
          'currency_code'      => $otherFeeTihuo['currency_code'],
          'currency_rate'      => '',
          'bi_chargeable_time' => $operationTime,
          'bi_note'            => '提货费',
        );
      }

      // 应付费用，服务商不能为空
      if (isset($otherFeeTihuo['cost']) && $otherFeeTihuo['cost'] > 0 && '' !== $otherFeeTihuo['sp_code']) {
        $spRow      = Service_ServiceProvider::getByField($otherFeeTihuo['sp_code'], 'sp_code');
        $spCurrency = $spRow['currency_code'];
        $spFee      = Service_Currency::converByCode($otherFeeTihuo['currency_code'], $spCurrency, $otherFeeTihuo['cost']); // 转为服务商币种
        $payment[]  = array(
          'sp_code'            => $otherFeeTihuo['sp_code'], //服务商代码
          'ft_code'            => 'TIHUO',
          'ut_code'            => 'PCE',
          'sm_code'            => '',
          'bp_amount'          => $spFee,
          'bp_org_amount'      => $otherFeeTihuo['cost'],
          'currency_code'      => $otherFeeTihuo['currency_code'],
          'currency_rate'      => '',
          'bp_chargeable_time' => $operationTime,
        );
      }

      // 判断是否存在应收应付
      if(!empty($income) || !empty($payment)) {
        //写入业务表
        $businessLog = array(
          'ds_code' => 'asn',
          'customer_code'             => $asnOrder['customer_code'],
          'warehouse_id'              => $asnOrder['warehouse_id'],
          'sm_code'                   => '',
          'bb_volume_weight'          => $asnWeight,
          'bb_charge_weight'          => $asnWeight,
          'bb_delivered_weight'       => $asnWeight,
          'bb_pieces'                 => $piece,
          'bb_declared_value'         => 0,
          'bb_declared_currency_code' => 'USD',
          'country_code'              => '',
          'bb_postcode'               => '',
          'bb_charge_time'            => $operationTime,
          'bb_declared_time'          => $operationTime, // 发货时间，此时间与服务商对接
          'bb_sales_id'               => $customer['customer_saler_user_id'],
          'bb_refer_code'             => $asnOrder['receiving_code'],
          'bb_service_number'         => '',//ref_tracking_number
          'bb_reference_no'           => '',
        );
        $businessObj = new Process_Business();
        $response    = $businessObj->businessFee($businessLog, $income, $payment);

        if (1 !== (int) $response['state']) {
          throw new Exception($response['message']);
        }
      }
    }

    self::$rodInfo['rd_status']             = 2;
    self::$asnInfo['receiving_status']      = 7;
    self::$asnInfo['receiving_update_time'] = $operationTime;
  }

  /**
   * 执行集货收货的所有操作
   * 
   * @return boolean
   */
  public static function receive() {
    if (!self::isValid()) {
      return FALSE;
    }

    $user  = new Zend_Session_Namespace('userAuthorization');
    $order = self::getOrderInfo();
    $asn   = self::getAsnInfo();
    $rod   = self::getRodInfo();
    $bad   = FALSE;
    $db    = Common_Common::getAdapter();
    $undo  = (int) Service_ReceivingOrderDetail::getByCondition(array(
      'receiving_code' => $asn['receiving_code'],
      'rd_status'      => '0',
    ), 'count(*)');

    // 开启事务
    $db->beginTransaction();

    try {
      $operationTime = date('Y-m-d H:i:s');
      $shipOrder     = Service_ShipOrder::getByField($order['order_code'], 'order_code');

      if (!empty($shipOrder)) { // 存在ship_order数据，只需更新
        $shipOrderRow = array(
          'tracking_number' => $order['ref_tracking_number'],
          'so_update_time'  => $operationTime,
        );
        Service_ShipOrder::update($shipOrderRow, $order['order_code']);
      }
      else { // 不存在ship_order数据，往ship_order表写数据
        $soCode       = Common_GetNumbers::getCode('shiporder', $order['customer_code'], 'SP');
        $shipOrderRow = array(
          'so_code'           => $soCode,
          'order_id'          => $order['order_id'],
          'order_code'        => $order['order_code'],
          'tracking_number'   => $order['ref_tracking_number'],
          'warehouse_id'      => $order['warehouse_id'],
          'pp_barcode'        => '',
          'sm_code'           => $order['sm_code'],
          'so_status'         => 0,
          'so_weight'         => '',
          'so_vol_weight'     => '',
          'so_length'         => '',
          'so_width'          => '',
          'so_height'         => '',
          'so_declared_value' => '',
          'so_shipping_fee'   => '',
          'currency_code'     => '',
          'so_add_time'       => $operationTime,
          'so_ship_time'      => $operationTime,
          'so_update_time'    => $operationTime,
        );
        Service_ShipOrder::add($shipOrderRow);
      }

      // 更新订单信息
      $orderRow = array(
        'order_status'    => 7, // 从已提交状态变为已打包状态
        'time_of_receipt' => $operationTime,
        'update_time'     => $operationTime,
      );
      Service_Orders::update($orderRow, (int) $order['order_id'], 'order_id');

      // 添加订单日志
      $orderLog = array(
        'order_id'          => $order['order_id'],
        'order_code'        => $order['order_code'],
        'ol_type'           => 1,
        'order_status_from' => $order['order_status'],
        'order_status_to'   => 7,
        'ol_add_time'       => $operationTime,
        'user_id'           => (int) $user->userId,
        'ol_ip'             => Common_Common::getIP()
      );
      Service_OrderLog::add($orderLog);

      // 添加轨迹信息
      $warehouse = Service_Warehouse::getByField($order['warehouse_id'], 'warehouse_id');
      $tracker   = array(
        'order_code'          => $order['order_code'],
        'sot_location'        => $warehouse['warehouse_desc'],
        'sot_add_time'        => $operationTime,
        'warehouse_id'        => $order['warehouse_id'],
        'sot_description'     => '集货ASN仓库收货中',
        'sot_type'            => 0,
        'sot_time_offset'     => '',
        'tracking_number'     => $order['order_code'],
        'ref_tracking_number' => '',
        'status_desc'         => '已打包',
        'user_id'             => (int) $user->userId,
      );
      Service_ShipOrderTracking::add($tracker);

      // 更新ASN订单列表订单状态
      $rodRow = array(
        'rd_status'      => 1,
        'rd_update_time' => $operationTime,
      );
      Service_ReceivingOrderDetail::update($rodRow,$rod['rod_id'], 'rod_id');

      // 更新订单操作时间
      $ootRow = array(
        'pack_time'    => $operationTime,
        'pack_user_id' => $user->userId,
      );
      Service_OrderOperationTime::update($ootRow, $order['order_code'], 'order_code');

      $db->commit();

      self::$orderInfo['order_status']    = 7;
      self::$orderInfo['time_of_receipt'] = $operationTime;
      self::$orderInfo['update_time']     = $operationTime;
    }
    catch (Exception $e) {
      $db->rollBack();
      exit(Zend_Json::encode(array('state' => 0, 'message' => $e->getMessage())));
      $bad = TRUE;
    }

    sleep(1); // 休眠1秒钟
    $db->beginTransaction();

    try {
      // ASN单轮询
      self::asnPolling($asn['receiving_code'], 1 === $undo);
      $db->commit();
    }
    catch (Exception $e) {
      $db->rollBack();
      exit(Zend_Json::encode(array('state' => 0, 'message' => $e->getMessage())));
    }

    return !$bad;
  }
}
