コード例 #1
0
 /**
  * 创建订单操作
  */
 public function doCreateAction()
 {
     if (!$this->getRequest()->isPost()) {
         $this->flash(0, '错误来源的表单提交');
     }
     $stacode = $this->input('sta') ?: $this->_hostel['h_order_default_stacode'];
     if ($stacode !== ORDER_STATUS_YD && $stacode !== ORDER_STATUS_BL) {
         $this->flash(0, '指定的订单状态码错误');
     }
     $channel = $this->loadUsableChannel($this->input('cid'));
     if (!$channel['hc_status']) {
         $this->flash(0, '指定的预订渠道不可用');
     }
     $typedef = $this->loadUsableTypedef($this->input('tid'));
     if (!$typedef['ht_status']) {
         $this->flash(0, '指定的预订类型不可用');
     }
     $saleman = $this->loadUsableSaleman($this->input('uid'));
     if (!$saleman['u_status']) {
         $this->flash(0, '指定的销售人员不可用');
     }
     $gbker = $this->fetchOrderGuest($this->input('gbker', 'array'), HOTEL_GUEST_TYPE_BOOK);
     if (empty($gbker)) {
         $this->flash(0, '没有指定下单的预订客人');
     }
     $order = $this->input('order', 'array');
     if (empty($order)) {
         $this->flash(0, '没有选择需预订的房间');
     }
     $price = $this->input('price', 'array');
     if (empty($price)) {
         $this->flash(0, '没有指定成交房费明细');
     }
     $brice = $this->input('brice', 'array');
     if (empty($brice)) {
         $this->flash(0, '没有指定账单房费明细');
     }
     if (($count = count($order)) > static::ORDER_LIMIT) {
         $this->flash(0, __('单次预订不允许超过%d个房间', static::ORDER_LIMIT));
     }
     if ($count !== count($price) || $count !== count($brice)) {
         $this->flash(0, '订单和房费明细不匹配');
     }
     $ctime = time();
     $dtime = strtotime(date('Y-m-d', $ctime));
     $ltime = null;
     $omber = $this->input('mno');
     $omber = empty($omber) ? null : $this->loadUsableMberByUqno($omber);
     if (isset($omber['m_status']) && !$omber['m_status']) {
         $this->flash(0, '会员已停用,不允许新的订单与其关联');
     }
     $obill = $this->input('bid');
     $obill = empty($obill) ? null : $this->loadUsableBill($obill);
     if (isset($obill['b_status']) && $obill['b_status'] !== BILL_STATUS_KF) {
         $this->flash(0, '账单已关闭,不允许新的订单与其关联');
     }
     if (empty($obill)) {
         $settlem = $this->loadUsableSettlem($this->input('sid'));
         if (!$settlem['hs_status']) {
             $this->flash(0, '指定的结算方式不可用');
         }
         if ($this->input('lft')) {
             $ldate = $this->input('ldate');
             $lhour = $this->input('lhour', 'numeric');
             $lminu = $this->input('lminu', 'numeric');
             isset($lhour[1]) or $lhour = '0' . $lhour;
             isset($lminu[1]) or $lminu = '0' . $lminu;
             if (!Zyon_Util::isDate($ldate) || !Zyon_Util::isTime($lhour . ':' . $lminu)) {
                 $this->flash(0, '账单过期时间格式错误');
             }
             $ltime = strtotime($ldate . ' ' . $lhour . ':' . $lminu);
             if ($ltime < $ctime - 59) {
                 $this->flash(0, __('账单过期时间不能早于当前时间%s', date('Y-m-d H:i', $ctime)));
             }
         }
     }
     // 以下处理订单集合
     $saved = $value_rules_conds = $other_order_conds = array();
     foreach ($order as $idx => &$val) {
         if (!is_array($val) || !isset($val['room']) || !Zyon_Util::isUnsignedInt($val['room']) || $val['room'] < 1 || !isset($val['date']) || !isset($val['hour']) || !isset($val['minu']) || !is_array($val['date']) || !isset($val['date'][0]) || !isset($val['date'][1]) || !is_array($val['hour']) || !isset($val['hour'][0]) || !isset($val['hour'][1]) || !is_array($val['minu']) || !isset($val['minu'][0]) || !isset($val['minu'][1]) || !is_numeric($val['hour'][0]) || !is_numeric($val['hour'][1]) || !is_numeric($val['minu'][0]) || !is_numeric($val['minu'][1]) || !Zyon_Util::isDate($val['date'][0]) || !Zyon_Util::isDate($val['date'][1]) || !Zyon_Util::isDateTime($val['date'][0] . ' ' . $val['hour'][0] . ':' . $val['minu'][0]) || !Zyon_Util::isDateTime($val['date'][1] . ' ' . $val['hour'][1] . ':' . $val['minu'][1]) || !isset($val['lver']) || !is_array($val['lver']) || !isset($val['memo']) || !is_string($val['memo']) || !isset($price[$idx]) || !is_array($price[$idx]) || !isset($brice[$idx]) || !is_array($brice[$idx])) {
             $this->flash(0, '参数错误');
         }
         $val['attr'] = $this->model('order')->getAttrCodeByList(isset($val['attr']) && is_array($val['attr']) ? $val['attr'] : array());
         $val['datm'][0] = strtotime($val['date'][0]);
         $val['datm'][1] = strtotime($val['date'][1]);
         if ($val['datm'][1] < $dtime) {
             $this->flash(0, '订单离店时间不能在今天之前');
         }
         $val['lgth'] = ($val['datm'][1] - $val['datm'][0]) / 86400;
         if ($val['lgth'] < $this->_hostel['h_order_minlens'] || $val['lgth'] > $this->_hostel['h_order_maxlens']) {
             $this->flash(0, __('旅店仅支持创建天数介于 %d 到 %d 的订单', $this->_hostel['h_order_minlens'], $this->_hostel['h_order_maxlens']));
         }
         $val['lver'] = $this->fetchOrderGuest($val['lver'], HOTEL_GUEST_TYPE_LIVE);
         $val['pval'] = $this->fetchOrderPrice($price[$idx], $val['date'][0], $val['date'][1]);
         $val['bval'] = $this->fetchOrderPrice($brice[$idx], $val['date'][0], $val['date'][1]);
         $val['time'][0] = strtotime($val['date'][0] . ' ' . $val['hour'][0] . ':' . $val['minu'][0]);
         $val['time'][1] = strtotime($val['date'][1] . ' ' . $val['hour'][1] . ':' . $val['minu'][1]);
         $value_rules_conds[] = sprintf('(rp_rid = %d AND rp_btime <= %d AND rp_etime >= %d)', $val['room'], $val['datm'][0] + ($val['lgth'] - 1) * 86400, $val['datm'][0]);
         $other_order_conds[] = sprintf('(o_rid = %d AND o_bdatm <= %d AND o_edatm >= %d)', $val['room'], $val['datm'][1], $val['datm'][0]);
         $saved[$val['room']] = array();
     }
     unset($val);
     $order = Zyon_Array::group($order, 'room');
     $value_rules_conds = implode(' OR ', $value_rules_conds);
     $other_order_conds = implode(' OR ', $other_order_conds);
     $rooms = Zyon_Array::keyto($this->model('room')->getRoomAryByIds(array_keys($order)), 'r_id');
     if (empty($rooms) || count($rooms) !== count($order)) {
         $this->flash(0, '找不到指定预订的房间');
     }
     // 以下处理每个房间的启用日、停用段以及订单最长时间限制
     foreach ($rooms as $rid => &$val) {
         if ($val['r_hid'] !== $this->_hostel['h_id']) {
             $this->flash(0, '找不到指定预订的房间');
         }
         foreach ($order[$rid] as &$v) {
             $btime = $v['datm'][0];
             $etime = $v['datm'][1] - 1;
             if ($btime < $val['r_otime']) {
                 $this->flash(0, __('房间%s在%s之前尚未启用', $val['r_name'], date('Y-m-d', $val['r_otime'])));
             }
             for ($_btime = max($btime, $dtime + 86400 * $this->_hostel['h_order_enddays']); $_btime < $etime; $_btime += 86400) {
                 $this->flash(0, __('%s的房间%s超出时间限制', date('Y-m-d', $_btime), $val['r_name']));
             }
             if ($val['r_btime']) {
                 $_r_btime = max($btime, $val['r_btime']);
                 $_r_etime = min($etime, $val['r_etime']);
                 while ($_r_btime < $_r_etime) {
                     $this->flash(0, __('%s的房间%s已停用', date('Y-m-d', $_r_btime), $val['r_name']));
                 }
             }
         }
         unset($v);
     }
     unset($val);
     // 以下处理订单集合内的冲突
     if ($stacode === ORDER_STATUS_BL) {
         foreach ($order as &$val) {
             foreach ($val as $k => &$v) {
                 foreach ($val as $i => &$o) {
                     if ($k !== $i && $k['time'][0] < $o['time'][1] && $k['time'][1] > $o['time'][0]) {
                         $this->flash(0, __('房间%s的订单时间冲突,不能同时创建', $rooms[$v['room']]['r_name']));
                     }
                 }
                 unset($o);
             }
             unset($v);
         }
         unset($val);
     }
     // 以下处理与系统订单的冲突
     $other = $this->model('order')->getOrderAryByIds($this->model('order')->fetchIds(array('o_hid = ' . $this->_hostel['h_id'], 'o_status <> ' . $this->model('order')->quote(ORDER_STATUS_YQX), 'o_status <> ' . $this->model('order')->quote(ORDER_STATUS_YD), $other_order_conds)));
     if (!is_array($other)) {
         $this->flash(0, '无法获取系统订单的信息');
     }
     if (!empty($other)) {
         foreach ($other as &$val) {
             $rid = $val['o_rid'];
             foreach ($order[$rid] as &$v) {
                 if ($val['o_edatm'] == $v['datm'][0] && $v['time'][0] < $val['o_etime']) {
                     $this->flash(0, __('%s的房间%s已被其它订单占用', date('Y-m-d H:i', $v['time'][0]), $rooms[$rid]['r_name']));
                 }
                 if ($val['o_bdatm'] == $v['datm'][1] && $v['time'][1] > $val['o_btime']) {
                     $this->flash(0, __('%s的房间%s已被其它订单占用', date('Y-m-d H:i', $v['time'][1]), $rooms[$rid]['r_name']));
                 }
                 $_o_btime = max($v['datm'][0], $val['o_bdatm']);
                 $_o_etime = min($v['datm'][1], $val['o_edatm']);
                 while ($_o_btime < $_o_etime) {
                     $this->flash(0, __('%s的房间%s已被其它订单占用', date('Y-m-d', $_o_btime), $rooms[$rid]['r_name']));
                 }
             }
             unset($v);
         }
         unset($val);
     }
     unset($other);
     /**
      * 开启事务,创建订单
      */
     $this->model('order')->dbase()->beginTransaction();
     try {
         if (empty($obill)) {
             if (!($bid = $this->model('bill')->addBill($this->model('bill')->getNewBill($this->_hostel['h_id'], $settlem['hs_id'], $settlem['hs_name'], 0, 0, mb_substr($gbker['o_gbker_name'], 0, 10) . '-' . date('ymdHi', $_SERVER['REQUEST_TIME']), $ltime)))) {
                 throw new exception('创建账单失败');
             }
             if ($obill = $this->model('bill')->getBill($bid)) {
                 $this->model('log.bill')->addLog($this->model('log.bill')->getNewCreateLog($this->_master, $obill));
             } else {
                 throw new exception('读取账单失败');
             }
         }
         $obval = array();
         foreach (array_keys($order) as $rid) {
             foreach ($order[$rid] as &$val) {
                 /**
                  * 检查房间状态
                  */
                 if (!$this->model('order')->chkCanCreateOrder($this->_hostel, $rooms[$rid], $val['time'][0], $val['time'][1])) {
                     throw new exception('无法创建订单,房间不可用');
                 }
                 $map = $this->model('order')->getNewOrder($rooms[$rid], $val['time'][0], $val['time'][1], json_encode($val['pval']), json_encode($val['bval']), $stacode);
                 if ($omber) {
                     $map['o_mid'] = $omber['m_id'];
                     $map['o_mno'] = $omber['m_no'];
                 }
                 $map['o_bid'] = $obill['b_id'];
                 $map['o_sid'] = $saleman['u_id'];
                 $map['o_snm'] = $saleman['u_realname'];
                 $map['o_cid'] = $channel['hc_id'];
                 $map['o_cnm'] = $channel['hc_name'];
                 $map['o_tid'] = $typedef['ht_id'];
                 $map['o_tnm'] = $typedef['ht_name'];
                 $map['o_attr'] = $val['attr'];
                 $map['o_memo'] = $val['memo'];
                 // 加入旅客信息
                 $map = array_merge($gbker, $val['lver'], $map);
                 $oid = $this->model('order')->addOrder($map);
                 if (!$oid) {
                     throw new exception('创建订单记录失败');
                 }
                 if ($map = $this->model('order')->getOrder($oid)) {
                     $this->model('log.order')->addLog($this->model('log.order')->getNewCreateLog($this->_master, $map));
                 }
                 $obval[$oid] = $map['o_brice'];
             }
             unset($val);
         }
         if (!$this->model('bill')->modBill($obill['b_id'], array('b_cost' => $this->model('bill')->expr('b_cost + ' . array_sum($obval))))) {
             throw new exception('更新账单信息失败');
         }
         foreach ($obval as $idx => $val) {
             $obval[$idx] = __('%d号订单的账单房费 %d', $idx, $val / 100);
         }
         $this->model('log.bill')->addLog($this->model('log.bill')->getNewUpdateLog($this->_master, $obill, $this->model('bill')->getBill($obill['b_id']), implode(",\n", $obval)));
         $this->model('order')->dbase()->commit();
         $this->flash(1, array('forward' => "/master/bill/detail?bid={$obill['b_id']}"));
     } catch (Exception $e) {
         $this->model('order')->dbase()->rollBack();
         $this->error($e);
     }
     $this->flash(0);
 }