You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1603 lines
90 KiB

  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: Steven
  5. * Date: 2017/12/25
  6. * Time: 18:40
  7. */
  8. namespace backend\modules\hotel\models;
  9. use backend\modules\api\logic\BaseBalance;
  10. use common\components\zOfficeWechat;
  11. use Yii;
  12. use yii\db\Exception;
  13. use backend\common\Utils;
  14. use common\components\zHttp;
  15. class CommonOrder extends OrderMain
  16. {
  17. public $HotelID; //酒店ID
  18. public $RoomID; //房型ID,opera_hotel_room中的ID
  19. public $RoomNum; //房间数量1
  20. public $CheckIn; //入住日期
  21. public $CheckOut; //离店日期
  22. public $DistribID; //渠道ID
  23. public $RoomPrices; //价格日历
  24. public $IfCheckPrice; //是否做价格校验
  25. public $ZZ_ORDER_ID; //我们系统的订单号(蜘蛛订单号)
  26. public $OrderID; //渠道订单号
  27. public $TotalPrice; //订单总价
  28. public $Currency; //币种
  29. public $ContactName; //联系人姓名
  30. public $ContactTel; //联系人电话
  31. public $OrderGuests; //入住人信息
  32. public $Comment; // 客人备注
  33. public $NeedInvoice; //是否需要开发票
  34. public $InvoiceInfos; //object 发票信息
  35. public $CreateUserID;
  36. public $RunTime; //最晚到店时间 格式2017-12-28 23:30:00
  37. public $PayType; //支付方式
  38. public $PayTradeNo; //支付流水号
  39. public $Reason; //订单取消原因
  40. public $CommentType; //备注类型 1:内部 2 外部
  41. public $Commission; //分销佣金
  42. public $OrderTitleID; //组合单号 如果不是组合订单,则为0,否则为组合单的订单号
  43. //返回值 该返回值为标准返回码,对渠道而言,需要根据渠道需要的
  44. const RETURN_CODE_SUCCESS = 0; //操作成功
  45. const RETURN_CODE_CANCEL_FAIL = 100; //取消失败/异常
  46. const RETURN_CODE_STOCK_FAIL = 101; //酒店满房/房量不足
  47. const RETURN_CODE_NOTICE_FAIL = 102; //备注不接受
  48. const RETURN_CODE_PRICE_FAIL = 103; //价格错误
  49. const RETURN_CODE_DATE_FAIL = 104; //日期错误/日期超过最大入住天数
  50. const RETURN_CODE_CHECKOUT = 105; //已入住不允许取消或修改
  51. const RETURN_CODE_EXPIRED = 106; //已过最晚取消修改时间
  52. const RETURN_CODE_NOT_EXIST = 107; //修改/取消原订单不存在
  53. const RETURN_CODE_PROGRAM_FAIL = 108; //程序错误
  54. const RETURN_CODE_NETWORK_FAIL = 109; //网络问题(程序错误)
  55. const RETURN_CODE_GUARANTEE_FAIL = 110; //担保错误
  56. const RETURN_CODE_HOTEL_CLOSED = 111; //酒店已停止合作
  57. const RETURN_CODE_MAPPING_FAIL = 112; //直连匹配错误(程序错误)
  58. const RETURN_CODE_REPEAT = 113; //重复预定
  59. const RETURN_CODE_NEED_TOTAL_GUARANTEE = 114; // 需要全额担保
  60. const RETURN_CODE_OVER_NUM = 115; //人数超限
  61. const RETURN_CODE_OVER_STOCK = 116; //客人当天累计已超间,请提供担保 重新预订
  62. const RETURN_CODE_SYSTEM_FAIL = 117; //服务器运行错误(程序错误)
  63. const RETURN_CODE_AUTH_FAIL = 118; //用户认证或授权错误(程序错误)
  64. const RETURN_CODE_PARAMS_FAIL = 119; //参数错误(程序错误)
  65. const RETURN_CODE_INFO_FAIL = 120; //预订信息不正确
  66. const RETURN_CODE_NOT_ALLOW_UPDATE = 121; //订单不允许修改
  67. const RETURN_CODE_NOT_ALLOW_CANCEL = 122; //订单不允许取消
  68. const RETURN_CODE_NEED_ALL_GUARANTEE = 123; //需要一律担保
  69. const RETURN_CODE_BREAKFAST_FAIL = 124; //早餐不一致
  70. const RETURN_CODE_CURRENCY_FAIL = 125; //币种错误
  71. const RETURN_CODE_UNAUTHORIZED = 126; //渠道未授权
  72. const RETURN_CODE_ROOM_CLOSED = 127; //房型已下线
  73. const RETURN_CODE_OTHER = 9999; //其他
  74. const RETURN_CODE_MAKE_ORDER = 180; // 下单扣款
  75. const RETURN_CODE_CANCEL_ORDER = 181; // 取消单扣款
  76. const RETURN_CODE_UPDATE_ORDER = 182; // 修改单扣款
  77. const SEND_REQUEST_GET = 1; // 请求类型GET
  78. const SEND_REQUEST_POST = 2; // 请求类型POST
  79. CONST RETURN_MSG = [
  80. self::RETURN_CODE_SUCCESS => '操作成功',
  81. self::RETURN_CODE_CANCEL_FAIL => '取消失败/异常',
  82. self::RETURN_CODE_STOCK_FAIL => '酒店满房/房量不足',
  83. self::RETURN_CODE_NOTICE_FAIL => '备注不接受',
  84. self::RETURN_CODE_PRICE_FAIL => '价格错误',
  85. self::RETURN_CODE_DATE_FAIL => '日期错误/日期超过最大入住天数',
  86. self::RETURN_CODE_CHECKOUT => '已入住不允许取消或修改',
  87. self::RETURN_CODE_EXPIRED => '已过最晚取消修改时间',
  88. self::RETURN_CODE_NOT_EXIST => '修改/取消原订单不存在',
  89. self::RETURN_CODE_PROGRAM_FAIL => '程序错误',
  90. self::RETURN_CODE_NETWORK_FAIL => '网络问题(程序错误)',
  91. self::RETURN_CODE_GUARANTEE_FAIL => '担保错误',
  92. self::RETURN_CODE_HOTEL_CLOSED => '酒店已停止合作/酒店已停售/下架',
  93. self::RETURN_CODE_MAPPING_FAIL => '直连匹配错误(程序错误)',
  94. self::RETURN_CODE_REPEAT => '重复预定',
  95. self::RETURN_CODE_NEED_TOTAL_GUARANTEE => '需要全额担保',
  96. self::RETURN_CODE_OVER_NUM => '人数超限',
  97. self::RETURN_CODE_OVER_STOCK => '客人当天累计已超间,请提供担保 重新预订',
  98. self::RETURN_CODE_SYSTEM_FAIL => '服务器运行错误(程序错误)',
  99. self::RETURN_CODE_AUTH_FAIL => '用户认证或授权错误(程序错误)',
  100. self::RETURN_CODE_PARAMS_FAIL => '参数错误(程序错误)',
  101. self::RETURN_CODE_INFO_FAIL => '预订信息不正确',
  102. self::RETURN_CODE_NOT_ALLOW_UPDATE => '订单不允许修改',
  103. self::RETURN_CODE_NOT_ALLOW_CANCEL => '订单不允许取消',
  104. self::RETURN_CODE_NEED_ALL_GUARANTEE => '需要一律担保',
  105. self::RETURN_CODE_BREAKFAST_FAIL => '早餐不一致',
  106. self::RETURN_CODE_CURRENCY_FAIL => '币种错误',
  107. self::RETURN_CODE_UNAUTHORIZED => '该渠道未授权',
  108. self::RETURN_CODE_CURRENCY_FAIL => '币种错误',
  109. self::RETURN_CODE_ROOM_CLOSED => '房型已下线',
  110. self::RETURN_CODE_OTHER => '其他',
  111. self::RETURN_CODE_MAKE_ORDER => '下单扣款失败',
  112. self::RETURN_CODE_CANCEL_ORDER => '取消订单金额回退失败',
  113. self::RETURN_CODE_UPDATE_ORDER => '修改单渠道预付款处理失败',
  114. self::ERROR_DEDUCTION_TYPE => '未知的扣款类型',
  115. ];
  116. CONST BUYOUT = 228; //库存类型 买断
  117. const REMAIN = 230; //库存类型 保留
  118. const INQUIRY = 229;//库存类型 现询
  119. const PAY_TYPE_ALIPAY = 638; //支付宝支付
  120. const PAY_TYPE_CASH = 221; //现金支付
  121. const PAY_TYPE_CREDIT = 275; //授信支付
  122. const PAY_TYPE_WEIXIN = 278; //微信支付
  123. const MAKE_ORDER_DEDUCTION_TYPE = 251; // 下单扣款
  124. const CANCEL_ORDER_DEDUCTION_TYPE = 252; // 取消单扣款
  125. const UPDATE_ORDER_DEDUCTION_TYPE = 253; // 修改单扣款
  126. const ERROR_DEDUCTION_TYPE = 254; // 错误扣款类型
  127. public function __construct(array $config = [])
  128. {
  129. parent::__construct($config);
  130. }
  131. public function scenarios()
  132. {
  133. $scenarios['BookHotelOrder'] = ['OrderID', 'HotelID', 'RoomID', 'DistribID', 'RoomNum', 'CheckIn', 'CheckOut', 'TotalPrice', 'Currency', 'ContactName',
  134. 'ContactTel', 'OrderGuests', 'Comment', 'NeedInvoice', 'InvoiceInfos', 'RoomPrices', 'CreateUserID', 'RunTime', 'PayType', 'PayTradeNo', 'Commission', 'CommentType', 'OrderTitleID'];
  135. $scenarios['CheckRoomAvail'] = ['HotelID', 'RoomID', 'RoomNum', 'CheckIn', 'CheckOut', 'DistribID', 'RoomPrices', 'IfCheckPrice', 'CreateUserID'];
  136. $scenarios['CancelHotelOrder'] = ['CreateUserID', 'OrderID', 'HotelID', 'RoomID', 'DistribID', 'Reason'];
  137. $scenarios['UpdateHotelOrder'] = ['ZZ_ORDER_ID', 'OrderID', 'HotelID', 'RoomID', 'DistribID', 'RoomNum', 'CheckIn', 'CheckOut', 'TotalPrice', 'Currency', 'ContactName',
  138. 'ContactTel', 'OrderGuests', 'Comment', 'NeedInvoice', 'InvoiceInfos', 'RoomPrices', 'CreateUserID', 'RunTime'];
  139. $scenarios['Product'] = ['RoomID', 'DistribID', 'CheckIn', 'CheckOut'];
  140. return $scenarios;
  141. }
  142. public function rules()
  143. {
  144. return [
  145. [['HotelID', 'RoomID', 'RoomNum', 'CheckIn', 'CheckOut', 'DistribID', 'RoomPrices', 'IfCheckPrice'], 'required', 'on' => 'CheckRoomAvail'],
  146. [['OrderID', 'HotelID', 'RoomID', 'DistribID', 'RoomNum', 'CheckIn', 'CheckOut', 'TotalPrice', 'OrderGuests', 'NeedInvoice',
  147. 'RoomPrices', 'PayType'], 'required', 'on' => 'BookHotelOrder'],
  148. [['Currency', 'ContactName', 'Comment', 'InvoiceInfos', 'RunTime', 'PayTradeNo', 'ContactTel', 'Commission', 'CommentType', 'OrderTitleID'], 'safe', 'on' => 'BookHotelOrder'],
  149. [['CreateUserID', 'HotelID', 'OrderID', 'RoomID', 'DistribID'], 'required', 'on' => 'CancelHotelOrder'],
  150. [['ZZ_ORDER_ID', 'OrderID', 'HotelID', 'RoomID', 'DistribID', 'RoomNum', 'CheckIn', 'CheckOut', 'TotalPrice',
  151. 'OrderGuests', 'NeedInvoice', 'RoomPrices'], 'required', 'on' => 'UpdateHotelOrder'],
  152. [['Currency', 'ContactName', 'Comment', 'InvoiceInfos', 'RunTime'], 'safe', 'on' => 'UpdateHotelOrder'],
  153. [['Reason'], 'safe', 'on' => 'CancelHotelOrder'],
  154. [['HotelID'], 'checkOrderExist', 'on' => 'CancelHotelOrder'],
  155. [['RoomID', 'DistribID', 'CheckIn', 'CheckOut'], 'required', 'on' => 'Product'],
  156. //共用
  157. [['CheckIn', 'CheckOut'], 'date', 'format' => 'yyyy-mm-dd'],
  158. [['RoomNum', 'NeedInvoice'], 'number'],
  159. ];
  160. }
  161. /**
  162. * Notes:
  163. * User: Steven
  164. * Date: 2018/1/10
  165. * Time: 14:48
  166. * @param array $data
  167. * @param null $formName
  168. * @return bool
  169. */
  170. public function load($data, $formName = null)
  171. {
  172. $scope = $formName === null ? $this->formName() : $formName;
  173. if ($scope === '' && !empty($data)) {
  174. $this->setAttributes($data);
  175. if ($this->NeedInvoice) {
  176. $this->InvoiceInfos = new OrderInvoiceInfo();
  177. $this->InvoiceInfos->NeedInvoice = $this->NeedInvoice;
  178. $this->InvoiceInfos->OrderID = $this->OrderID;
  179. $this->InvoiceInfos->ChannelId = $this->DistribID;
  180. $this->InvoiceInfos->InvoiceMoney = "$this->TotalPrice";
  181. $flag = $this->InvoiceInfos->load($data['InvoiceInfos'], '') && $this->InvoiceInfos->validate();
  182. /*if (!$flag) {
  183. $error = array_values($this->InvoiceInfos->getFirstErrors());
  184. $this->addError('InvoiceInfos', $error[0]);
  185. return false;
  186. }*/
  187. }
  188. return true;
  189. } elseif (isset($data[$scope])) {
  190. $this->setAttributes($data[$scope]);
  191. return true;
  192. } else {
  193. return false;
  194. }
  195. }
  196. /**
  197. * Notes: 取消订单的时候查询订单是否
  198. * User: Steven
  199. * Date: 2018/1/3
  200. * Time: 10:45
  201. */
  202. public function checkOrderExist()
  203. {
  204. $res_order_id = OrderMain::find()->select(['ORDER_ID', 'CHANNEL_ORDER_STATUS', 'PROD_ID', 'PARENT_PROD_ID'])->where([
  205. 'OUTSIDE_ORDER_NO' => "{$this->OrderID}",
  206. 'ORDER_PROD_TYPE' => OrderMain::ORDER_PROD_TYPE_MAIN,
  207. 'PARENT_ORDER_ID' => 0,
  208. 'order_main.CANCEL_FLAG' => 0,
  209. ])->limit(1)->asArray()->one();
  210. if (empty($res_order_id)) {
  211. $this->addError('OrderID', '该订单不存在,请核实后在进行相关操作!');
  212. }
  213. }
  214. /**
  215. * Notes:下单前的可定检查
  216. * User: Steven
  217. * Date: 2018/1/10
  218. * Time: 14:06
  219. */
  220. public function checkRoomAvail($order_id = 0)
  221. {
  222. $res = $this->getProductData();
  223. $date_list = Utils::createDateRangeArray($this->CheckIn, $this->CheckOut);
  224. if (!empty($res) && count($res) == count($date_list)) {
  225. $roomPrice = [];
  226. $total_price = 0;
  227. $return_code = 0;
  228. $availInfo = [];
  229. $room_num = 0;
  230. if ($order_id) {
  231. $room_num = $this->getRoomNum($order_id);
  232. }
  233. foreach ($res as $item) {
  234. //检查渠道是否授权
  235. if (!$item['AUTHORITY_STATUS']) {
  236. $return_code = self::RETURN_CODE_UNAUTHORIZED;
  237. }
  238. //检查产品是否上线
  239. if ($item['ROOM_IS_ONSALE'] == 0 || $item['ROOM_DAY_IS_ONSALE'] == 0 || $item['DISTRIB_DAY_IS_ONSALE'] == 0) {
  240. $return_code = self::RETURN_CODE_ROOM_CLOSED;
  241. }
  242. //检查是否关房
  243. if ($item['ROOM_RUN_STATUS'] == 0 || $item['DISTRIB_RUN_STATUS'] == 329) { //ROOM_RUN_STATUS=0 房型关房;DISTRIB_RUN_STATUS=329渠道关房
  244. $return_code = self::RETURN_CODE_STOCK_FAIL;
  245. }
  246. //判断库存
  247. if ($order_id) {
  248. if (($item['BUYOUT'] + $item['RETAIN'] + $item['INQUIRY'] + $room_num) < $this->RoomNum) {
  249. $return_code = self::RETURN_CODE_STOCK_FAIL;
  250. }
  251. if (($item['REMAINING_COUNT'] + $room_num) < $this->RoomNum && $item['OVERSELL_FLAG'] == 0) { //给渠道的库存不足且不允许超卖
  252. $return_code = self::RETURN_CODE_STOCK_FAIL;
  253. }
  254. } else {
  255. if (($item['BUYOUT'] + $item['RETAIN']) < $this->RoomNum && $item['INQUIRY'] < $this->RoomNum) {
  256. $return_code = self::RETURN_CODE_STOCK_FAIL;
  257. }
  258. if ($item['REMAINING_COUNT'] < $this->RoomNum && $item['OVERSELL_FLAG'] == 0) { //给渠道的库存不足且不允许超卖
  259. $return_code = self::RETURN_CODE_STOCK_FAIL;
  260. }
  261. }
  262. //价格校验
  263. if ($this->IfCheckPrice) {
  264. foreach ($this->RoomPrices as $val) {
  265. $newPrice = $item['SALE_TYPE'] == 177 ? $item['PROD_PRICE'] : $item['CUS_PRICE'];//分销选取分销价,其他选择零售价
  266. if ($val['RUN_DATE'] == $item['RUN_DATE']) {
  267. if ($newPrice != $val['PRICE']) {
  268. $return_code = self::RETURN_CODE_PRICE_FAIL;
  269. }
  270. }
  271. }
  272. }
  273. $newPrice = $item['SALE_TYPE'] == 177 ? $item['PROD_PRICE'] : $item['CUS_PRICE'];//分销选取分销价,其他选择零售价
  274. $roomPrice[$item['RUN_DATE']] = [
  275. 'run_date' => $item['RUN_DATE'],
  276. 'price' => $newPrice,
  277. 'avail_quantity' => (string)($availInfo['code'] <> 0 ? 0 :
  278. ($item['OVERSELL_FLAG'] == 1 ? ($item['BUYOUT'] + $item['INQUIRY'] + $item['RETAIN']) : $item['REMAINING_COUNT'])),
  279. ];
  280. $total_price += $newPrice;
  281. }
  282. $availInfo = [
  283. 'total_price' => $total_price * $this->RoomNum,
  284. 'room_price' => $roomPrice,
  285. ];
  286. if ($return_code <> 0) {
  287. return ['code' => $return_code, 'info' => self::RETURN_MSG[$return_code]];
  288. }
  289. } else {
  290. return ['code' => self::RETURN_CODE_PROGRAM_FAIL, 'info' => self::RETURN_MSG[self::RETURN_CODE_PROGRAM_FAIL]];
  291. }
  292. return ['code' => self::RETURN_CODE_SUCCESS, 'info' => self::RETURN_MSG[self::RETURN_CODE_SUCCESS], 'data' => $availInfo];
  293. }
  294. /**
  295. * Notes:下单接口
  296. * User: Steven
  297. * Date: 2017/12/28
  298. * Time: 15:19
  299. * @return array
  300. * @throws \yii\db\Exception
  301. */
  302. public function bookHotelOrder()
  303. {
  304. $flag = false; //标识是否设置订单为现询的(包括保留房和非保留房混合的情况,全是现询房)
  305. $data = $this->getProductData();
  306. $hotelInfo = $this->getHotelInfo();
  307. if ($data) {
  308. $transaction = Yii::$app->db->beginTransaction();
  309. $stock_arr = []; //订单最终消耗的类型及数量
  310. try {
  311. foreach ($data as $item) {
  312. //检查渠道是否授权
  313. if (!$item['AUTHORITY_STATUS']) {
  314. return ['code' => self::RETURN_CODE_UNAUTHORIZED, 'info' => self::RETURN_MSG[self::RETURN_CODE_UNAUTHORIZED]];
  315. }
  316. //检查产品是否上线
  317. if ($item['ROOM_IS_ONSALE'] == 0 || $item['ROOM_DAY_IS_ONSALE'] == 0 || $item['DISTRIB_DAY_IS_ONSALE'] == 0) {
  318. return ['code' => self::RETURN_CODE_ROOM_CLOSED, 'info' => self::RETURN_MSG[self::RETURN_CODE_ROOM_CLOSED]];
  319. }
  320. //检查是否关房
  321. if ($item['ROOM_RUN_STATUS'] == 0 || $item['DISTRIB_RUN_STATUS'] == 329) { //ROOM_RUN_STATUS=0 房型关房;DISTRIB_RUN_STATUS=329渠道关房
  322. return ['code' => self::RETURN_CODE_STOCK_FAIL, 'info' => self::RETURN_MSG[self::RETURN_CODE_STOCK_FAIL]];
  323. }
  324. //判断库存
  325. if (($item['BUYOUT'] + $item['RETAIN'] + $item['INQUIRY']) < $this->RoomNum) { //买断+保留库存和现询库存是不能同时消耗的
  326. return ['code' => self::RETURN_CODE_STOCK_FAIL, 'info' => self::RETURN_MSG[self::RETURN_CODE_STOCK_FAIL]];
  327. }
  328. if ($item['REMAINING_COUNT'] < $this->RoomNum && $item['OVERSELL_FLAG'] == 0) { //给渠道的库存不足且不允许超卖
  329. return ['code' => self::RETURN_CODE_STOCK_FAIL, 'info' => self::RETURN_MSG[self::RETURN_CODE_STOCK_FAIL]];
  330. }
  331. //价格校验
  332. if ($this->IfCheckPrice) { //渠道下单是需要校验的,其他:如自己的系统下单,不需要校验价格的
  333. foreach ($this->RoomPrices as $val) {
  334. $newPrice = $item['SALE_TYPE'] == 177 ? $item['PROD_PRICE'] : $item['CUS_PRICE'];//分销选取分销价,其他选择零售价
  335. if ($val['RunDate'] == $item['RUN_DATE']) {
  336. if ($newPrice != $val['Price']) {
  337. return ['code' => self::RETURN_CODE_PRICE_FAIL, 'info' => self::RETURN_MSG[self::RETURN_CODE_PRICE_FAIL]];
  338. }
  339. }
  340. }
  341. }
  342. //订单最终消耗的类型及数量
  343. if ($item['BUYOUT'] >= $this->RoomNum) { //只消耗买断
  344. $stock_arr[$item['RUN_DATE']][CommonOrder::BUYOUT] = ['room_num' => $this->RoomNum, 'product_data' => $item];
  345. } elseif (($item['BUYOUT'] + $item['RETAIN']) >= $this->RoomNum) { //消耗买断和保留
  346. $stock_arr[$item['RUN_DATE']][CommonOrder::BUYOUT] = ['room_num' => $item['BUYOUT'], 'product_data' => $item];
  347. $stock_arr[$item['RUN_DATE']][CommonOrder::REMAIN] = ['room_num' => $this->RoomNum - $item['BUYOUT'], 'product_data' => $item];
  348. } elseif (($item['BUYOUT'] + $item['RETAIN'] + $item['INQUIRY']) >= $this->RoomNum) { //需要消耗买断+保留+现询
  349. $stock_arr[$item['RUN_DATE']][CommonOrder::BUYOUT] = ['room_num' => $item['BUYOUT'], 'product_data' => $item];
  350. $stock_arr[$item['RUN_DATE']][CommonOrder::REMAIN] = ['room_num' => $item['RETAIN'], 'product_data' => $item];
  351. $stock_arr[$item['RUN_DATE']][CommonOrder::INQUIRY] = ['room_num' => $this->RoomNum - $item['BUYOUT'] - $item['RETAIN'], 'product_data' => $item];
  352. } else {
  353. return ['code' => self::RETURN_CODE_STOCK_FAIL, 'info' => self::RETURN_MSG[self::RETURN_CODE_STOCK_FAIL]];
  354. }
  355. }
  356. //创建主订单
  357. $main_order_id = $this->getHotelOrderID();
  358. $order_description = ''; //主订单中的订单描述
  359. $total_base_price = ''; //总成本
  360. $total_commission = ''; //总佣金
  361. $total_profit_value = ''; //总利润
  362. $orderMainParam = [];
  363. $total_price = 0;
  364. $prices = array_column($this->RoomPrices, 'Price');
  365. foreach ($prices as $price) {
  366. $total_price += $price * $this->RoomNum;
  367. }
  368. /*if ((string)$total_price != (string)$this->TotalPrice) {
  369. return ['code' => self::RETURN_CODE_PRICE_FAIL, 'info' => self::RETURN_MSG[self::RETURN_CODE_PRICE_FAIL]];
  370. }*/
  371. //订单总金额
  372. //更新库存
  373. ksort($stock_arr);
  374. foreach ($stock_arr as $run_date => $stock) {
  375. $roomPrice = [];
  376. #region 计算佣金
  377. foreach ($this->RoomPrices as $room_price) {
  378. if (isset($hotelInfo['commission'][BaseSupplier::BACK_COMMISION_METHOD_SALE])) {//按照销售额 按返佣比例计算 取百分比
  379. $commission_rate = $hotelInfo['commission'][BaseSupplier::BACK_COMMISION_METHOD_SALE];
  380. $commission = $room_price['Price'] * ($commission_rate / 100);
  381. } elseif (isset($hotelInfo['commission'][BaseSupplier::BACK_COMMISION_METHOD_SETTLE])) {
  382. $commission_rate = $hotelInfo['commission'][BaseSupplier::BACK_COMMISION_METHOD_SETTLE];
  383. $commission = $commission_rate;
  384. } else {
  385. $commission = 0;
  386. }
  387. $roomPrice[$room_price['RunDate']] = [
  388. 'Price' => $room_price['Price'],
  389. 'Commission' => round($commission, 2)];
  390. }
  391. #endregion
  392. // 消耗库存
  393. $distrib = RunHotelDistrib::findOne([
  394. 'HOTEL_ID' => $this->HotelID,
  395. 'ROOM_TYPE' => $data[0]['ROOM_TYPE'],
  396. 'BASE_ROOM_TYPE' => $data[0]['BASE_ROOM_TYPE'],
  397. 'RUN_DATE' => $run_date,
  398. 'DISTRIB_ID' => $this->DistribID,
  399. ]);
  400. $distrib->SALED_COUNT += $this->RoomNum; //更新已售数量
  401. #region 1、扣渠道的库存
  402. if ($distrib->REMAINING_COUNT < $this->RoomNum) { //说明固定数量的库存小于客人所需的间数,这个时候,还需要消耗超卖的库存
  403. $distrib->REMAINING_COUNT = 0;
  404. $flag = true; //这个订单标记为现询单
  405. } else { //直接扣除固定数量
  406. $distrib->REMAINING_COUNT = ($distrib->REMAINING_COUNT - $this->RoomNum);
  407. }
  408. if (!$distrib->save()) {
  409. $msg = $this->getErrorMsg($distrib);
  410. throw new \Exception($msg);
  411. }
  412. #endregion
  413. $stock_count = 0;
  414. foreach ($stock as $stock_type => $room_num) {
  415. #region 2、扣基础房型的库存
  416. $runHotel = RunHotel::findOne([
  417. 'HOTEL_ID' => $this->HotelID,
  418. 'BASE_ROOM_TYPE' => $data[0]['BASE_ROOM_TYPE'],
  419. 'RUN_DATE' => $run_date,
  420. 'STOCK_TYPE' => $stock_type,
  421. ]);
  422. if (empty($runHotel)) {
  423. continue;
  424. }
  425. $runHotel->SALED_COUNT += $room_num['room_num'];
  426. $runHotel->REMAINING_COUNT -= $room_num['room_num'];
  427. if (!$runHotel->save()) {
  428. $msg = $this->getErrorMsg($runHotel);
  429. throw new \Exception($msg);
  430. }
  431. #endregion
  432. //根据库存类型判断售卖单价
  433. $base_price = $stock_type == 228 ? $room_num['product_data']['BASE_PRICE_BUYOUT'] :
  434. ($stock_type == 230 ? $room_num['product_data']['BASE_PRICE_RESERVE'] :
  435. ($stock_type == 230 ? $room_num['product_data']['BASE_PRICE_INQUIRY'] :
  436. $room_num['product_data']['BASE_PRICE_INQUIRY']));
  437. $total_base_price += $base_price * $room_num['room_num']; //总成本价格
  438. #region 3、创建子订单
  439. for ($i = 1; $i <= $room_num['room_num']; $i++) {
  440. $stock_count++;
  441. $order_id = $this->getHotelOrderID();
  442. //最晚到店时间
  443. if ($this->RunTime != '') {
  444. $timeArr = explode(':', date('H:i', $this->RunTime));
  445. $minutes = $timeArr[0] * 60 + $timeArr[1];
  446. } else {
  447. $minutes = 0;
  448. }
  449. //入住人信息
  450. $order_guests = '';
  451. foreach ($this->OrderGuests as $Guest) {
  452. $order_guests .= $order_guests == '' ? $Guest['Name'] : ',' . $Guest['Name'];
  453. }
  454. $fenxiao_commisssion = empty($this->Commission) ? 0 : $this->Commission / (Utils::diffBetweenTwoDays($this->CheckIn, $this->CheckOut) * $this->RoomNum);
  455. $orderMainParam = [
  456. 'ID' => $order_id,
  457. 'MAIN_CREATE_USER_ID' => $this->CreateUserID,
  458. 'CREATE_USER_ID' => $this->CreateUserID,
  459. 'CREATE_TIME' => date('Y-m-d H:i:s'),
  460. 'UPDATE_USER_ID' => $this->CreateUserID,
  461. 'UPDATE_TIME' => date('Y-m-d H:i:s'),
  462. 'PROD_TOP_ORG_ID' => $hotelInfo['hotel_info']['SUPPLIER_ID'], //酒店供应商ID
  463. 'ORDER_ID' => $order_id,
  464. 'ORDER_VALID_STATUS' => 1,
  465. 'ORDER_BOOK_STATUS' => 0,
  466. 'ORDER_PAY_STATUS' => 1,
  467. 'ORDER_PAY_MAIN_ID' => $main_order_id,
  468. 'ORDER_PAY_USER_ID' => $this->CreateUserID,
  469. 'ORDER_PAY_TIME' => date('Y-m-d H:i:s'),
  470. 'PARENT_ORDER_ID' => $main_order_id, //主订单号码
  471. 'PROD_ID' => $hotelInfo['hotel_info']['ROOM_TYPE'], //子房型ID room_type
  472. 'PARENT_PROD_ID' => $this->HotelID,
  473. 'PROD_NAME' => $hotelInfo['hotel_info']['ROOM_NAME'], //子房型名称
  474. 'PARENT_PROD_NAME' => $hotelInfo['hotel_info']['HOTEL_NAME'], //酒店名称,
  475. 'ORDER_PRICE' => $roomPrice[$run_date]['Price'],
  476. 'ORDER_PROD_TYPE' => OrderMain::ORDER_PROD_TYPE_SUM,
  477. 'PROD_SUPPLY_ORG_NAME' => $hotelInfo['hotel_info']['SUPPLIER_NAME'], //酒店供应商名称
  478. 'BASE_PRICE' => $base_price,
  479. 'MID_PRICE' => $fenxiao_commisssion,
  480. 'RUN_ID' => $this->RoomID,
  481. 'RUN_DATE' => $run_date,
  482. 'RUN_TIME' => $this->RunTime != '' ? date('H:i', $this->RunTime) : '0', //最晚到店
  483. 'RUN_BUS_SEAT_TYPE' => $stock_count <= $item['REMAINING_COUNT'] ? 1 : 2, //酒店:消耗渠道的库存类型:1:固定数量:2:超卖
  484. 'RUN_TIME_MINUTES' => $minutes,
  485. 'PROD_START_STATION_DATE' => $run_date,
  486. 'PROD_START_STATION_TIME_MINUTES' => 0,
  487. 'PROD_START_STATION_AREA_ID' => $hotelInfo['hotel_info']['AREA_ID'],
  488. 'PROD_START_STATION_AREA_NAME' => $hotelInfo['hotel_info']['AREA_NAME'],
  489. 'PROD_END_STATION_DATE' => $this->CheckOut,
  490. 'CUSTOMER_NAME' => $order_guests,
  491. 'CUSTOMER_MOBILE' => $this->ContactTel,
  492. 'CUSTOMER_MEMO' => '',
  493. 'ORDER_STATUS' => OrderMain::ORDER_STATUS_WAITING_SEND,
  494. 'IF_LAST_PROD' => $room_num['product_data']['GIFT_ID'], //是否有礼盒
  495. 'ORDER_LEVEL' => OrderMain::ORDER_LEVEL_SURE,
  496. 'OUTSIDE_ORDER_NO' => $this->OrderID,
  497. 'OUTSIDE_SALE_ORG_ID' => $this->DistribID,
  498. 'ORDER_TITLE_ID' => $this->OrderTitleID,
  499. 'STOCK_TYPE' => $stock_type,
  500. 'REFUSE_FLAG' => $flag === true ? 1 : 0, //$flag为true,说明订单是现询的,可以拒单
  501. 'PROFIT_VALUE' => ($roomPrice[$run_date]['Price'] - $base_price - $roomPrice[$run_date]['Commission'] - $fenxiao_commisssion),
  502. 'TOTAL_COMMISSION' => $roomPrice[$run_date]['Commission'],
  503. 'SALES_MAN' => $hotelInfo['hotel_info']['PURCHASE_NAME'], //采购人
  504. 'PRINCIPAL_ID' => $hotelInfo['hotel_info']['PRINCIPAL'] //运营负责人
  505. ];
  506. $total_commission += $roomPrice[$run_date]['Commission'];
  507. $total_profit_value += ($roomPrice[$run_date]['Price'] - $base_price - $roomPrice[$run_date]['Commission']);
  508. $orderMain = new OrderMain();
  509. if ($orderMain->load($orderMainParam, '') && $orderMain->validate()) {
  510. if (!$orderMain->save()) {
  511. $msg = $this->getErrorMsg($orderMain);
  512. throw new \Exception($msg);
  513. }
  514. } else {
  515. $msg = $this->getErrorMsg($orderMain);
  516. throw new \Exception($msg);
  517. }
  518. }
  519. #endregion
  520. }
  521. //主订单中的订单描述
  522. $description = $hotelInfo['hotel_info']['ROOM_NAME'] . ',' . $run_date . ',' . $this->RoomNum;
  523. $order_description .= $order_description == '' ? $description : '|' . $description;
  524. }
  525. #region 4、创建主订单
  526. $orderMainParam['ID'] = $main_order_id;
  527. $orderMainParam['ORDER_ID'] = $main_order_id;
  528. $orderMainParam['ORDER_DESCRIPTION'] = $order_description;
  529. $orderMainParam['ORDER_PAY_MAIN_ID'] = $main_order_id;
  530. $orderMainParam['PARENT_ORDER_ID'] = 0;
  531. $orderMainParam['ORDER_PRICE'] = $total_price;
  532. $orderMainParam['ORDER_PROD_TYPE'] = OrderMain::ORDER_PROD_TYPE_MAIN;
  533. $orderMainParam['BASE_PRICE'] = $total_base_price;
  534. $orderMainParam['RUN_DATE'] = '';
  535. $orderMainParam['RUN_TIME'] = '';
  536. $orderMainParam['MID_PRICE'] = empty($this->Commission) ? 0 : $this->Commission;
  537. $orderMainParam['RUN_TIME_MINUTES'] = 0;
  538. $orderMainParam['PROD_START_STATION_DATE'] = $this->CheckIn;
  539. $orderMainParam['PROD_END_STATION_DATE'] = $this->CheckOut;
  540. $orderMainParam['STOCK_TYPE'] = 0;
  541. $orderMainParam['ORDER_TITLE_ID'] = $this->OrderTitleID;
  542. $orderMainParam['PROFIT_VALUE'] = $total_profit_value - (empty($this->Commission) ? 0 : $this->Commission);
  543. $orderMainParam['TOTAL_COMMISSION'] = $total_commission;
  544. $main_order = new OrderMain();
  545. if ($main_order->load($orderMainParam, '') && $main_order->validate()) {
  546. if (!$main_order->save()) {
  547. $msg = $this->getErrorMsg($main_order);
  548. throw new \Exception($msg);
  549. }
  550. } else {
  551. $msg = $this->getErrorMsg($main_order);
  552. throw new \Exception($msg);
  553. }
  554. //记录订单的备注信息
  555. if (!empty($this->Comment)) {
  556. if (is_array($this->Comment)) { //这里是为了对应CS系统下单的时候,可以同时保存两个不同类型的备注
  557. foreach ($this->Comment as $comment_k => $comment_v) { //备注类型$comment_k 备注内容 $comment_v
  558. /*if (trim($comment_v['comment']) != '') { //代理通逻辑
  559. $order_comment = new OrderComment();
  560. if (in_array($comment_k, ['orderMemo', 'specialMemo', 'additionalList'])) {
  561. //针对渠道设置的渠道备注标识
  562. $order_comment->SPECIAL_FLAG = $comment_k == 'orderMemo' ? (OrderComment::SPECIAL_FLAG_COMMENT) :
  563. ($comment_k == 'specialMemo' ? (OrderComment::SPECIAL_FLAG_SERVICE) :
  564. OrderComment::SPECIAL_FLAG_EXTRA);
  565. }
  566. $order_comment->ORDER_ID = $main_order_id;
  567. $order_comment->COMMENT_TXT = $comment_v['comment'];
  568. $order_comment->COMMENT_TYPE = $comment_v['comment_type'];
  569. $order_comment->CREATE_USER_ID = $this->CreateUserID;
  570. $order_comment->CREATE_TIME = date('Y-m-d', time());
  571. $order_comment->UPDATE_USER_ID = $this->CreateUserID;
  572. $order_comment->save();
  573. }*/
  574. if(trim($comment_v)!=''){
  575. $order_comment = new OrderComment();
  576. $order_comment->ORDER_ID = $main_order_id;
  577. $order_comment->COMMENT_TXT = $comment_v;
  578. $order_comment->COMMENT_TYPE = $comment_k;
  579. $order_comment->CREATE_USER_ID = $this->CreateUserID;
  580. $order_comment->CREATE_TIME = date('Y-m-d', time());
  581. $order_comment->UPDATE_USER_ID = $this->CreateUserID;
  582. $order_comment->save();
  583. }
  584. }
  585. } else {
  586. $order_comment = new OrderComment();
  587. if ($this->CommentType == 1) { //内部备注
  588. $order_comment->COMMENT_TYPE = OrderComment::TYPE_INTERNAL;
  589. } elseif ($this->CommentType == 2) { //公共备注
  590. $order_comment->COMMENT_TYPE = OrderComment::TYPE_PUBLIC;
  591. } else { //没有设置CommentTypede 情况,像携程等渠道
  592. $order_comment->COMMENT_TYPE = OrderComment::TYPE_INTERNAL;
  593. }
  594. $order_comment->ORDER_ID = $main_order_id;
  595. $order_comment->COMMENT_TXT = $this->Comment;
  596. $order_comment->CREATE_USER_ID = $this->CreateUserID;
  597. $order_comment->CREATE_TIME = date('Y-m-d', time());
  598. $order_comment->UPDATE_USER_ID = $this->CreateUserID;
  599. $order_comment->save();
  600. }
  601. }
  602. #endregion
  603. //更新支付相关
  604. $this->setPayInfo($main_order_id, $total_price);
  605. //记录日志
  606. $msg = $this->OrderTitleID == 0 ? "创建订单号为{$main_order_id}的订单" : "创建订单号为{$main_order_id}的组合订单,组合订单号为{$this->OrderTitleID}";
  607. $this->setOrderLog($main_order_id, $hotelInfo['hotel_info']['PARENT_ROOM_TYPE'], $hotelInfo['hotel_info']['ROOM_TYPE'], $msg);
  608. if ($this->PayType != OrderPayMain::PAY_TYPE_CASH && $this->PayType != OrderPayMain::PAY_TYPE_CREDIT) {
  609. $pay_type = $this->PayType == OrderPayMain::PAY_TYPE_ALIPAY ? '支付宝支付' : ($this->PayType == OrderPayMain::PAY_TYPE_WEIXIN ? '微信支付' : '支付');
  610. $msg = "支付订单,{$pay_type}流水号:{$this->PayTradeNo}";
  611. $this->setOrderLog($main_order_id, $hotelInfo['hotel_info']['PARENT_ROOM_TYPE'], $hotelInfo['hotel_info']['ROOM_TYPE'], $msg);
  612. }
  613. $statusLog = new OrderHtStatusLog();
  614. $statusLog->CREATE_USER_ID = $this->CreateUserID;
  615. $statusLog->UPDATE_USER_ID = $this->CreateUserID;
  616. $statusLog->ORDER_STATUS = OrderMain::ORDER_STATUS_WAITING_SEND;
  617. $statusLog->ORDER_ID = $main_order_id;
  618. $statusLog->save();
  619. //如果有发票信息,需要记录发票
  620. if ($this->NeedInvoice) {
  621. $this->InvoiceInfos->InvoiceMoney = "$total_price";
  622. $this->InvoiceInfos->CreateUseId = $this->CreateUserID;
  623. $this->InvoiceInfos->Status = 1;
  624. $this->InvoiceInfos->ChannelId = $this->DistribID;
  625. $this->InvoiceInfos->OrderID = $main_order_id;
  626. $this->InvoiceInfos->save();
  627. }
  628. $transaction->commit();
  629. //这里处理共享库存逻辑
  630. //Notes:库存共享导致的部分渠道的库存大于基础房型的买断+保留
  631. // 解决方案:将其他库存大于基础房型买断+保留的渠道库存设置为买断+保留
  632. $main_order->UpdateStockByShare(['hotel_id' => $this->HotelID, 'check_in' => $this->CheckIn, 'check_out' => $this->CheckOut, 'distrib_id' => $this->DistribID, 'room_id' => $this->RoomID]);
  633. $soap_param = array('hotel_id' => $this->HotelID, 'parent_room_type' => $hotelInfo['hotel_info']['PARENT_ROOM_TYPE'], 'room_type' => $hotelInfo['hotel_info']['ROOM_TYPE'],
  634. 'begin_date' => $this->CheckIn, 'end_date' => $this->CheckOut, 'channel_id' => $this->DistribID);
  635. // 异步扣除预付款
  636. zHttp::syncRequest(self::SEND_REQUEST_GET, Yii::$app->params['prepay_interface'], array('type' => self::MAKE_ORDER_DEDUCTION_TYPE, 'order_id' => $main_order_id));
  637. // 异步推送房态接口
  638. zHttp::syncRequest(self::SEND_REQUEST_GET, Yii::$app->params['push_info_interface'], array('param' => $soap_param));
  639. } catch (\Exception $e) {
  640. $error = $e->getMessage();
  641. $transaction->rollBack();
  642. return ['code' => self::RETURN_CODE_PROGRAM_FAIL, 'info' => self::RETURN_MSG[self::RETURN_CODE_PROGRAM_FAIL]];
  643. }
  644. } else {
  645. return ['code' => self::RETURN_CODE_PROGRAM_FAIL, 'info' => self::RETURN_MSG[self::RETURN_CODE_PROGRAM_FAIL]];
  646. }
  647. return ['code' => self::RETURN_CODE_SUCCESS, 'info' => self::RETURN_CODE_SUCCESS, 'data' => ['order_id' => $main_order_id]];
  648. }
  649. /**
  650. * Notes:取消订单
  651. * User: Steven
  652. * Date: 2018/1/26
  653. * Time: 13:58
  654. * @return array|int
  655. * @throws Exception
  656. * @throws \Exception
  657. */
  658. public function cancelHotelOrder()
  659. {
  660. //这里查询到的是主订单
  661. $order_main = OrderMain::findOne([
  662. 'OUTSIDE_ORDER_NO' => "{$this->OrderID}",
  663. 'ORDER_PROD_TYPE' => OrderMain::ORDER_PROD_TYPE_MAIN,
  664. 'PARENT_ORDER_ID' => 0,
  665. 'OUTSIDE_SALE_ORG_ID' => $this->DistribID,
  666. 'order_main.CANCEL_FLAG' => 0,
  667. ]);
  668. if (empty($order_main)) { //订单不存在
  669. return self::RETURN_CODE_NOT_EXIST;
  670. }
  671. $this->setOrderLog($order_main->ORDER_ID, $this->RoomID, $order_main->PROD_ID, "渠道商申请取消订单:" . $order_main->ORDER_ID . ',原因:' . (empty($this->Reason) ? '无' : $this->Reason));
  672. if ($order_main->CHANNEL_ORDER_STATUS == OrderMain::ORDER_CHANNEL_STATUS_APPLY_CANCEL_CONFIRMED) { //渠道接单状态是已取消 ,依然返回同意取消
  673. $this->setOrderLog($order_main->ORDER_ID, $this->RoomID, $order_main->PROD_ID, '渠道状态已经变更为已取消,二次取消,同意取消' . "[{$order_main->CHANNEL_ORDER_STATUS}]/[{$order_main->ORDER_STATUS}]");
  674. return self::RETURN_CODE_SUCCESS;
  675. }
  676. $white_list = OrderHtExceptionList::find()->where(['order_id' => $order_main->ORDER_ID])->one();
  677. if ($white_list != null) { //加入白名单的直接同意取消即可
  678. if ($white_list->status == OrderHtExceptionList::AGREE_CANCEL) { //同意取消
  679. $channel_status = OrderMain::ORDER_CHANNEL_STATUS_APPLY_CANCEL_CONFIRMED;
  680. } else { //拒绝取消
  681. $channel_status = OrderMain::ORDER_CHANNEL_STATUS_APPLY_CANCEL_REJECT;
  682. }
  683. //变更渠道的订单状态为已取消,但是不取消订单,即不回退库存,发人工退改申请
  684. $count = OrderMain::updateAll(['CHANNEL_ORDER_STATUS' => $channel_status, 'UPDATE_TIME' => date('Y-m-d H:i:s', time())],
  685. ['ORDER_PROD_TYPE' => [25, 26], 'CANCEL_FLAG' => 0, 'OUTSIDE_ORDER_NO' => $this->OrderID, 'DOCKING_TYPE' => OrderMain::ORDER_TYPE_CHANNEL]);
  686. if ($count == 0) {
  687. throw new \Exception();
  688. }
  689. if ($channel_status == OrderMain::ORDER_CHANNEL_STATUS_APPLY_CANCEL_CONFIRMED) {
  690. $this->setOrderLog($order_main->ORDER_ID, $this->RoomID, $order_main->PROD_ID, '该订单已加入白名单,白名单类型:同意取消,同意渠道取消。' . "[{$order_main->CHANNEL_ORDER_STATUS}]/[{$order_main->ORDER_STATUS}]");
  691. return self::RETURN_CODE_SUCCESS;
  692. } else {
  693. $this->setOrderLog($order_main->ORDER_ID, $this->RoomID, $order_main->PROD_ID, '该订单已加入白名单,白名单类型:拒绝取消,拒绝渠道取消。' . "[{$order_main->CHANNEL_ORDER_STATUS}]/[{$order_main->ORDER_STATUS}]");
  694. return self::RETURN_CODE_NOT_ALLOW_CANCEL;
  695. }
  696. }
  697. //白名单的订单不需要在这里直接取消订单,先同意渠道取消订单,然后人工发退改申请
  698. if ($order_main->CHANNEL_ORDER_STATUS != OrderMain::ORDER_CHANNEL_STATUS_WAITING ||
  699. !in_array($order_main->ORDER_STATUS, [OrderMain::ORDER_STATUS_NO_PAID, OrderMain::ORDER_STATUS_WAITING_SEND])) { //该情况不能退单
  700. $this->setOrderLog($order_main->ORDER_ID, $this->RoomID, $order_main->PROD_ID, "拒绝渠道商取消订单:" . $order_main->ORDER_ID);
  701. return self::RETURN_CODE_NOT_ALLOW_CANCEL;
  702. }
  703. $transaction = Yii::$app->db->beginTransaction();
  704. try {
  705. if ($order_main->ORDER_STATUS == OrderMain::ORDER_STATUS_WAITING_SEND) { //待发单 需要直接取消订单
  706. $order_main->ORDER_STATUS = OrderMain::ORDER_STATUS_CANCEL;
  707. $order_main->ORDER_VALID_STATUS = 0;
  708. $cancel = $order_main->rollbackStocks();
  709. if (!$cancel) {
  710. throw new \Exception();
  711. }
  712. }
  713. $count = OrderMain::updateAll(['CHANNEL_ORDER_STATUS' => OrderMain::ORDER_CHANNEL_STATUS_APPLY_CANCEL_CONFIRMED, 'ORDER_VALID_STATUS' => $order_main->ORDER_VALID_STATUS,
  714. 'ORDER_STATUS' => $order_main->ORDER_STATUS, 'UPDATE_TIME' => date('Y-m-d H:i:s', time())],
  715. ['ORDER_PROD_TYPE' => [25, 26], 'CANCEL_FLAG' => 0, 'OUTSIDE_ORDER_NO' => $this->OrderID, 'DOCKING_TYPE' => OrderMain::ORDER_TYPE_CHANNEL]);
  716. if ($count == 0) {
  717. throw new \Exception();
  718. }
  719. $this->setOrderLog($order_main->ORDER_ID, $this->RoomID, $order_main->PROD_ID, "同意渠道商取消订单:" . $order_main->ORDER_ID);
  720. $orderComment = new OrderComment();
  721. $orderComment->ORDER_ID = $order_main->ORDER_ID;
  722. $orderComment->COMMENT_TYPE = OrderComment::TYPE_CANCEL_NOTE;
  723. $orderComment->COMMENT_TXT = $this->Reason;
  724. $orderComment->CREATE_USER_ID = $this->CreateUserID;
  725. $orderComment->UPDATE_USER_ID = $this->CreateUserID;
  726. $orderComment->save();
  727. $transaction->commit();
  728. return self::RETURN_CODE_SUCCESS;
  729. } catch (Exception $exception) {
  730. $transaction->rollBack();
  731. $this->setOrderLog($order_main->ORDER_ID, $this->RoomID, $order_main->PROD_ID, "订单取消失败:" . $exception->getMessage() . $order_main->ORDER_ID);
  732. return self::RETURN_CODE_CANCEL_FAIL;
  733. }
  734. }
  735. /**
  736. * Notes:修改订单
  737. * User: Steven
  738. * Date: 2018/1/4
  739. * Time: 19:05
  740. * @return array
  741. * @throws Exception
  742. */
  743. public function updateHotelOrder()
  744. {
  745. // 修改订单之前保留预定单的信息,用于渠道预付款处理
  746. //这里查询到的是主订单
  747. $order_main = OrderMain::findOne([
  748. 'ORDER_ID' => $this->ZZ_ORDER_ID,
  749. 'ORDER_PROD_TYPE' => OrderMain::ORDER_PROD_TYPE_MAIN,
  750. 'PARENT_ORDER_ID' => 0,
  751. 'order_main.CANCEL_FLAG' => 0,
  752. 'CANCEL_FLAG' => 0,
  753. ]);
  754. $child_order = OrderMain::findAll([
  755. 'CANCEL_FLAG' => 0,
  756. 'PARENT_ORDER_ID' => $this->ZZ_ORDER_ID,
  757. 'ORDER_PROD_TYPE' => self::ORDER_PROD_TYPE_SUM,
  758. ]);
  759. $order_level = in_array($order_main['ORDER_STATUS'], array(198, 382)) ? OrderMain::ORDER_LEVEL_CHANGE : OrderMain::ORDER_LEVEL_SURE;
  760. $supplier = BaseSupplier::find()->select(['ID', 'SUPPLIER_NAME'])->andFilterWhere([
  761. 'IN', 'ID', [$order_main->OUTSIDE_SALE_ORG_ID, $this->DistribID],
  762. ])->indexBy('ID')->asArray()->all();
  763. $old_log_desc = '';
  764. $old_supplier_name = $supplier[$order_main->OUTSIDE_SALE_ORG_ID]['SUPPLIER_NAME'] . "({$order_main->OUTSIDE_ORDER_NO}): ";
  765. $new_log_desc = '';
  766. $new_supplier_name = $supplier[$this->DistribID]['SUPPLIER_NAME'] . "({$this->OrderID}): ";
  767. foreach ($child_order as $c_o) {
  768. $old_log_desc .= '【' . $c_o->RUN_DATE . '/' . $c_o->BASE_PRICE . '(采)/' . $c_o->ORDER_PRICE . '(销)' . '】;';
  769. }
  770. $old_log_desc = $old_supplier_name . '<br>' . $old_log_desc;
  771. $transaction = Yii::$app->db->beginTransaction();
  772. try {
  773. //回退库存
  774. $resRollback = $order_main->rollbackStocks();
  775. if (!$resRollback) {
  776. throw new Exception('修改失败');
  777. }
  778. //下单并修改主订单和子订单
  779. $child_order_count = OrderMain::updateAll([
  780. 'CANCEL_FLAG' => 1,
  781. 'UPDATE_USER_ID' => $this->CREATE_USER_ID,
  782. 'UPDATE_TIME' => date('Y-m-d H:i:s', time()),
  783. ],
  784. [
  785. 'CANCEL_FLAG' => 0,
  786. 'PARENT_ORDER_ID' => $this->ZZ_ORDER_ID,
  787. 'ORDER_PROD_TYPE' => self::ORDER_PROD_TYPE_SUM,
  788. ]);
  789. if ($child_order_count <= 0) {
  790. throw new Exception('修改失败');
  791. }
  792. $flag = false; //标识是否设置订单为现询的(包括保留房和非保留房混合的情况,全是现询房)
  793. $data = $this->getProductData();
  794. $hotelInfo = $this->getHotelInfo();
  795. if ($data) {
  796. $stock_arr = []; //订单最终消耗的类型及数量
  797. foreach ($data as $item) {
  798. //检查渠道是否授权
  799. if (!$item['AUTHORITY_STATUS']) {
  800. return ['code' => 2, 'info' => '不可订,渠道未授权'];
  801. }
  802. //检查产品是否上线
  803. if ($item['ROOM_IS_ONSALE'] == 0 || $item['ROOM_DAY_IS_ONSALE'] == 0 || $item['DISTRIB_DAY_IS_ONSALE'] == 0) {
  804. return ['code' => 3, 'info' => '不可订,产品已下线'];
  805. }
  806. //检查是否关房
  807. if ($item['ROOM_RUN_STATUS'] == 0 || $item['DISTRIB_RUN_STATUS'] == 329) { //ROOM_RUN_STATUS=0 房型关房;DISTRIB_RUN_STATUS=329渠道关房
  808. $desc = $item['ROOM_RUN_STATUS'] == 0 ? '满房' : '关房';
  809. return ['code' => 4, 'info' => '不可订,该日期下房型已' . $desc];
  810. }
  811. //判断库存
  812. if (($item['BUYOUT'] + $item['RETAIN'] + $item['INQUIRY']) < $this->RoomNum) { //买断+保留库存和现询库存是不能同时消耗的
  813. return ['code' => 5, 'info' => '不可订,基础房型库存不足!'];
  814. }
  815. if ($item['REMAINING_COUNT'] < $this->RoomNum && $item['OVERSELL_FLAG'] == 0) { //给渠道的库存不足且不允许超卖
  816. return ['code' => 6, 'info' => '不可订,渠道房型库存不足!'];
  817. }
  818. //价格校验
  819. if ($this->IfCheckPrice) { //渠道下单是需要校验的,其他:如自己的系统下单,不需要校验价格的
  820. foreach ($this->RoomPrices as $val) {
  821. $newPrice = $item['SALE_TYPE'] == 177 ? $item['PROD_PRICE'] : $item['CUS_PRICE'];//分销选取分销价,其他选择零售价
  822. if ($val['RUN_DATE'] == $item['RUN_DATE']) {
  823. if ($newPrice != $val['PRICE']) {
  824. return ['code' => 6, 'info' => '不可订,价格已更新,请刷新后重试!'];
  825. }
  826. }
  827. }
  828. }
  829. //订单最终消耗的类型及数量
  830. if ($item['BUYOUT'] >= $this->RoomNum) { //只消耗买断
  831. $stock_arr[$item['RUN_DATE']][CommonOrder::BUYOUT] = ['room_num' => $this->RoomNum, 'product_data' => $item];
  832. } elseif (($item['BUYOUT'] + $item['RETAIN']) >= $this->RoomNum) { //消耗买断和保留
  833. $stock_arr[$item['RUN_DATE']][CommonOrder::BUYOUT] = ['room_num' => $item['BUYOUT'], 'product_data' => $item];
  834. $stock_arr[$item['RUN_DATE']][CommonOrder::REMAIN] = ['room_num' => $this->RoomNum - $item['BUYOUT'], 'product_data' => $item];
  835. } elseif (($item['BUYOUT'] + $item['RETAIN'] + $item['INQUIRY']) >= $this->RoomNum) { //需要消耗买断+保留+现询
  836. $stock_arr[$item['RUN_DATE']][CommonOrder::BUYOUT] = ['room_num' => $item['BUYOUT'], 'product_data' => $item];
  837. $stock_arr[$item['RUN_DATE']][CommonOrder::REMAIN] = ['room_num' => $item['RETAIN'], 'product_data' => $item];
  838. $stock_arr[$item['RUN_DATE']][CommonOrder::INQUIRY] = ['room_num' => $this->RoomNum - $item['BUYOUT'] - $item['RETAIN'], 'product_data' => $item];
  839. } else {
  840. return ['code' => 5, 'info' => '不可订,基础房型库存不足!'];
  841. }
  842. }
  843. //创建订单
  844. $order_description = ''; //主订单中的订单描述
  845. $gift_flag = false; //标识是否有礼盒 只有某一天有礼盒,那么该订单都属于有礼盒
  846. $total_base_price = ''; //总成本
  847. $total_commission = ''; //总佣金
  848. $total_profit_value = ''; //总利润
  849. $total_price = 0;
  850. $prices = array_column($this->RoomPrices, 'Price');
  851. foreach ($prices as $price) {
  852. $total_price += $price * $this->RoomNum;
  853. }
  854. if ($total_price != $this->TotalPrice) {
  855. throw new \Exception('传入的价格信息不符,总金额和间夜金额不符!');
  856. }
  857. //更新库存
  858. foreach ($stock_arr as $run_date => $stock) {
  859. $roomPrice = [];
  860. #region 计算佣金
  861. foreach ($this->RoomPrices as $room_price) {
  862. if (isset($hotelInfo['commission'][BaseSupplier::BACK_COMMISION_METHOD_SALE])) {//按照销售额 按返佣比例计算 取百分比
  863. $commission_rate = $hotelInfo['commission'][BaseSupplier::BACK_COMMISION_METHOD_SALE];
  864. $commission = $room_price['Price'] * ($commission_rate / 100);
  865. } elseif (isset($hotelInfo['commission'][BaseSupplier::BACK_COMMISION_METHOD_SETTLE])) {
  866. $commission_rate = $hotelInfo['commission'][BaseSupplier::BACK_COMMISION_METHOD_SETTLE];
  867. $commission = $commission_rate;
  868. } else {
  869. $commission = 0;
  870. }
  871. $roomPrice[$room_price['RunDate']] = [
  872. 'Price' => $room_price['Price'],
  873. 'Commission' => round($commission, 2)];
  874. }
  875. #endregion
  876. // 消耗库存
  877. $distrib = RunHotelDistrib::findOne([
  878. 'HOTEL_ID' => $this->HotelID,
  879. 'ROOM_TYPE' => $data[0]['ROOM_TYPE'],
  880. 'BASE_ROOM_TYPE' => $data[0]['BASE_ROOM_TYPE'],
  881. 'RUN_DATE' => $run_date,
  882. 'DISTRIB_ID' => $this->DistribID,
  883. ]);
  884. $distrib->SALED_COUNT += $this->RoomNum; //更新已售数量
  885. #region 1、扣渠道的库存
  886. if ($item['REMAINING_COUNT'] < $this->RoomNum) { //说明固定数量的库存小于客人所需的间数,这个时候,还需要消耗超卖的库存
  887. $distrib->REMAINING_COUNT = 0;
  888. $flag = true; //这个订单标记为现询单
  889. } else { //直接扣除固定数量
  890. $distrib->REMAINING_COUNT = ($item['REMAINING_COUNT'] - $this->RoomNum);
  891. }
  892. if (!$distrib->save()) {
  893. $msg = $this->getErrorMsg($distrib);
  894. throw new \Exception($msg);
  895. }
  896. #endregion
  897. $stock_count = 0;
  898. foreach ($stock as $stock_type => $room_num) {
  899. if ($room_num['product_data']['GIFT_ID'] > 0) {
  900. $gift_flag = true;
  901. }
  902. #region 2、扣基础房型的库存
  903. $runHotel = RunHotel::findOne([
  904. 'HOTEL_ID' => $this->HotelID,
  905. 'BASE_ROOM_TYPE' => $data[0]['BASE_ROOM_TYPE'],
  906. 'RUN_DATE' => $run_date,
  907. 'STOCK_TYPE' => $stock_type,
  908. ]);
  909. if (empty($runHotel)) {
  910. continue;
  911. }
  912. $runHotel->SALED_COUNT += $room_num['room_num'];
  913. $runHotel->REMAINING_COUNT -= $room_num['room_num'];
  914. if (!$runHotel->save()) {
  915. $msg = $this->getErrorMsg($runHotel);
  916. throw new \Exception($msg);
  917. }
  918. #endregion
  919. //根据库存类型判断售卖单价
  920. $base_price = $stock_type == 228 ? $room_num['product_data']['BASE_PRICE_BUYOUT'] :
  921. ($stock_type == 230 ? $room_num['product_data']['BASE_PRICE_RESERVE'] :
  922. ($stock_type == 230 ? $room_num['product_data']['BASE_PRICE_INQUIRY'] :
  923. $room_num['product_data']['BASE_PRICE_INQUIRY']));
  924. $total_base_price += $base_price * $room_num['room_num']; //总成本价格
  925. #region 3、创建子订单
  926. for ($i = 1; $i <= $room_num['room_num']; $i++) {
  927. $stock_count++;
  928. $order_id = $this->getHotelOrderID();
  929. //最晚到店时间
  930. if ($this->RunTime != '') {
  931. $timeArr = explode(':', date('H:i', $this->RunTime));
  932. $minutes = $timeArr[0] * 60 + $timeArr[1];
  933. } else {
  934. $minutes = 0;
  935. }
  936. //入住人信息
  937. $order_guests = '';
  938. foreach ($this->OrderGuests as $Guest) {
  939. $order_guests .= $order_guests == '' ? $Guest['Name'] : ',' . $Guest['Name'];
  940. }
  941. $orderMainParam = [
  942. 'ID' => $order_id,
  943. 'MAIN_CREATE_USER_ID' => $this->CreateUserID,
  944. 'CREATE_USER_ID' => $this->CreateUserID, //将子订单的创建时间
  945. 'CREATE_TIME' => $order_main->CREATE_TIME,
  946. 'UPDATE_USER_ID' => $this->CreateUserID,
  947. 'UPDATE_TIME' => date('Y-m-d H:i:s'),
  948. 'PROD_TOP_ORG_ID' => $hotelInfo['hotel_info']['SUPPLIER_ID'], //酒店供应商ID
  949. 'ORDER_ID' => $order_id,
  950. 'ORDER_VALID_STATUS' => 1,
  951. 'ORDER_BOOK_STATUS' => 0,
  952. 'ORDER_PAY_STATUS' => 1,
  953. 'ORDER_PAY_MAIN_ID' => $order_main->ORDER_ID,
  954. 'ORDER_PAY_USER_ID' => $this->CreateUserID,
  955. 'ORDER_PAY_TIME' => date('Y-m-d H:i:s'),
  956. 'PARENT_ORDER_ID' => $order_main->ORDER_ID, //主订单号码
  957. 'PROD_ID' => $hotelInfo['hotel_info']['ROOM_TYPE'], //子房型ID room_type
  958. 'PARENT_PROD_ID' => $this->HotelID,
  959. 'PROD_NAME' => $hotelInfo['hotel_info']['ROOM_NAME'], //子房型名称
  960. 'PARENT_PROD_NAME' => $hotelInfo['hotel_info']['HOTEL_NAME'], //酒店名称,
  961. 'ORDER_PRICE' => $roomPrice[$run_date]['Price'],
  962. 'ORDER_PROD_TYPE' => OrderMain::ORDER_PROD_TYPE_SUM,
  963. 'PROD_SUPPLY_ORG_NAME' => $hotelInfo['hotel_info']['SUPPLIER_NAME'], //酒店供应商名称
  964. 'BASE_PRICE' => $base_price,
  965. 'RUN_ID' => $this->RoomID,
  966. 'RUN_DATE' => $run_date,
  967. 'RUN_TIME' => $this->RunTime != '' ? date('H:i', $this->RunTime) : '0', //最晚到店
  968. 'RUN_BUS_SEAT_TYPE' => $stock_count <= $item['REMAINING_COUNT'] ? 1 : 2, //酒店:消耗渠道的库存类型:1:固定数量:2:超卖
  969. 'RUN_TIME_MINUTES' => $minutes,
  970. 'PROD_START_STATION_DATE' => $run_date,
  971. 'PROD_START_STATION_TIME_MINUTES' => 0,
  972. 'PROD_START_STATION_AREA_ID' => $hotelInfo['hotel_info']['AREA_ID'],
  973. 'PROD_START_STATION_AREA_NAME' => $hotelInfo['hotel_info']['AREA_NAME'],
  974. 'PROD_END_STATION_DATE' => $this->CheckOut,
  975. 'CUSTOMER_NAME' => $order_guests,
  976. 'CUSTOMER_MOBILE' => $this->ContactTel,
  977. 'CUSTOMER_MEMO' => '',
  978. 'ORDER_STATUS' => OrderMain::ORDER_STATUS_WAITING_CONFIRM,
  979. 'IF_LAST_PROD' => $room_num['product_data']['GIFT_ID'], //是否有礼盒
  980. 'ORDER_LEVEL' => $order_level,
  981. 'OUTSIDE_ORDER_NO' => $this->OrderID,
  982. 'OUTSIDE_SALE_ORG_ID' => $this->DistribID,
  983. 'STOCK_TYPE' => $stock_type,
  984. 'REFUSE_FLAG' => $flag === true ? 1 : 0, //$flag为true,说明订单是现询的,可以拒单
  985. 'PROFIT_VALUE' => ($roomPrice[$run_date]['Price'] - $base_price - $roomPrice[$run_date]['Commission']),
  986. 'TOTAL_COMMISSION' => $roomPrice[$run_date]['Commission'],
  987. 'SALES_MAN' => $hotelInfo['hotel_info']['PURCHASE_NAME'], //采购人
  988. 'PRINCIPAL_ID' => $hotelInfo['hotel_info']['PRINCIPAL'] //运营负责人
  989. ];
  990. $total_commission += $roomPrice[$run_date]['Commission'];
  991. $total_profit_value += ($roomPrice[$run_date]['Price'] - $base_price - $roomPrice[$run_date]['Commission']);
  992. $orderMain = new OrderMain();
  993. if ($orderMain->load($orderMainParam, '') && $orderMain->validate()) {
  994. if (!$orderMain->save()) {
  995. $msg = $this->getErrorMsg($orderMain);
  996. throw new \Exception($msg);
  997. }
  998. } else {
  999. $msg = $this->getErrorMsg($orderMain);
  1000. throw new \Exception($msg);
  1001. }
  1002. $new_log_desc .= '【' . $run_date . '/' . $base_price . '(采)/' . $roomPrice[$run_date]['Price'] . '(销)' . '】;';
  1003. }
  1004. #endregion
  1005. }
  1006. //主订单中的订单描述
  1007. $description = $hotelInfo['hotel_info']['ROOM_NAME'] . ',' . $run_date . ',' . $this->RoomNum;
  1008. $order_description .= $order_description == '' ? $description : '|' . $description;
  1009. }
  1010. #region 4、更新主订单
  1011. $order_main->UPDATE_TIME = date('Y-m-d H:i:s');
  1012. $order_main->ORDER_DESCRIPTION = $order_description;
  1013. $order_main->PROD_TOP_ORG_ID = $hotelInfo['hotel_info']['SUPPLIER_ID'];
  1014. $order_main->OUTSIDE_ORDER_NO = "{$this->OrderID}";
  1015. $order_main->PROD_ID = $hotelInfo['hotel_info']['ROOM_TYPE'];
  1016. $order_main->PROD_NAME = $hotelInfo['hotel_info']['ROOM_NAME'];
  1017. $order_main->ORDER_PRICE = $total_price;
  1018. $order_main->BASE_PRICE = $total_base_price;
  1019. $order_main->PROD_START_STATION_DATE = $this->CheckIn;
  1020. $order_main->PROD_END_STATION_DATE = $this->CheckOut;
  1021. $order_main->CUSTOMER_NAME = $order_guests;
  1022. $order_main->CUSTOMER_MOBILE = $this->ContactTel;
  1023. $order_main->PROFIT_VALUE = $total_profit_value;
  1024. $order_main->TOTAL_COMMISSION = $total_commission;
  1025. $order_main->IF_LAST_PROD = $gift_flag === true ? 1 : 0;
  1026. $order_main->OUTSIDE_SALE_ORG_ID = $this->DistribID;
  1027. $order_main->ORDER_LEVEL = $order_level;
  1028. if (!$order_main->save()) {
  1029. $msg = $this->getErrorMsg($order_main);
  1030. throw new \Exception($msg);
  1031. }
  1032. //记录日志
  1033. $old_log_desc = "修改订单:由{$old_log_desc}";
  1034. $this->setOrderLog($order_main->ORDER_ID, $hotelInfo['hotel_info']['PARENT_ROOM_TYPE'], $hotelInfo['hotel_info']['ROOM_TYPE'], $old_log_desc);
  1035. $new_log_desc = $new_supplier_name . '<br>' . $new_log_desc;
  1036. $new_log_desc = "修改为:{$new_log_desc}";
  1037. $this->setOrderLog($order_main->ORDER_ID, $hotelInfo['hotel_info']['PARENT_ROOM_TYPE'], $hotelInfo['hotel_info']['ROOM_TYPE'], $new_log_desc);
  1038. } else {
  1039. return ['code' => 2, 'info' => '数据获取失败'];
  1040. }
  1041. //修改订单备注信息
  1042. //2018年5月15日:这里的修改备注信息目前只适用于代理通直连(CS修改订单备注有单独的接口,阿里不能修改订单)
  1043. //并且,携程的订单备注不管有几条都会拼接成一条传过来
  1044. /*if (!empty($this->Comment)) {
  1045. $comment_model = OrderComment::findOne(['ORDER_ID' => $this->ZZ_ORDER_ID, 'CANCEL_FLAG' => 0, 'SPECIAL_FLAG' => OrderComment::SPECIAL_FLAG_COMMENT, 'CREATE_USER_ID' => Yii::$app->params['ctrip']['base_user_id']]);
  1046. $comment_model->UPDATE_TIME = date('Y-m-d H:i:s');
  1047. $comment_model->COMMENT_TXT = $this->Comment;
  1048. $comment_model->SPECIAL_FLAG = OrderComment::SPECIAL_FLAG_COMMENT;
  1049. $comment_model->save();
  1050. }*/
  1051. $transaction->commit();
  1052. // 下单渠道供应商预付款处理及房态推送处理
  1053. $soap_param = array('hotel_id' => $this->HotelID, 'parent_room_type' => $hotelInfo['hotel_info']['PARENT_ROOM_TYPE'], 'room_type' => $hotelInfo['hotel_info']['ROOM_TYPE'],
  1054. 'begin_date' => $this->CheckIn, 'end_date' => $this->CheckOut, 'channel_id' => $this->DistribID);
  1055. zHttp::syncRequest(self::SEND_REQUEST_GET, Yii::$app->params['prepay_interface'], array('type' => CommonOrder::UPDATE_ORDER_DEDUCTION_TYPE, 'order_id' => $order_main->ORDER_ID));
  1056. zHttp::syncRequest(self::SEND_REQUEST_GET, Yii::$app->params['push_info_interface'], array('param' => $soap_param));
  1057. return ['code' => 0, 'info' => '修改成功'];
  1058. } catch (\Exception $e) {
  1059. $error = $e->getMessage();
  1060. $transaction->rollBack();
  1061. $arr = array(
  1062. "agentid" => 1000002,
  1063. "title" => '修改订单失败',
  1064. "msg" => "关联订单号:" . $order_main->ORDER_ID . "\n错误信息:" . $error,
  1065. "touser" => 'wanglg');
  1066. zOfficeWechat::sendMsg($arr);
  1067. return ['code' => 1, 'info' => $error];
  1068. }
  1069. }
  1070. /**
  1071. * Notes:订单的操作日志
  1072. * User: Steven
  1073. * Date: 2018/1/3
  1074. * Time: 13:16
  1075. * @param $order_id
  1076. * @param $parent_room_type
  1077. * @param $room_type
  1078. * @param $msg
  1079. * @return bool
  1080. */
  1081. public function setOrderLog($order_id, $parent_room_type, $room_type, $msg, $user_id = "", $hotel_id = "")
  1082. {
  1083. $orderLog = new OperaHotelLog();
  1084. $orderLog->CREATE_USER_ID = empty($user_id) ? $this->CreateUserID : $user_id;
  1085. $orderLog->HOTEL_ID = empty($this->HotelID) ? $hotel_id : $this->HotelID;
  1086. $orderLog->LOG_TYPE = OperaHotelLog::LOG_TYPE_ORDER;
  1087. $orderLog->ROOM_TYPE = $room_type;
  1088. $orderLog->PARENT_ROOM_TYPE = $parent_room_type;
  1089. $orderLog->LOG_DESC = $msg;
  1090. $orderLog->ORDER_ID = $order_id;
  1091. $orderLog->save();
  1092. return true;
  1093. }
  1094. /**
  1095. * Notes: 下单设置支付相关的信息
  1096. * User: Steven
  1097. * Date: 2018/1/2
  1098. * Time: 12:10
  1099. * @param $order_id
  1100. * @param $total_price
  1101. * @return bool
  1102. */
  1103. public function setPayInfo($order_id, $total_price)
  1104. {
  1105. $payMain = new OrderPayMain();
  1106. $payMain->ID = $order_id;
  1107. $payMain->CREATE_USER_ID = $this->CreateUserID;
  1108. $payMain->UPDATE_USER_ID = $this->CreateUserID;
  1109. $payMain->PAY_TOTAL = $total_price;
  1110. $payMain->ORDER_ID = $order_id;
  1111. $payMain->save();
  1112. $payDetail = new OrderPayDetail();
  1113. $payDetail->ID = $order_id;
  1114. $payDetail->PAY_MAIN_ID = $payMain->ID;
  1115. $payDetail->CREATE_USER_ID = $this->CreateUserID;
  1116. $payDetail->UPDATE_USER_ID = $this->CreateUserID;
  1117. $payDetail->PAY_TYPE_ID_1 = $this->PayType;
  1118. $payDetail->PAY_MONEY = $total_price;
  1119. $payDetail->PAY_SERIAL_NUMBER = $this->PayTradeNo == '' ? '0' : "{$this->PayTradeNo}";
  1120. //ORDER_PAY_STATUS 订单是否已支付,0未支付,1已支付
  1121. //ORDER_PAY_MAIN_ID 支付记录主ID,ORDER_PAY_MAIN.ID
  1122. //ORDER_PAY_USER_ID 支付操作用户ID,BASE_USER.ID
  1123. //ORDER_PAY_TIME 支付操作时间
  1124. $payDetail->save();
  1125. return true;
  1126. }
  1127. public function updateRoomQuantity()
  1128. {
  1129. }
  1130. /**
  1131. * Author:Steven
  1132. * Desc:获取可定订检查的数据
  1133. * @return array|\yii\db\ActiveRecord[]
  1134. */
  1135. public function getProductData()
  1136. {
  1137. $end_date = date('Y-m-d', strtotime($this->CheckOut . '-1 day'));
  1138. $query = RunHotelDistrib::find()
  1139. ->select(['a.DISTRIB_ID', 'a.HOTEL_ID', 'a.BASE_ROOM_TYPE', 'b.ROOM_TYPE', 'a.RUN_DATE', 'a.REMAINING_COUNT',
  1140. 'a.PROD_PRICE', 'a.CUS_PRICE', 'a.RUN_STATUS as DISTRIB_RUN_STATUS', 'a.OVERSELL_FLAG', 'c.STOCK_TYPE',
  1141. 'c.IS_ONSALE as ROOM_DAY_IS_ONSALE', 'b.IS_ONSALE as ROOM_IS_ONSALE', 'd.IS_ONSALE as DISTRIB_DAY_IS_ONSALE',
  1142. 'd.RUN_STATUS as ROOM_RUN_STATUS', 'e.AUTHORITY_STATUS', 'a.GIFT_ID', 'f.SALE_TYPE', 'd.BASE_PRICE_BUYOUT', 'd.BASE_PRICE_RESERVE', 'd.BASE_PRICE_INQUIRY',
  1143. 'SUM(case c.stock_type when 228 then c.remaining_count else 0 end) as BUYOUT', //买断
  1144. 'SUM(case c.stock_type when 229 then c.remaining_count else 0 end) as INQUIRY', //现询
  1145. 'SUM(case c.stock_type when 230 then c.remaining_count else 0 end) as RETAIN'//保留
  1146. ])
  1147. ->joinWith('operaHotelRoom b', false)
  1148. ->joinWith(['runHotel c'], false)
  1149. ->joinWith(['runHotelSubRoom d'], false)
  1150. ->leftJoin('opera_room_distrib e', 'e.ROOM_ID=b.ID and e.DISTRIB_ID=a.DISTRIB_ID')
  1151. ->leftJoin('base_supplier_sale f', 'a.DISTRIB_ID=f.SUPPLIER_ID and f.CANCEL_FLAG=0 and PARENT_TYPE=25')
  1152. ->from('run_hotel_distrib a')
  1153. ->where([
  1154. 'a.HOTEL_ID' => $this->HotelID,
  1155. 'b.ID' => $this->RoomID,
  1156. 'a.DISTRIB_ID' => $this->DistribID,
  1157. ]);
  1158. $query->andFilterWhere(['between', 'a.RUN_DATE', $this->CheckIn, $end_date])->groupBy('a.ID');
  1159. $sql = $query->createCommand()->getRawSql();
  1160. $data = $query->asArray()->all();
  1161. return $data;
  1162. }
  1163. /**
  1164. * @Author wanglg
  1165. * @Desc获取库存信息
  1166. * @return array
  1167. */
  1168. public function getHotelStock()
  1169. {
  1170. // 获取查询结果集中的最小值
  1171. $end_date = date('Y-m-d', strtotime($this->CheckOut . '-1 day'));
  1172. $query = RunHotelDistrib::find()
  1173. ->select(['a.OVERSELL_FLAG', 'a.REMAINING_COUNT', 'a.PROD_PRICE', 'a.CUS_PRICE', 'a.RUN_DATE', 'a.REMAINING_COUNT DISTRIB_REMAINING_COUNT', 'b.ID', 'b.HOTEL_ID',
  1174. 'b.PARENT_ROOM_TYPE', 'b.ROOM_TYPE', 'c.REMAINING_COUNT as BASE_REMAINING_COUNT', 'a.DISTRIB_ID', 'd.BASE_PRICE_BUYOUT', 'd.BASE_PRICE_INQUIRY', 'd.BASE_PRICE_RESERVE',
  1175. 'f.SALE_TYPE', 'f.COMMISION_FLAG', 'f.COMMISION_TYPE', 'f.BACK_COMMISION_TYPE', 'f.BACK_COMMISION_METHOD', 'f.BACK_PERCENT', 'f.BACK_VALUE',
  1176. 'SUM(case c.stock_type when 228 then c.remaining_count else 0 end) as BUYOUT', // 买断
  1177. 'SUM(case c.stock_type when 229 then c.remaining_count else 0 end) as INQUIRY', // 现询
  1178. 'SUM(case c.stock_type when 230 then c.remaining_count else 0 end) as RETAIN' // 保留
  1179. ])
  1180. ->leftJoin('opera_hotel_room b', 'a.HOTEL_ID=b.HOTEL_ID AND a.ROOM_TYPE=b.ROOM_TYPE AND b.PARENT_ROOM_TYPE=a.BASE_ROOM_TYPE')
  1181. ->leftJoin('run_hotel c', 'b.HOTEL_ID=c.HOTEL_ID AND b.PARENT_ROOM_TYPE=c.BASE_ROOM_TYPE AND a.RUN_DATE=c.RUN_DATE')
  1182. ->leftJoin('run_hotel_sub_room d', 'b.HOTEL_ID=d.HOTEL_ID and b.ROOM_TYPE=d.ROOM_TYPE and b.PARENT_ROOM_TYPE=d.BASE_ROOM_TYPE AND d.RUN_DATE=a.RUN_DATE')
  1183. ->leftJoin('base_supplier_sale f', 'a.DISTRIB_ID=f.SUPPLIER_ID and f.CANCEL_FLAG=0 and f.PARENT_TYPE=25')
  1184. ->from('run_hotel_distrib a')
  1185. ->where(['b.ID' => $this->RoomID, 'a.DISTRIB_ID' => $this->DistribID, 'd.IS_ONSALE' => 1, 'b.IS_ONSALE' => 1, 'a.RUN_STATUS' => RunHotelDistrib::ROOM_STATUS_SALE,
  1186. 'd.RUN_STATUS' => 1, 'c.IS_ONSALE' => 1, 'b.CANCEL_FLAG' => 0]);
  1187. $query->andFilterWhere(['between', 'a.RUN_DATE', $this->CheckIn, $end_date]);
  1188. $availStock = $query->groupBy(['a.RUN_DATE', 'b.ID'])->orderBy(['a.RUN_DATE' => SORT_ASC])->createCommand()
  1189. ->queryAll();
  1190. return $availStock;
  1191. }
  1192. /**
  1193. * @Author wanglg
  1194. * @Desc 获取房型日期段内最少的库存数
  1195. * @return mixed
  1196. */
  1197. public function getMinStock()
  1198. {
  1199. $availStock = $this->getHotelStock();
  1200. $arr = [];
  1201. foreach ($availStock as $item) {
  1202. $arr[] = $item['OVERSELL_FLAG'] == 1 ? $item['BUYOUT'] + $item['INQUIRY'] + $item['RETAIN'] : $item['REMAINING_COUNT'];
  1203. }
  1204. $minStock = empty($arr) ? 0 : min($arr);
  1205. return $minStock;
  1206. }
  1207. public function dealStock($order_id, $request)
  1208. {
  1209. $this->load($request, '');
  1210. $availStock = $this->getChannelStock($order_id);
  1211. $arr = [];
  1212. foreach ($availStock as $item) {
  1213. $arr[] = $item['OVERSELL_FLAG'] == 1 ? $item['BUYOUT'] + $item['INQUIRY'] + $item['RETAIN'] : $item['REMAINING_COUNT'];
  1214. }
  1215. $minStock = empty($arr) ? 0 : min($arr);
  1216. return $minStock;
  1217. }
  1218. /**
  1219. * @Author wanglg
  1220. * @Desc 获取房型日期段内最少的库存数
  1221. * @return mixed
  1222. */
  1223. public function getChannelStock($order_id)
  1224. {
  1225. $order_main = OrderMain::find()
  1226. ->select(['ORDER_ID', 'RUN_BUS_SEAT_TYPE', 'OUTSIDE_SALE_ORG_ID', 'RUN_DATE', 'STOCK_TYPE', 'LATEST_COMFIRM_TIME', 'PARENT_PROD_ID', 'PARENT_ROOM_TYPE'])
  1227. ->joinWith('operaHotelRoom', false)
  1228. ->leftJoin('opera_room_distrib b', 'opera_hotel_room.ID=b.ROOM_ID AND b.DISTRIB_ID=order_main.OUTSIDE_SALE_ORG_ID')
  1229. ->where(['PARENT_ORDER_ID' => $order_id, 'order_main.CANCEL_FLAG' => 0, 'ORDER_PROD_TYPE' => 26, 'ORDER_VALID_STATUS' => 1, 'ORDER_LEVEL' => [0, 1]])
  1230. ->from('order_main')
  1231. ->asArray()->all();
  1232. $availStock = $this->getHotelStock();
  1233. // 如果渠道相同,库存需要+原订单房间数
  1234. foreach ($order_main as $value) {
  1235. foreach ($availStock as $key => $stock) {
  1236. // 保留房超过最晚立即确认时间库存不回退,即库存等于现有库存+订单消耗库存
  1237. if ($value['RUN_BUS_SEAT_TYPE'] == self::DISTRIB_STOCK_TYPE_RESERVE) { // 保留房库存
  1238. if (!empty($value['LATEST_COMFIRM_TIME']) && $value['LATEST_COMFIRM_TIME'] != -1) { //保留房设置了最晚预定时间
  1239. $time = explode(',', $value['LATEST_COMFIRM_TIME']);
  1240. $date = date('Y-m-d', strtotime($value['RUN_DATE'] . "{$time[0]} days"));
  1241. $last_confirm_time = $date . ' ' . $time[1];
  1242. if ($time >= strtotime($last_confirm_time)) { // 超过了最晚预定时间,保留房库存不回退,现询及买断照常回退
  1243. if ($value['STOCK_TYPE'] != self::STOCK_TYPE_RESERVE) {
  1244. if ($value['STOCK_TYPE'] == self::STOCK_TYPE_BUYOUT && $value['RUN_DATE'] == $stock['RUN_DATE']) {
  1245. $availStock[$key]['BUYOUT'] += 1;
  1246. } elseif ($value['STOCK_TYPE'] == self::STOCK_TYPE_INQUIRY && $value['RUN_DATE'] == $stock['RUN_DATE']) {
  1247. $availStock[$key]['INQUIRY'] += 1;
  1248. }
  1249. }
  1250. } else { // 未设置保留房确认时间,保留房坤村照常回退
  1251. if ($value['STOCK_TYPE'] == self::STOCK_TYPE_BUYOUT && $value['RUN_DATE'] == $stock['RUN_DATE']) {
  1252. $availStock[$key]['BUYOUT'] += 1;
  1253. } elseif ($value['STOCK_TYPE'] == self::STOCK_TYPE_INQUIRY && $value['RUN_DATE'] == $stock['RUN_DATE']) {
  1254. $availStock[$key]['INQUIRY'] += 1;
  1255. } elseif ($value['STOCK_TYPE'] == self::STOCK_TYPE_RESERVE && $value['RUN_DATE'] == $stock['RUN_DATE']) {
  1256. $availStock[$key]['RETAIN'] += 1;
  1257. }
  1258. }
  1259. } else {
  1260. if ($value['STOCK_TYPE'] == self::STOCK_TYPE_BUYOUT && $value['RUN_DATE'] == $stock['RUN_DATE']) {
  1261. $availStock[$key]['BUYOUT'] += 1;
  1262. } elseif ($value['STOCK_TYPE'] == self::STOCK_TYPE_INQUIRY && $value['RUN_DATE'] == $stock['RUN_DATE']) {
  1263. $availStock[$key]['INQUIRY'] += 1;
  1264. } elseif ($value['STOCK_TYPE'] == self::STOCK_TYPE_RESERVE && $value['RUN_DATE'] == $stock['RUN_DATE']) {
  1265. $availStock[$key]['RETAIN'] += 1;
  1266. }
  1267. }
  1268. } else {
  1269. if ($value['STOCK_TYPE'] == self::STOCK_TYPE_BUYOUT && $value['RUN_DATE'] == $stock['RUN_DATE']) {
  1270. $availStock[$key]['BUYOUT'] += 1;
  1271. } elseif ($value['STOCK_TYPE'] == self::STOCK_TYPE_INQUIRY && $value['RUN_DATE'] == $stock['RUN_DATE']) {
  1272. $availStock[$key]['INQUIRY'] += 1;
  1273. } elseif ($value['STOCK_TYPE'] == self::STOCK_TYPE_RESERVE && $value['RUN_DATE'] == $stock['RUN_DATE']) {
  1274. $availStock[$key]['RETAIN'] += 1;
  1275. }
  1276. }
  1277. }
  1278. }
  1279. return $availStock;
  1280. }
  1281. /**
  1282. * Notes:获取酒店的信息以及渠道的信息
  1283. * User: Steven
  1284. * Date: 2017/12/29
  1285. * Time: 14:07
  1286. * @return array
  1287. */
  1288. public function getHotelInfo()
  1289. {
  1290. $hotel_info = OperaHotelRoom::find()->select([
  1291. 'a.PARENT_ROOM_TYPE', 'a.ROOM_TYPE', 'a.ROOM_NAME', 'b.SUPPLIER_ID', 'b.HOTEL_NAME', 'd.SUPPLIER_NAME', 'b.PRINCIPAL', 'b.PURCHASE_NAME', 'b.AREA_ID', 'c.AREA_NAME'])
  1292. ->leftJoin('opera_hotel b', 'a.HOTEL_ID=b.HOTEL_ID and b.CANCEL_FLAG=0')
  1293. ->leftJoin('base_area c', 'b.AREA_ID=c.ID and c.CANCEL_FLAG=0')
  1294. ->leftJoin('base_supplier d', 'b.SUPPLIER_ID=d.ID and d.CANCEL_FLAG=0')
  1295. ->from('opera_hotel_room a')
  1296. ->where(['a.ID' => $this->RoomID])->asArray()->one();
  1297. $supplier = BaseSupplier::find()->select([
  1298. 'a.SUPPLIER_NAME', 'b.SALE_TYPE', 'b.COMMISION_FLAG', 'b.COMMISION_TYPE', 'b.BACK_COMMISION_TYPE',
  1299. 'b.BACK_COMMISION_METHOD', 'b.BACK_PERCENT', 'b.BACK_VALUE'])
  1300. ->leftJoin('base_supplier_sale b', "b.SUPPLIER_ID=a.ID and b.PARENT_TYPE=25 and b.CANCEL_FLAG=0")
  1301. ->from('base_supplier a')->where(['a.ID' => $this->DistribID])->asArray()->one();
  1302. if ($supplier['COMMISION_FLAG'] == 1 && $supplier['COMMISION_TYPE'] == BaseSupplier::COMMISION_TYPE_CHANNEL
  1303. && $supplier['BACK_COMMISION_TYPE'] == BaseSupplier::BACK_COMMISION_TYPE_FIXED) {
  1304. if ($supplier['BACK_COMMISION_METHOD'] == BaseSupplier::BACK_COMMISION_METHOD_SALE) { //按照销售额 按返佣比例计算 取百分比
  1305. $commission[BaseSupplier::BACK_COMMISION_METHOD_SALE] = $supplier['BACK_PERCENT'];
  1306. } elseif ($supplier['BACK_COMMISION_METHOD'] == BaseSupplier::BACK_COMMISION_METHOD_SETTLE) { //按结算金额 按返佣固定金额 取固定金额
  1307. $commission[BaseSupplier::BACK_COMMISION_METHOD_SETTLE] = $supplier['BACK_VALUE'];
  1308. } else {
  1309. $commission[BaseSupplier::BACK_COMMISION_METHOD_SETTLE] = 0;
  1310. }
  1311. } else {
  1312. $commission[BaseSupplier::BACK_COMMISION_METHOD_SETTLE] = 0;
  1313. }
  1314. return ['hotel_info' => $hotel_info, 'commission' => $commission];
  1315. }
  1316. /**
  1317. * Notes:获取酒店订单号
  1318. * User: Steven
  1319. * Date: 2017/12/28
  1320. * Time: 18:01
  1321. * @return mixed
  1322. * @throws \yii\db\Exception
  1323. */
  1324. public function getHotelOrderID()
  1325. {
  1326. $conn = Yii::$app->db;
  1327. $get_unique_id = "select func_get_unique_id(1,1) as unique_id"; //得到新的出车任务ID
  1328. $data_id = $conn->createCommand($get_unique_id)->queryAll();
  1329. return $data_id[0]['unique_id'];
  1330. }
  1331. /**
  1332. * @Author wanglg
  1333. * @Desc 渠道预付款处理逻辑
  1334. * @param $type
  1335. * @param $order_id
  1336. * @param int $base_price
  1337. * @param int $order_price
  1338. * @param int $channel_id
  1339. * @return array
  1340. */
  1341. public function previousBalance($type, $order_id)
  1342. {
  1343. $model = new BaseBalance($order_id, '', '');
  1344. // 预付款处理之前判断是结算方式是否是预付,如果不是预付则不进行预付款处理
  1345. $supplier_info = OrderMain::find()
  1346. ->select(['a.SETT_TYPE as cType', 'b.SETT_TYPE as sType'])
  1347. ->joinWith('baseChannel a')
  1348. ->joinWith('baseSupplier b')
  1349. ->where(['ORDER_ID' => $order_id, 'order_main.CANCEL_FLAG' => 0, 'ORDER_PROD_TYPE' => OrderMain::ORDER_PROD_TYPE_MAIN, 'PARENT_ORDER_ID' => 0])
  1350. ->asArray()->one();
  1351. if (!isset($supplier_info)) {
  1352. return array('code' => self::RETURN_CODE_OTHER, 'msg' => '未找到订单相关信息');
  1353. }
  1354. if ($type == self::MAKE_ORDER_DEDUCTION_TYPE) {
  1355. $model->memo = '下单扣款';
  1356. $model->pay_type = BaseBalance::STATUS_REDUCE;
  1357. // 添加供应商与渠道商扣款记录,如果供应商预付则添加记录
  1358. if ($supplier_info['sType'] == 288) {
  1359. $supplier_insert = $model->insertBalanceMain();
  1360. if ($supplier_insert['code'] != self::RETURN_CODE_SUCCESS) {
  1361. return array('code' => self::RETURN_CODE_MAKE_ORDER, 'msg' => '下单供应商预付款处理失败');
  1362. }
  1363. }
  1364. // 渠道预付则添加记录
  1365. if ($supplier_info['cType'] == 288) {
  1366. $channel_insert = $model->insertChannelBalanceMain();
  1367. if ($channel_insert['code'] != self::RETURN_CODE_SUCCESS) {
  1368. return array('code' => self::RETURN_CODE_MAKE_ORDER, 'msg' => '下单渠道商预付款处理失败');
  1369. }
  1370. }
  1371. } elseif ($type == self::CANCEL_ORDER_DEDUCTION_TYPE) {
  1372. $model->memo = '订单取消,金额回退';
  1373. $model->pay_type = BaseBalance::STATUS_ADD;
  1374. if ($supplier_info['sType'] == 288) {
  1375. $supplier_cancel = $model->cancelBalanceMain();
  1376. if ($supplier_cancel['code'] != self::RETURN_CODE_SUCCESS) {
  1377. return array('code' => self::RETURN_CODE_CANCEL_ORDER, 'msg' => '取消单供应商预付款处理失败');
  1378. }
  1379. }
  1380. // 渠道预付则添加记录
  1381. if ($supplier_info['cType'] == 288) {
  1382. $channel_cancel = $model->cancelChannelBalanceMain();
  1383. if ($channel_cancel['code'] != self::RETURN_CODE_SUCCESS) {
  1384. return array('code' => self::RETURN_CODE_CANCEL_ORDER, 'msg' => '取消单渠道预付款处理失败');
  1385. }
  1386. }
  1387. } elseif ($type == self::UPDATE_ORDER_DEDUCTION_TYPE) {
  1388. // 供应商扣款方式
  1389. if ($supplier_info['sType'] == 288) {
  1390. $model->memo = '订单修改,金额回退';
  1391. $model->pay_type = BaseBalance::STATUS_ADD;
  1392. $supplier_cancel = $model->cancelBalanceMain();
  1393. $model->memo = '订单修改,重新扣款';
  1394. $model->pay_type = BaseBalance::STATUS_REDUCE;
  1395. // 供应商修改添加新纪录
  1396. $supplier_insert = $model->insertBalanceMain();
  1397. if (($supplier_cancel['code'] != self::RETURN_CODE_SUCCESS && $supplier_cancel['code'] == 3) || $supplier_insert['code'] != self::RETURN_CODE_SUCCESS) {
  1398. return array('code' => self::RETURN_CODE_UPDATE_ORDER, 'msg' => '修改单供应商预付款处理失败');
  1399. }
  1400. }
  1401. // 渠道扣款方式
  1402. if ($supplier_info['cType'] == 288) {
  1403. $model->memo = '订单修改,金额回退';
  1404. $model->pay_type = BaseBalance::STATUS_ADD;
  1405. // 渠道商已扣款取消、回退处理
  1406. $channel_cancel = $model->cancelChannelBalanceMain();
  1407. $model->memo = '订单修改,重新扣款';
  1408. $model->pay_type = BaseBalance::STATUS_REDUCE;
  1409. $channel_insert = $model->insertChannelBalanceMain();
  1410. if (($channel_cancel['code'] != self::RETURN_CODE_SUCCESS && $channel_cancel['code'] == 3) || $channel_insert['code'] != self::RETURN_CODE_SUCCESS) {
  1411. return array('code' => self::RETURN_CODE_UPDATE_ORDER, 'msg' => '修改单渠道预付款处理失败!');
  1412. }
  1413. }
  1414. } else {
  1415. return array('code' => self::ERROR_DEDUCTION_TYPE, 'msg' => self::RETURN_MSG[self::ERROR_DEDUCTION_TYPE]);
  1416. }
  1417. return array('code' => self::RETURN_CODE_SUCCESS, 'msg' => self::RETURN_MSG[self::RETURN_CODE_SUCCESS]);
  1418. }
  1419. /**
  1420. * @Author wanglg
  1421. * @Desc携程阿里直连统一推送接口
  1422. * @param $type标识推送的渠道
  1423. * @param array $param推送数据
  1424. */
  1425. public function pushRoomStatus(array $param = [])
  1426. {
  1427. /*$param = [
  1428. 'hotel_id' => '197',
  1429. 'parent_room_type' => '150246',
  1430. 'room_type' => '9',
  1431. 'begin_date' => '2017-10-30',
  1432. 'end_date' => '2017-11-11',
  1433. 'channel_id' => 669,
  1434. ];*/
  1435. if ($param['channel_id'] == Yii::$app->params['ctrip']['supplier_id']) {
  1436. // 判断房型是否是携程直连有效,无效不推送
  1437. $connection_info = $this->hotelConnect($param);
  1438. if (empty($connection_info['ChannelHotelId']) || empty($connection_info['ChannelRoomId'])) {
  1439. return array('code' => 2, 'msg' => '酒店房型未直连,酒店信息:' . $param['hotel_id'] . ',基础房型信息:' . $param['parent_room_type'] . ',子房型信息' . $param['room_type']);
  1440. }
  1441. $status_data = ['hotel_id' => $param['hotel_id'], 'parent_room_type' => $param['parent_room_type'], 'room_type' => $param['room_type'],
  1442. 'StartDate' => $param['begin_date'], 'EndDate' => $param['end_date']];
  1443. Yii::$app->runAction('hotel/ctrip/set-room-info', ['param' => $status_data]);
  1444. Yii::$app->runAction('hotel/ctrip/set-room-price', ['param' => $status_data]);
  1445. Yii::$app->runAction('hotel/ctrip/update-room-quantity', ['param' => $status_data]);
  1446. }
  1447. if ($param['channel_id'] == Yii::$app->params['ali']['supplier_id']) {
  1448. // 判断房型是否是阿里直连有效,无效不推送房态
  1449. $connection_info = $this->hotelConnect($param);
  1450. if (empty($connection_info['ChannelHotelId']) || empty($connection_info['ChannelRoomId']) || empty($connection_info['RP_ID'])) {
  1451. return array('code' => 2, 'msg' => '酒店房型未直连,酒店信息:' . $param['hotel_id'] . ',基础房型信息:' . $param['parent_room_type'] . ',子房型信息' . $param['room_type']);
  1452. }
  1453. unset($param['channel_id']);
  1454. $data[] = $param;
  1455. $room_info['room_info'] = json_encode($data);
  1456. Yii::$app->runAction('/hotel/ali/rates-update', ['param' => $room_info]);
  1457. }
  1458. }
  1459. /**
  1460. * Notes:
  1461. * User: Steven
  1462. * Date: 2018/1/22
  1463. * Time: 15:49
  1464. * @param $supplier
  1465. * @return mixed
  1466. */
  1467. public static function calCommision($supplier)
  1468. {
  1469. if ($supplier['COMMISION_FLAG'] == 1 && $supplier['COMMISION_TYPE'] == BaseSupplier::COMMISION_TYPE_CHANNEL
  1470. && $supplier['BACK_COMMISION_TYPE'] == BaseSupplier::BACK_COMMISION_TYPE_FIXED) {
  1471. if ($supplier['BACK_COMMISION_METHOD'] == BaseSupplier::BACK_COMMISION_METHOD_SALE) { //按照销售额 按返佣比例计算 取百分比
  1472. $commission[BaseSupplier::BACK_COMMISION_METHOD_SALE] = $supplier['BACK_PERCENT'];
  1473. } elseif ($supplier['BACK_COMMISION_METHOD'] == BaseSupplier::BACK_COMMISION_METHOD_SETTLE) { //按结算金额 按返佣固定金额 取固定金额
  1474. $commission[BaseSupplier::BACK_COMMISION_METHOD_SETTLE] = $supplier['BACK_VALUE'];
  1475. } else {
  1476. $commission[BaseSupplier::BACK_COMMISION_METHOD_SETTLE] = 0;
  1477. }
  1478. } else {
  1479. $commission[BaseSupplier::BACK_COMMISION_METHOD_SETTLE] = 0;
  1480. }
  1481. return $commission;
  1482. }
  1483. /**
  1484. * @Author wanglg
  1485. * @Desc 渠道直连信息查询
  1486. * @param $param数组信息:酒店id、基础房型id、子房型type、渠道id
  1487. * @return array|null|\yii\db\ActiveRecord
  1488. */
  1489. public function hotelConnect($param)
  1490. {
  1491. $select = [];
  1492. $where = '';
  1493. // 如果是阿里
  1494. if ($param['channel_id'] == Yii::$app->params['ali']['supplier_id']) {
  1495. $select = ['b.ChannelHotelId', 'c.ChannelRoomId', 'a.RP_ID'];
  1496. $where = 'a.PARENT_ROOM_TYPE';
  1497. } elseif ($param['channel_id'] == Yii::$app->params['ctrip']['supplier_id']) { // 携程
  1498. $select = ['b.ChannelHotelId', 'c.ChannelRoomId'];
  1499. $where = 'a.ID';
  1500. }
  1501. $connect_info = OperaHotelRoom::find()
  1502. ->select($select)
  1503. ->leftJoin('channel_hotel_relation b', 'a.HOTEL_ID=b.HotelId and b.ChannelId=' . $param['channel_id'])
  1504. ->leftJoin('channel_room_relation c', $where . '=c.RoomId AND c.ChannelId=' . $param['channel_id'])
  1505. ->from('opera_hotel_room a')
  1506. ->where(['a.CANCEL_FLAG' => 0, 'a.HOTEL_ID' => $param['hotel_id'], 'a.PARENT_ROOM_TYPE' => $param['parent_room_type'], 'a.ROOM_TYPE' => $param['room_type']])
  1507. ->asArray()->one();
  1508. return $connect_info;
  1509. }
  1510. }
  1511. ?>