<?php
class Service_OutArea {
  const TYPE_TONCAR      = 0; // 柜型类型，吨车
  const TYPE_CONTAINER   = 1; // 柜型类型，集装箱
  const STATUS_DRAFT     = 0; // 出区派车单状态，草稿
  const STATUS_CONFIRMED = 1; // 出区派车单状态，确认
  const ASN_IA_TAG       = 0; // 能否用于创建出区派车单的ASN标识
  const ASN_FILISH       = 1; // 出货单状态，已完成
  const ASN_PENDING      = 2; // 出货单状态，待审核
  const ASN_AUDITED      = 3; // 出货单状态，已审核

  private static $_outArea         = array();
  private static $_outAreaDetail   = array();
  private static $_sbCode          = array();

  /**
   * 能创建出区派车单的ASN状态
   * 
   * @return array
   */
  public static function getAllowedAsnStatus() {
    return array(
      self::ASN_FILISH,
      self::ASN_PENDING,
      self::ASN_AUDITED,
    );
  }

  /**
   * 允许使用的柜型类型
   * 
   * @return array
   */
  public static function getAllowedContainerType() {
    return array(
      self::TYPE_TONCAR,
      self::TYPE_CONTAINER,
    );
  }

  /**
   * 获取柜型类型
   * 
   * @return array
   */
  public static function getContainer() {
    return array(
      self::TYPE_TONCAR    => '吨车',
      self::TYPE_CONTAINER => '集装箱',
    );
  }

  /**
   * 获取出区派车单状态
   * 
   * @return array
   */
  public static function getType() {
    return array(
      self::STATUS_DRAFT     => '草稿',
      self::STATUS_CONFIRMED => '确认',
    );
  }

  /**
   * 验证接收的数据的有效性
   * 
   * @param array $data    需要验证的数据
   * @return mixed         有效返回TRUE，否则返回错误信息数组
   */
  public static function valid($data) {
    $user    = new Zend_Session_Namespace('userAuthorization');
    $default = array(
      'oa_code'        => '',
      'car_number'     => '',
      'ie_port'      => '',
      'container_type' => '',
      'sb_code'       => array(),
    );
    $default = array_merge($default, $data);
    $detail  = array();
    $error   = array();

    if ('' !== $default['oa_code']) {
      $model    = Table_OutArea::getInstance();
      $outArea = $model->getByCode($default['oa_code']);

      if (empty($outArea)) {
        $error[] = '出区派车单【' . $default['oa_code'] . '】不存在';
        return $error;
      }

      if (self::STATUS_DRAFT !== (int) $outArea['status']) {
        $error[] = '出区派车单【' . $default['oa_code'] . '】不是草稿状态';
        return $error;
      }

      self::$_outArea = $outArea;
      $outAreaDetail  = self::getDetailByCode($default['oa_code']);

      foreach ($outAreaDetail as $item) {
        $detail[$item['oad_id']] = $item['sb_code'];
      }

      self::$_outAreaDetail = $detail;
    }

    if ('' === $default['car_number']) {
      $error[] = '车牌号不能为空';
    }
    if ('' === $default['ie_port']) {
      $error[] = '进出口口岸不能为空';
    }
    if (!in_array($default['container_type'], self::getAllowedContainerType(), TRUE)) {
      $error[] = '柜型只能为吨车、集装箱';
    }
    $car=array();
    $port=array();
    $car[]=$default['car_number'];
    $port[]=$default['ie_port'];
    if (!empty($default['sb_code'])) {    //出货总单非空
    foreach ($default['sb_code'] as $code) {
      $shipBatch = Service_ShipBatch::getByField($code, 'sb_code');
      $carNumber = trim($shipBatch['sb_truck_no']);
      $car[]     = $carNumber;
      if ('' === $carNumber) {
          $error[] = '出货总单【' . $code . '】车牌号为空';
          continue ;
        }
      $shipBatchAttr = Service_ShipBatchAttribute::getByField($code, 'sb_code');

      if (empty($shipBatchAttr)) {
            $error[] = '出货总单【' . $code . '】缺乏必要的属性';
            continue ;
        }

        $iePort    = trim($shipBatchAttr['ie_port']);
        $port[]    = $iePort;
        $cabinet[] = ('' !== trim($shipBatchAttr['conta_id'])) ? 1 : 0;

        if ('' === $iePort) {
            $error[] = '出货总单【' . $code . '】缺进出口口岸为空';
                continue ;
        }
      if (empty($shipBatch)) {
        $error[] = '出货总单【' . $code . '】不存在';
      }
      elseif ((int) $user->warehouseId !== (int) $shipBatch['warehouse_id']) {
        $error[] = '出货总单【' . $code . '】不属于当前仓库';
      }
      elseif (!in_array((int) $shipBatch['sb_status'], self::getAllowedAsnStatus(), TRUE)) {
        $error[] = '出货总单【' . $code . '】状态不是已完成、待审核、已审核';
      }
      elseif (self::ASN_IA_TAG !== (int) $shipBatch['out_area'] && !in_array($code, $detail, TRUE)) {
        $error[] = '出货总单【' . $code . '】已创建过出区派车单';
      }
      else {
        self::$_sbCode[$code] = array(
          'sb_id'    => (int) $shipBatch['sb_id'],
          'sb_code'  => $shipBatch['sb_code'],
          'reference_no' => $shipBatch['reference_no'],
        );
      }
    }
   
    if (empty($error)) { // 没有错误信息，则检查车牌号、进出口口岸是否一致
            $ucar     = array_unique($car);
            $uport    = array_unique($port);
            $ucabinet = array_unique($cabinet);

            if (empty($car)) {
              $error[] = '所选的出货总单缺乏车牌号信息';
            }
            elseif (!empty($car) && 1 !== count($ucar)) {
              $error[] = '所选的出货总单存在车牌号不一致的情况';
            }

            if (empty($port)) {
              $error[] = '所选的出货总单缺乏进出口口岸信息';
            }
            elseif (!empty($port) && 1 !== count($uport)) {
              $error[] = '所选的出货总单存在进出口口岸不一致的情况';
            }
            elseif (!empty($uport) && 1 === count($uport)) {
              $iePort = Service_IePort::getByField($uport[0], 'ie_port');

              if (empty($iePort)) {
                $error[] = '进出口口岸【' . $uport[0] . '】不存在';
              }
            }

            /*if (empty($cabinet)) {
              $error[] = '所选的出货总单缺乏柜型信息';
            }
            elseif (!empty($cabinet) && 1 !== count($ucabinet)) {
              $error[] = '所选的出货总单存在柜型不一致的情况';
            }*/
        }
     }
    return empty($error) ? TRUE : $error;
  }

