/** * 创建订单操作 */ 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); }