  /**
   * 创建出区派车单
   * 
   * @param array $row    出区派车单数据
   * @return mixed        创建成功返回出区派车单单号，否则返回错误信息数组
   */
  public static function create($row) {
    $error = array();
    $code  = ''; // 出区派车单单号
    $user  = new Zend_Session_Namespace('userAuthorization');
    $db    = Common_Common::getAdapter();

    $db->beginTransaction(); // 开启事务

    try {
      $valid = self::valid($row); // 验证数据有效性

      if (TRUE !== $valid) {
        throw new Exception(join('；', $valid));
      }

      $code        = Common_GetNumbers::getCode('OUT_AREA', '', 'BHO');
      $outAreaRow = array(
        'oa_code'        => $code,
        'car_number'     => $row['car_number'],
        'container_type' => $row['container_type'],
        'ie_port'		 => $row['ie_port'],
        'warehouse_id'   => (int) $user->warehouseId,
        'status'         => self::STATUS_DRAFT,
        'created_time'   => date('Y-m-d H:i:s'),
        'creator'        => (int) $user->userId,
        'creator_ip'     => Common_Common::getIP(),
      );
      if (!($oaId = self::insert($outAreaRow))) {
        throw new Exception('数据库异常，无法入库out_area');
      }
      foreach (self::$_sbCode as $sb) {
        $outAreaDetailRow = array(
          'oa_id'           => $oaId,
          'oa_code'         => $code,
          'sb_code'  => $sb['sb_code'],
        );
        Service_ShipBatch::update(array(
          'out_area' => 1,
        ), $sb['sb_code'], 'sb_code');
        if (!self::insertDetail($outAreaDetailRow)) {
          throw new Exception('数据库异常，无法入库out_area_detail');
        }

      }

      $db->commit(); // 提交
    }
    catch (Exception $e) {
      $error[] = $e->getMessage();
      $db->rollBack(); // 异常回滚
    }

    return empty($error) ? $code : $error;
  }

  /**
   * 更新出区派车单
   * 
   * @param array $row    出区派车单数据
   * @return mixed        成功返回TRUE，否则返回错误信息
   */
  public static function update($row) {
    $code     = trim($row['oa_code']);
    $response = TRUE;
    $db       = Common_Common::getAdapter();

    $db->beginTransaction(); // 开启事务

    try {
      if ('' === $code) {
        throw new Exception('出区派车单号不能为空');
      }

      $valid = self::valid($row); // 验证数据有效性

      if (TRUE !== $valid) {
        throw new Exception(join('；', $valid));
      }

      foreach (self::$_outAreaDetail as $key => $val) { // 删除旧数据，释放ASN选择权
        self::deleteDetailById($key);
        Service_ShipBatch::update(array(
          'out_area' => 0,
        ), $val, 'sb_code');
      }

      foreach (self::$_sbCode as $sb) { // 新增详情，冻结选择权
        self::insertDetail(array(
          'oa_id'           => self::$_outArea['oa_id'],
          'oa_code'         => self::$_outArea['oa_code'],
          'sb_code'  => $sb['sb_code'],
        ));
        Service_ShipBatch::update(array(
          'out_area' => 1,
        ), $sb['sb_code'], 'sb_code');
      }

      self::updateByCode(array(
        'car_number'     => $row['car_number'],
        'ie_port'      => $row['ie_port'],
        'container_type' => $row['container_type'],
        'updated_time'   => date('Y-m-d H:i:s'),
      ), $code);

      $db->commit(); // 提交
    }
    catch (Exception $e) {
      $response = $e->getMessage();
      $db->rollBack(); // 异常回滚
    }

    return $response;
  }

  /**
   * 确认出区派车单
   * 
   * @param string $code    出区派车单号
   * @return mixed          成功返回TRUE，否则返回错误信息
   */
  public static function confirm($code) {
    $code     = trim($code);
    $response = TRUE;
    $db       = Common_Common::getAdapter();

    $db->beginTransaction(); // 开启事务

    try {
      if ('' === $code) {
        throw new Exception('出区派车单号不能为空');
      }

      $outArea = self::getByCode($code);

      if (empty($outArea)) {
        throw new Exception('出区派车单【' . $code . '】不存在');
      }

      if (self::STATUS_DRAFT !== (int) $outArea['status']) {
        throw new Exception('出区派车单【' . $code . '】不是草稿状态');
      }

      $outAreaDetail = self::getDetailByCode($code);

      if (empty($outAreaDetail)) {
        throw new Exception('出区派车单【' . $code . '】为空，不能进行确认');
      }
     /* foreach($outAreaDetail as $out){
      if (!Service_ShipBatch::update(array('out_area' => 1), $out['sb_code'], 'sb_code')){
          throw new Exception('数据库异常，无法更新出货总单');
        }
      }*/
      // 更新出区派车单状态为确认
      self::updateByCode(array(
        'status'         => self::STATUS_CONFIRMED,
        'confirmed_time' => date('Y-m-d H:i:s'),
      ), $code);

      $db->commit(); // 提交
    }
    catch (Exception $e) {
      $response = $e->getMessage();
      $db->rollBack(); // 异常回滚
    }

    return $response;
  }

  /**
   * 根据指定条件检索数据
   * 
   * @param array $condition    检索条件
   * @param array $option       附件条件
   * @return mixed
   */
  public static function getByCondition($condition, $option = array()) {
    $model = Table_OutArea::getInstance();

    return $model->getByCondition($condition, $option);
  }

  /**
   * 根据出区派车单单号检索数据
   * 
   * @param array $code    出区派车单单号
   * @return mixed
   */
  public static function getByCode($code) {
    $model = Table_OutArea::getInstance();

    return $model->getByCode($code);
  }

  /**
   * 新增出区派车单
   * 
   * @param array $row    出区派车单数据
   * @return integer
   */
  public static function insert($row) {
    $model = Table_OutArea::getInstance();

    return $model->insert($row);
  }

  /**
   * 新增出区派车单详情
   * 
   * @param array $row    详情数据
   * @return integer
   */
  public static function insertDetail($row) {
    $model = Table_OutAreaDetail::getInstance();

    return $model->insert($row);
  }

  /**
   * 根据出区派车单单号检索出区派车单出货总单数据
   * 
   * @param array $code    出区派车单单号
   * @return mixed
   */
  public static function getDetailByCode($code) {
    $model = Table_OutAreaDetail::getInstance();

    return $model->getByParentCode($code);
  }

  /**
   * 根据出区派车单单号更新数据
   * 
   * @param array $code    出区派车单单号
   * @return mixed
   */
  public static function updateByCode($data, $code) {
    $model = Table_OutArea::getInstance();

    return $model->updateByCode($data, $code);
  }

  /**
   * 根据出区派车单详情ID更新数据
   * 
   * @param array $data    需要更新的字段，键值对
   * @param array $id      出区派车单详情ID
   * @return integer
   */
  public static function updateDetailById($data, $id) {
    $model = Table_OutAreaDetail::getInstance();

    return $model->updateById($data, $id);
  }

  /**
   * 根据出区派车单详情ID删除数据
   * 
   * @param array $id      出区派车单详情ID
   * @return integer
   */
  public static function deleteDetailById($id) {
    $model = Table_OutAreaDetail::getInstance();

    return $model->deleteById($id);
  }
}
