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.

GetTouristStock.php 43 KiB

3 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834
  1. <?php
  2. /**
  3. *
  4. * ============================================================================
  5. * * 版权所有 蜘蛛出行 * *
  6. * 网站地址: http://www.zhizhuchuxing.com
  7. * ----------------------------------------------------------------------------
  8. * 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和
  9. * 使用;不允许对程序代码以任何形式任何目的的再发布。
  10. * ============================================================================
  11. * Author By: 温依莅
  12. * PhpStorm GetTouristStock.php 组合产品成本,库存操作类
  13. * Create By 2017/6/28 9:44 $
  14. */
  15. namespace backend\modules\api\logic;
  16. use backend\modules\api\models\OperaProductRun;
  17. use backend\modules\api\models\OperaTouristCommon;
  18. use common\models\CheckData;
  19. use backend\modules\api\logic\GetStockData;
  20. use common\models\OperaTouristRun;
  21. use common\util\HotelUtil;
  22. use yii\db\Query;
  23. use yii\base\Exception;
  24. use yii\db\Expression;
  25. use Yii;
  26. /**
  27. * 组合产品成本库存操作
  28. */
  29. class GetTouristStock extends Query
  30. {
  31. /**
  32. * Function Description:获取格式化的组合产品库存成本
  33. * Function Name: getTouristStock
  34. * @param int $tourist_id
  35. * @param string $run_date 出发日期
  36. * @param int $org_id 组合产品售卖渠道id
  37. * @param int $org_id 渠道id
  38. * @param int $user_id 用户id
  39. * @param int $main_corp_id 运营主体id
  40. * @return array
  41. *
  42. * @author 温依莅
  43. */
  44. public function getFormatTouristStock($tourist_id, $run_date, $org_id, $user_id, $main_corp_id = -1)
  45. {
  46. $res = $this->getTouristStock($tourist_id, $run_date, $org_id, $user_id, $main_corp_id = -1);
  47. $result = array();
  48. $result['code'] = '0';
  49. $result['info'] = '获取成功';
  50. //在此组合产品存在子资源不可用的情况时,这里不返回具体错误信息,而是返回各库存为0
  51. if ($res['code'] != '0') {
  52. $final_stock_arr = array(
  53. 'tourist_id' => $tourist_id,
  54. 'limit_total_num' => 0, //渠道限制销售总库存
  55. 'limit_adult_num' => 0, //渠道限制销售成人总库存
  56. 'max_total_num' => 0, //总体剩余库存
  57. 'max_adult_num' => 0, //总体成人剩余库存
  58. 'adult_cost' => 0, //成人成本
  59. 'child_cost' => 0, //儿童成本
  60. 'diff_cost' => 0 //单人差成本
  61. );
  62. $result['list'] = $final_stock_arr;
  63. } else {
  64. $result['list'] = $res['list'];
  65. }
  66. //若成功,则返回实际库存成本数据
  67. return $result;
  68. }
  69. /**
  70. * Function Description:获取自由行产品实际需要支付金额
  71. * Function Name: getTouristPayTotal
  72. * @param int $tourist_id 自由行产品id
  73. * @param string $run_date 出发时间
  74. * @param int $org_id 自由行产品渠道id
  75. * @param array $prod_arr 成人儿童订票信息
  76. * @param int $user_id 用户id
  77. *
  78. * @return array
  79. *
  80. * @author 温依莅
  81. */
  82. public function getTouristPayTotal($tourist_id, $run_date, $org_id = 164, $user_id = 2, $prod_arr)
  83. {
  84. $result = array();
  85. //1,处理参数 (微信所传格式为TR-10001;成人票:TR-1001-1,儿童票:TR-1001-2)
  86. #1.1 处理tourist_id
  87. $res = $this->getTouristPara($tourist_id);
  88. $tourist_id = $res['real_id'];
  89. #1.2处理prod_arr :[['prod_id'=>'TR-1000-1','prod_name'=>'成人票','prod_num'=>'4'],['prod_id'=>'TR-1000-2','prod_name'=>'儿童票','prod_num'=>'3']]
  90. if (!$prod_arr) {
  91. $result['code'] = '1';
  92. $result['info'] = '无票种信息';
  93. return $result;
  94. }
  95. $adult_num = 0;
  96. $child_num = 0;
  97. foreach ($prod_arr as $k => $v) {
  98. if (!isset($v['prod_id']) || !isset($v['prod_num'])) {
  99. $result['code'] = '1';
  100. $result['info'] = '票种信息错误';
  101. return $result;
  102. }
  103. $res = $this->getTouristPara($v['prod_id']);
  104. if ($res['list'][2] == 1) {
  105. $adult_num += $v['prod_num'];
  106. } else {
  107. $child_num += $v['prod_num'];
  108. }
  109. }
  110. if ($adult_num == 0 && $child_num == 0) {
  111. $result['code'] = '1';
  112. $result['info'] = '订票数量不可为0';
  113. return $result;
  114. }
  115. //2,判断该组合产品是否整体可售(opera_tourist_common 表的is_onsale字段 和是否在可售时间限制内)
  116. #2.1主产品是否可售
  117. $res = $this->getTouristIsOnSale($tourist_id);
  118. if ($res['code'] != '0') {
  119. $result['code'] = '1';
  120. $result['info'] = '所选产品不可售';
  121. return $result;
  122. }
  123. #2.2是否在可售时间范围内
  124. $res = OperaTouristCommon::judgeTouristTimeAllow($tourist_id, $run_date);
  125. if (!$res) {
  126. $result['code'] = '1';
  127. $result['info'] = '不在允许售卖日期内';
  128. return $result;
  129. }
  130. //3,调用库存接口判断获取自由行库存数据
  131. $res = $this->getTouristStock($tourist_id, $run_date, $org_id, $user_id);
  132. if ($res['code'] != '0') {
  133. $result['code'] = '1';
  134. $result['info'] = '所选产品无库存';
  135. return $result;
  136. }
  137. //4,判断是自由行产品库存是否满足
  138. $limit_total_num = $res['list']['limit_total_num'];//渠道限定总人数
  139. $limit_adult_num = $res['list']['limit_adult_num'];//渠道限定成人人数
  140. if (($limit_total_num < $adult_num + $child_num) || ($limit_adult_num < $adult_num)) {
  141. $result['code'] = '1';
  142. $result['info'] = '该选择库存不足';
  143. return $result;
  144. }
  145. //5,根据巴士酒店门票各自的库存成本信息,结合自由行产品的销售规则
  146. $stock_list = $res['list']['extra_info'];
  147. #5.1 根据成人,儿童人数获取 自由行产品实际总成本
  148. $bus_total_cost = 0;
  149. $hotel_total_cost = 0;
  150. $ticket_total_cost_adult = 0;
  151. $ticket_total_cost_child = 0;
  152. foreach ($stock_list as $sk => $sv) {
  153. if ($sk == 'bus_extra_info' && !empty($sv)) { //巴士
  154. $bus_total_cost = ($adult_num + $child_num) * $sv['list']['adult_cost'];
  155. //$tourist_total_cost = ($adult_num + $child_num) * $sv['list']['adult_cost'];
  156. } else if ($sk == 'hotel_extra_info' && !empty($sv)) { //酒店
  157. #-【酒店】获取酒店住店人数
  158. $hotel_people_num = $adult_num;
  159. if ($sv['crowd_type'] == '11') {
  160. $hotel_people_num = $adult_num + $child_num;
  161. }
  162. #-【酒店】循环根据酒店入住人数和单房间最大人数获取实际房间数,和相应成本
  163. $hotel_list = $sv['list'];
  164. if (!empty($hotel_list)) {
  165. foreach ($hotel_list as $hk => $hv) {
  166. foreach ($hv as $dk => $dv) {
  167. $add_para = $dv['cost'] * ceil($hotel_people_num / $dv['room_max_people']);
  168. //$tourist_total_cost += $add_para;
  169. $hotel_total_cost += $add_para;
  170. }
  171. }
  172. }
  173. } else if ($sk == 'ticket_extra_info' && isset($sv['crowd_type'])) { //门票
  174. $ticket_total_cost_adult += $adult_num * $sv['list']['adult_cost'];
  175. //$tourist_total_cost += $adult_num * $sv['list']['adult_cost'];
  176. if ($sv['crowd_type'] != '10') {
  177. $ticket_total_cost_child += $child_num * $sv['list']['child_cost'];
  178. //$tourist_total_cost += $child_num * $sv['list']['child_cost'];
  179. }
  180. }
  181. }
  182. #5.2 根据自由行产品在该日的加价方式获取最终售价
  183. $opera_tourist_run=new OperaTouristRun();
  184. $sale_res=$opera_tourist_run->getTouristAddInfo($tourist_id, $run_date, $org_id);
  185. if ($sale_res['code'] != '0') {
  186. $result['code'] = '1';
  187. $result['info'] = '所选产品该日期已下架';
  188. return $result;
  189. }
  190. $tourist_total_cost_adult = round($bus_total_cost*($adult_num/($adult_num+$child_num)),2) + round(0.5*$hotel_total_cost,2) + $ticket_total_cost_adult;
  191. $tourist_total_cost_child = ($bus_total_cost-round($bus_total_cost*($adult_num/($adult_num+$child_num)),2)) + ($hotel_total_cost-round(0.5*$hotel_total_cost,2)) + $ticket_total_cost_child;
  192. $final_total_money = 0;
  193. $sale_type_adult = $sale_res['list']['sale_type_adult'];
  194. $sale_type_child = $sale_res['list']['sale_type_child'];
  195. $diff_arr_adult = $sale_res['list']['diff_para_adult'];
  196. $diff_arr_child = $sale_res['list']['diff_para_child'];
  197. if ($sale_type_adult == 1) {
  198. $final_total_money_adult =$tourist_total_cost_adult+ $adult_num * $diff_arr_adult;//固定加价
  199. } else {
  200. $final_total_money_adult = $tourist_total_cost_adult * (1+0.01 * $diff_arr_adult);//百分比加价
  201. }
  202. if($sale_type_child ==1){
  203. $final_total_money_child=$tourist_total_cost_child+$child_num * $diff_arr_child;//固定加价
  204. }else{
  205. $final_total_money_child = $tourist_total_cost_child * (1+0.01 * $diff_arr_child);//百分比加价
  206. }
  207. $final_total_money = floor($final_total_money_adult+$final_total_money_child);//最终价格向下取整
  208. #5.3 判断最终自由行产品总售价,如果非正则报相应错误信息
  209. if ($final_total_money <= 0) {
  210. $result['code'] = '1';
  211. $result['info'] = '售价不能低于0';
  212. return $result;
  213. }
  214. $tourist_total_cost=$tourist_total_cost_child+$tourist_total_cost_adult;
  215. $extra_info = array(
  216. 'tourist_id' => $tourist_id,
  217. 'run_date' => $run_date,
  218. 'org_id' => $org_id,
  219. 'total_cost' => $tourist_total_cost,
  220. 'bus_cost' => $bus_total_cost,
  221. 'hotel_cost' => $hotel_total_cost,
  222. 'ticket_cost' => $ticket_total_cost_adult+$ticket_total_cost_child,
  223. 'adult_num' => $adult_num,
  224. 'child_num' => $child_num
  225. );
  226. $result['code'] = '0';
  227. $result['info'] = '获取自由行产品应付金额成功';
  228. $result['list'] = array('total_money' => $final_total_money, 'extra_info' => $extra_info);
  229. return $result;
  230. }
  231. /**
  232. * Function Description:判断自由行产品是否可售
  233. * Function Name: getTouristIsOnSale
  234. * @param int $tourist_id 自由行产品id
  235. * @return array
  236. *
  237. * @author 温依莅
  238. */
  239. public function getTouristIsOnSale($tourist_id)
  240. {
  241. $result = array();
  242. $res = (new Query())->select('a.tourist_id,a.is_onsale,a.pre_days,a.pre_time')
  243. ->from('opera_tourist_common as a')
  244. ->where('a.tourist_id=' . $tourist_id)
  245. ->limit(1)->one();
  246. if (!$res || $res['is_onsale'] == 0) {
  247. $result['code'] = '1';
  248. $result['info'] = '该自由行产品不可售';
  249. return $result;
  250. }
  251. $result['code'] = '0';
  252. $result['info'] = '该自由行产品可售';
  253. return $result;
  254. }
  255. /**
  256. * Function Description:参数转换:将TR-1101格式转为1101
  257. * Function Name: getTouristPara
  258. * @param int $tourist_id
  259. *
  260. * @return mixed
  261. *
  262. * @author 温依莅
  263. */
  264. public function getTouristPara($tourist_id)
  265. {
  266. if (strpos($tourist_id, 'TR-') === false) {
  267. return array('real_id' => $tourist_id, 'list' => array());
  268. } else {
  269. $arr = explode('-', $tourist_id);
  270. return array('real_id' => $arr[1], 'list' => $arr);
  271. }
  272. }
  273. /**
  274. * Function Description:获取自由行产品价格日历加价方式
  275. * Function Name: getTouristAddInfo
  276. * @param int $tourist_id 自由行产品id
  277. * @param string $run_date 出发时间
  278. * @param int $org_id 自由行销售渠道id
  279. *
  280. * @return array
  281. *
  282. * @author 温依莅
  283. */
  284. public function getTouristAddInfo($tourist_id, $run_date, $org_id)
  285. {
  286. $result = array();
  287. $res = (new Query())->select('tourist_id,sale_type_adult,diff_para_adult,sale_type_child,diff_para_child,is_onsale')->from('opera_tourist_run')->where(['tourist_id' => $tourist_id, 'run_date' => $run_date, 'to_org_id' => $org_id])->limit(1)->one();
  288. if (!$res) { //没有在opera_product_run设置,取默认设置
  289. $sale_type_adult = 2;
  290. $sale_type_child = 2;
  291. $diff_para_adult = Yii::$app->params['tourist_profit'] ? Yii::$app->params['tourist_profit'] : 10;
  292. $diff_para_child = Yii::$app->params['tourist_profit'] ? Yii::$app->params['tourist_profit'] : 10;
  293. } else if (!$res['is_onsale']) { //该渠道日期下架不可售
  294. $result['code'] = '1';
  295. $result['info'] = '该日期不可售';
  296. return $result;
  297. } else {
  298. $sale_type_adult = $res['sale_type_adult'];
  299. $sale_type_child = $res['sale_type_child'];
  300. $diff_para_adult = $res['diff_para_adult'];
  301. $diff_para_child = $res['diff_para_child'];
  302. }
  303. $result['code'] = '0';
  304. $result['info'] = '获取加价信息成功';
  305. $result['list'] = array('sale_type_adult' => $sale_type_adult, 'diff_para_adult' => $diff_para_adult,'sale_type_child'=>$sale_type_child,'diff_para_child'=>$diff_para_child);
  306. return $result;
  307. }
  308. /**
  309. * Function Description:获取组合产品的库存和成本
  310. * Function Name: getTouristStock
  311. * @param int $tourist_id
  312. * @param string $run_date 出发日期
  313. * @param int $org_id 组合产品售卖渠道id
  314. * @param int $org_id 组合产品销售渠道id
  315. * @param int $user_id 用户id
  316. * @param int $main_corp_id 运营主体id
  317. * @return array
  318. *
  319. * @author 温依莅
  320. */
  321. public function getTouristStock($tourist_id, $run_date, $org_id, $user_id, $main_corp_id = -1)
  322. {
  323. $stock_obj = new GetStockData();
  324. //1,校验参数,获取部分数据
  325. $result = array();
  326. $param = array('tourist_id' => $tourist_id, 'run_date' => $run_date, 'org_id' => $org_id, 'user_id' => $user_id, 'main_corp_id' => $main_corp_id);
  327. $check_obj = new CheckData();
  328. if (!$check_obj->checkArrayData($param, [[['tourist_id', 'user_id'], 2], [['main_corp_id'], 3], [['run_date'], 6]])) {
  329. $result['code'] = '1';
  330. $result['info'] = '参数格式不正确(tourist_id,run_date)';
  331. return $result;
  332. }
  333. #1.1 获取运营主体id
  334. $corp_res = $this->getTouristMainCorpId($user_id, $main_corp_id);
  335. if ($corp_res['code'] != '0') {
  336. $result['code'] = '1';
  337. $result['info'] = $corp_res['info'];
  338. return $result;
  339. }
  340. $main_corp_id = $corp_res['list']['main_corp_id'];//获取运营主体id
  341. #1.2获取运营主体内部采购渠道id
  342. // $purchase_res = $this->getPurchaseOrgId($main_corp_id);
  343. // if ($purchase_res['code'] != '0') {
  344. // $result['code'] = '1';
  345. // $result['info'] = $purchase_res['info'];
  346. // return $result;
  347. // }
  348. // $purchase_org_id = $purchase_res['list']['purchase_org_id'];
  349. //2,根据组合产品tourist_id获取组合产品子资源信息
  350. #2.1 初步获取组合产品
  351. $res = $this->getTouristResource($tourist_id);
  352. if ($res['code'] != '0') {
  353. $result['code'] = '1';
  354. $result['info'] = $res['info'];
  355. return $result;
  356. }
  357. $res_info = $res['list']['res_info'];
  358. #2.2,按日期,资源类型重排组合资源数组
  359. $tourist_arr = array();
  360. foreach ($res_info as $k => $v) {
  361. $the_date = date('Y-m-d', strtotime('+' . $v['day_from_start'] . ' day', strtotime($run_date)));//获取组合产品各子资源生效日期
  362. $tourist_arr[$the_date][$v['res_type']][$v['id']] = $v;
  363. }
  364. //3,处理组合产品子资源获取库存和成本
  365. $stock_info = array();//库存数组
  366. #按日期循环
  367. foreach ($tourist_arr as $tk => $tv) {
  368. #-按资源类型循环($rk:1巴士 2酒店 3门票)
  369. foreach ($tv as $rk => $rv) {
  370. #--巴士资源
  371. if ($rk == 1) {
  372. #--【巴士】获取巴士人群类型(成人10,儿童01,成人儿童11)
  373. if (!isset($stock_info[$tk]['bus']['crowd_type'])) {
  374. $tmp_arr = current($rv);
  375. $bus_crowd_type = $tmp_arr['crowd_type'];
  376. $stock_info[$tk]['bus']['crowd_type'] = $bus_crowd_type;
  377. }
  378. #--【巴士】循环该日期该资源类型下的具体巴士子资源
  379. foreach ($rv as $sk => $sv) {
  380. #取巴士库存时所用的渠道商(传0时取蜘蛛国旅)
  381. $bus_org_id=$org_id==0?1:$org_id;
  382. #---【巴士】获取班次run_id
  383. $run_res = $this->getBusRunInfo($sv['sub_res_id'], $tk, $sv['extra_res_info']);
  384. if ($run_res['code'] != '0') {
  385. $result['code'] = '1';
  386. $result['info'] = $run_res['info'];
  387. return $result;
  388. }
  389. #---【巴士】获取巴士该班次票种的成本
  390. $bus_cost = $stock_obj->getBusBasicCost($sv['sub_res_id'], $bus_org_id, $user_id, $main_corp_id);
  391. if ($bus_cost['code'] != '0') {
  392. $result['code'] = '1';
  393. $result['info'] = $bus_cost['info'];
  394. return $result;
  395. }
  396. if (!isset($stock_info[$tk]['bus']['cost'])) {
  397. $stock_info[$tk]['bus']['cost'] = 0;//$bus_cost['list']['sale_price'];
  398. }
  399. $stock_info[$tk]['bus']['cost'] += $bus_cost['list']['sale_price'];//获取巴士当日成本
  400. #---【巴士】获取巴士该班次票种的库存
  401. $bus_stock = $stock_obj->getBusBasicStock($run_res['list']['run_id'], $run_res['list']['prod_id']);
  402. if ($bus_stock['code'] != '0') {
  403. $result['code'] = '1';
  404. $result['info'] = $bus_stock['info'];
  405. return $result;
  406. }
  407. #---【巴士】比较获取该日期该班次票种的单次可售最大数
  408. if (!isset($stock_info[$tk]['bus']['stock'])) {
  409. $stock_info[$tk]['bus']['stock'] = $bus_stock['list']['single_max_stock'];
  410. }
  411. $stock_info[$tk]['bus']['stock'] = min($stock_info[$tk]['bus']['stock'], $bus_stock['list']['single_max_stock']);
  412. #---【巴士】参数集合
  413. $stock_info[$tk]['bus']['detail_list'][$sk]['cost'] = $bus_cost['list']['sale_price'];
  414. $stock_info[$tk]['bus']['detail_list'][$sk]['stock'] = $bus_stock['list']['single_max_stock'];
  415. $stock_info[$tk]['bus']['detail_list'][$sk]['param'] = array('run_id' => $run_res['list']['run_id'], 'prod_id' => $sv['sub_res_id'], 'org_id' => $bus_org_id, 'user_id' => $user_id, 'main_corp_id' => $main_corp_id);
  416. }
  417. #--酒店资源
  418. } else if ($rk == 2) {
  419. #酒店获取价格默认渠道时为微信渠道#
  420. $hotel_org_id=$org_id==0?164:$org_id;
  421. #--【酒店】获取酒店人群类型(成人10,儿童01,成人儿童11)
  422. if (!isset($stock_info[$tk]['hotel']['crowd_type'])) {
  423. $tmp_arr = current($rv);
  424. $hotel_crowd_type = $tmp_arr['crowd_type'];
  425. $stock_info[$tk]['hotel']['crowd_type'] = $hotel_crowd_type;
  426. }
  427. #--【酒店】循环该日期该资源类型下的酒店子资源
  428. foreach ($rv as $sk => $sv) {
  429. #---【酒店】获取酒店该日期该子房型该渠道下的库存和成本
  430. $hotel_stock = HotelUtil::getHotelStockAndPrice($sv['extra_res_info'], $sv['top_res_id'], $sv['sub_res_id'], $tk, $hotel_org_id);
  431. if ($hotel_stock['code'] != '0') {
  432. $result['code'] = '1';
  433. $result['info'] = $hotel_stock['info'];
  434. return $result;
  435. }
  436. if (!isset($stock_info[$tk]['hotel']['cost'])) {
  437. $stock_info[$tk]['hotel']['cost'] = 0;//$hotel_stock['list']['price'];
  438. $stock_info[$tk]['hotel']['diff_cost'] = 0;//单人差成本
  439. }
  440. #---【酒店】判断酒店房间最大容纳人数,若小于1,返回错误信息
  441. if ($sv['max_num'] < 1) {
  442. $result['code'] = '1';
  443. $result['info'] = 'hotel_id:' . $sv['extra_res_info'] . '房型最大人数无效';
  444. return $result;
  445. }
  446. $stock_info[$tk]['hotel']['cost'] += round($hotel_stock['list']['price'] / $sv['max_num'], 2);//获取酒店当日成本
  447. $single_room_diff = ($sv['max_num'] == 1) ? 0 : round($hotel_stock['list']['price'] / $sv['max_num'], 2);//酒店单人差
  448. $stock_info[$tk]['hotel']['diff_cost'] += $single_room_diff;
  449. #---【酒店】比较获取该日期该酒店子房型的单次可售最大数
  450. if (!isset($stock_info[$tk]['hotel']['channel_stock'])) {
  451. $stock_info[$tk]['hotel']['channel_stock'] = $hotel_stock['list']['limit_total_num'] * $sv['max_num'];//酒店的渠道限制库存【人数】(对该运营主体的内部采购渠道)
  452. }
  453. if (!isset($stock_info[$tk]['hotel']['total_stock'])) {
  454. $stock_info[$tk]['hotel']['total_stock'] = $hotel_stock['list']['max_total_num'] * $sv['max_num'];//酒店的总体库存【人数】(对该运营主体的内部采购渠道)
  455. }
  456. $stock_info[$tk]['hotel']['channel_stock'] = min($stock_info[$tk]['hotel']['channel_stock'], $hotel_stock['list']['limit_total_num'] * $sv['max_num']);
  457. $stock_info[$tk]['hotel']['total_stock'] = min($stock_info[$tk]['hotel']['total_stock'], $hotel_stock['list']['max_total_num'] * $sv['max_num']);
  458. #---【酒店】参数集合
  459. $stock_info[$tk]['hotel']['detail_list'][$sk]['channel_stock'] = $hotel_stock['list']['limit_total_num'] * $sv['max_num'];
  460. $stock_info[$tk]['hotel']['detail_list'][$sk]['total_stock'] = $hotel_stock['list']['max_total_num'] * $sv['max_num'];
  461. $stock_info[$tk]['hotel']['detail_list'][$sk]['cost'] = $hotel_stock['list']['price'];
  462. $stock_info[$tk]['hotel']['detail_list'][$sk]['diff_cost'] = $single_room_diff;
  463. $stock_info[$tk]['hotel']['detail_list'][$sk]['room_max_people'] = $sv['max_num'];//单间子房间最大人数
  464. $stock_info[$tk]['hotel']['detail_list'][$sk]['param'] = array('hotel_id' => $sv['extra_res_info'], 'base_room_type' => $sv['top_res_id'], 'room_type' => $sv['sub_res_id'], 'run_date' => $tk, 'org_id' => $hotel_org_id);
  465. }
  466. #--门票资源
  467. } else if ($rk == 3) {
  468. $ticket_has_adult = 0;//门票是否有成人子资源
  469. $ticket_has_child = 0;//门票是否有儿童子资源
  470. #--【门票】获取门票人群类型(成人10,儿童01,成人儿童11)
  471. if (!isset($stock_info[$tk]['ticket']['crowd_type'])) {
  472. $tmp_arr = current($rv);
  473. $ticket_crowd_type = $tmp_arr['crowd_type'];
  474. $stock_info[$tk]['ticket']['crowd_type'] = $ticket_crowd_type;
  475. }
  476. if ($ticket_crowd_type == '11') { //成人+儿童
  477. $ticket_has_adult = 1;
  478. $ticket_has_child = 1;
  479. } else if ($ticket_crowd_type == '10') { //成人
  480. $ticket_has_adult = 1;
  481. $ticket_has_child = 0;
  482. } else if ($ticket_crowd_type == '01') { //儿童
  483. $ticket_has_adult = 0;
  484. $ticket_has_child = 1;
  485. }
  486. #--【门票】循环该日期该资源类型下的门票子资源
  487. foreach ($rv as $sk => $sv) {
  488. #---【门票】获取门票该日期的库存和成本【门票这里产品要区分成人和儿童】
  489. #---(1),【门票成人】
  490. if ($ticket_has_adult) {
  491. $ticket_stock_adult = $stock_obj->getTicketBasicStock($sv['top_res_id'], $sv['sub_res_id'], $tk,$org_id);
  492. if ($ticket_stock_adult['code'] != '0') {
  493. $result['code'] = '1';
  494. $result['info'] = $ticket_stock_adult['info'];
  495. return $result;
  496. }
  497. if (!isset($stock_info[$tk]['ticket']['adult_cost'])) {
  498. $stock_info[$tk]['ticket']['adult_cost'] = 0;//$ticket_stock_adult['list']['base_price'];
  499. }
  500. $stock_info[$tk]['ticket']['adult_cost'] += $ticket_stock_adult['list']['base_price'];//获取门票当日成人成本
  501. #---【门票】比较获取该日期该门票子票种(成人类型)的单次可售最大数
  502. if (!isset($stock_info[$tk]['ticket']['adult_stock'])) {
  503. $stock_info[$tk]['ticket']['adult_stock'] = $ticket_stock_adult['list']['total_stock'];//门票[成人]的库存
  504. }
  505. $stock_info[$tk]['ticket']['adult_stock'] = min($stock_info[$tk]['ticket']['adult_stock'], $ticket_stock_adult['list']['total_stock']);
  506. }
  507. #---(2),【门票儿童】
  508. if ($ticket_has_child) {
  509. $ticket_stock_child = $stock_obj->getTicketBasicStock($sv['top_res_id'], $sv['sub_res_id1'], $tk,$org_id);
  510. if ($ticket_stock_child['code'] != '0') {
  511. $result['code'] = '1';
  512. $result['info'] = $ticket_stock_child['info'];
  513. return $result;
  514. }
  515. if (!isset($stock_info[$tk]['ticket']['child_cost'])) {
  516. $stock_info[$tk]['ticket']['child_cost'] = 0;//$ticket_stock_child['list']['base_price'];
  517. }
  518. $stock_info[$tk]['ticket']['child_cost'] += $ticket_stock_child['list']['base_price'];//获取门票当日儿童成本
  519. #---【门票】比较获取该日期该门票子票种(儿童类型)的单次可售最大数
  520. if (!isset($stock_info[$tk]['ticket']['child_stock'])) {
  521. $stock_info[$tk]['ticket']['child_stock'] = $ticket_stock_child['list']['total_stock'];//门票[成人]的库存
  522. }
  523. $stock_info[$tk]['ticket']['child_stock'] = min($stock_info[$tk]['ticket']['child_stock'], $ticket_stock_child['list']['total_stock']);
  524. }
  525. #---【门票】参数集合
  526. if ($ticket_has_adult) {
  527. $stock_info[$tk]['ticket']['detail_list'][$sk]['adult_stock'] = $ticket_stock_adult['list']['total_stock'];
  528. $stock_info[$tk]['ticket']['detail_list'][$sk]['adult_cost'] = $ticket_stock_adult['list']['base_price'];
  529. }
  530. if ($ticket_has_child) {
  531. $stock_info[$tk]['ticket']['detail_list'][$sk]['child_stock'] = $ticket_stock_child['list']['total_stock'];
  532. $stock_info[$tk]['ticket']['detail_list'][$sk]['child_cost'] = $ticket_stock_child['list']['base_price'];
  533. }
  534. $stock_info[$tk]['ticket']['detail_list'][$sk]['param'] = array('main_prod_id' => $sv['top_res_id'], 'sub_prod_id' => $sv['sub_res_id'], 'run_date' => $tk);
  535. }
  536. }
  537. }
  538. }
  539. //4,整合处理组合产品库存信息
  540. $hotel_extra_info = array();//酒店成本信息
  541. $bus_extra_info = array('list' => array('adult_cost' => 0, 'child_cost' => 0));//巴士成本信息
  542. $ticket_extra_info = array('list' => array('adult_cost' => 0, 'child_cost' => 0));//门票成本信息
  543. #4.1循环得到每日的库存成本数据
  544. foreach ($stock_info as $date_k => $date_v) {
  545. #初始化该日期的数组
  546. $date_stock_arr[$date_k] = array(
  547. 'limit_total_num' => 1000000, //渠道限制销售总库存
  548. 'limit_adult_num' => 1000000, //渠道限制销售成人总库存
  549. 'max_total_num' => 1000000, //总体剩余库存
  550. 'max_adult_num' => 1000000, //总体成人剩余库存
  551. 'adult_cost' => 0, //成人成本
  552. 'child_cost' => 0, //儿童成本
  553. 'diff_cost' => 0 //单人差成本
  554. );
  555. foreach ($date_v as $res_k => $res_v) {
  556. if ($res_k == 'bus') { //【巴士】成人+儿童
  557. #处理得到巴士成本信息
  558. $bus_extra_info['crowd_type'] = $res_v['crowd_type'];
  559. $bus_extra_info['list']['adult_cost'] += $res_v['cost'];
  560. $bus_extra_info['list']['child_cost'] += $res_v['cost'];
  561. $date_stock_arr[$date_k]['limit_total_num'] = min($date_stock_arr[$date_k]['limit_total_num'], $res_v['stock']);
  562. $date_stock_arr[$date_k]['limit_adult_num'] = min($date_stock_arr[$date_k]['limit_adult_num'], $res_v['stock']);
  563. $date_stock_arr[$date_k]['max_total_num'] = min($date_stock_arr[$date_k]['max_total_num'], $res_v['stock']);
  564. $date_stock_arr[$date_k]['max_adult_num'] = min($date_stock_arr[$date_k]['max_adult_num'], $res_v['stock']);
  565. $date_stock_arr[$date_k]['adult_cost'] += $res_v['cost'];
  566. $date_stock_arr[$date_k]['child_cost'] += $res_v['cost'];
  567. //$date_stock_arr[$date_k]['diff_cost'] += 0;
  568. } else if ($res_k == 'hotel') { //【酒店】
  569. #处理得到酒店成本信息
  570. $hotel_extra_info['crowd_type'] = $res_v['crowd_type'];
  571. $hotel_extra_info['list'][$date_k] = $res_v['detail_list'];
  572. if ($res_v['crowd_type'] == '10') { #【酒店】人群:仅成人
  573. //$date_stock_arr[$date_k]['limit_total_num'] = min($date_stock_arr[$date_k]['limit_total_num'], $res_v['channel_stock']);//仅成人情况,此处不再取最小值
  574. $date_stock_arr[$date_k]['limit_adult_num'] = min($date_stock_arr[$date_k]['limit_adult_num'], $res_v['channel_stock']);
  575. //$date_stock_arr[$date_k]['max_total_num'] = min($date_stock_arr[$date_k]['max_total_num'], $res_v['total_stock']);//仅成人情况,此处不再取最小值
  576. $date_stock_arr[$date_k]['max_adult_num'] = min($date_stock_arr[$date_k]['max_adult_num'], $res_v['total_stock']);
  577. $date_stock_arr[$date_k]['adult_cost'] += $res_v['cost'];
  578. //$date_stock_arr[$date_k]['child_cost'] += $res_v['cost'];
  579. $date_stock_arr[$date_k]['diff_cost'] += $res_v['diff_cost'];
  580. } else { #【酒店】人群:成人+儿童
  581. $date_stock_arr[$date_k]['limit_total_num'] = min($date_stock_arr[$date_k]['limit_total_num'], $res_v['channel_stock']);
  582. $date_stock_arr[$date_k]['limit_adult_num'] = min($date_stock_arr[$date_k]['limit_adult_num'], $res_v['channel_stock']);
  583. $date_stock_arr[$date_k]['max_total_num'] = min($date_stock_arr[$date_k]['max_total_num'], $res_v['total_stock']);
  584. $date_stock_arr[$date_k]['max_adult_num'] = min($date_stock_arr[$date_k]['max_adult_num'], $res_v['total_stock']);
  585. $date_stock_arr[$date_k]['adult_cost'] += $res_v['cost'];
  586. $date_stock_arr[$date_k]['child_cost'] += $res_v['cost'];
  587. $date_stock_arr[$date_k]['diff_cost'] += $res_v['diff_cost'];
  588. }
  589. } else if ($res_k == 'ticket') { //【门票】
  590. #处理得到门票成本信息
  591. $ticket_extra_info['crowd_type'] = $res_v['crowd_type'];
  592. $ticket_extra_info['list']['adult_cost'] += $res_v['adult_cost'];
  593. if ($res_v['crowd_type'] == '10') {
  594. $ticket_extra_info['list']['child_cost'] = 0;
  595. } else {
  596. $ticket_extra_info['list']['child_cost'] += $res_v['child_cost'];
  597. }
  598. if ($res_v['crowd_type'] == '10') { #【门票】人群:仅成人
  599. $date_stock_arr[$date_k]['limit_total_num'] = min($date_stock_arr[$date_k]['limit_total_num'], $res_v['adult_stock']);
  600. $date_stock_arr[$date_k]['limit_adult_num'] = min($date_stock_arr[$date_k]['limit_adult_num'], $res_v['adult_stock']);
  601. $date_stock_arr[$date_k]['max_total_num'] = min($date_stock_arr[$date_k]['max_total_num'], $res_v['adult_stock']);
  602. $date_stock_arr[$date_k]['max_adult_num'] = min($date_stock_arr[$date_k]['max_adult_num'], $res_v['adult_stock']);
  603. $date_stock_arr[$date_k]['adult_cost'] += $res_v['adult_cost'];
  604. //$date_stock_arr[$date_k]['child_cost'] += $res_v['child_cost'];
  605. //$date_stock_arr[$date_k]['diff_cost'] += $res_v['diff_cost'];
  606. } else { #【门票】人群:成人+儿童
  607. $date_stock_arr[$date_k]['limit_total_num'] = min($date_stock_arr[$date_k]['limit_total_num'], $res_v['adult_stock'] + $res_v['child_stock']);
  608. $date_stock_arr[$date_k]['limit_adult_num'] = min($date_stock_arr[$date_k]['limit_adult_num'], $res_v['adult_stock']);
  609. $date_stock_arr[$date_k]['max_total_num'] = min($date_stock_arr[$date_k]['max_total_num'], $res_v['adult_stock'] + $res_v['child_stock']);
  610. $date_stock_arr[$date_k]['max_adult_num'] = min($date_stock_arr[$date_k]['max_adult_num'], $res_v['adult_stock']);
  611. $date_stock_arr[$date_k]['adult_cost'] += $res_v['adult_cost'];
  612. $date_stock_arr[$date_k]['child_cost'] += $res_v['child_cost'];
  613. //$date_stock_arr[$date_k]['diff_cost'] += $res_v['diff_cost'];
  614. }
  615. }
  616. }
  617. }
  618. #4.2整合得到最终库存成本数据
  619. $final_stock_arr = array(
  620. 'tourist_id' => $tourist_id,
  621. 'limit_total_num' => 1000000, //渠道限制销售总库存
  622. 'limit_adult_num' => 1000000, //渠道限制销售成人总库存
  623. 'max_total_num' => 1000000, //总体剩余库存
  624. 'max_adult_num' => 1000000, //总体成人剩余库存
  625. 'adult_cost' => 0, //成人成本
  626. 'child_cost' => 0, //儿童成本
  627. 'diff_cost' => 0, //单人差成本
  628. 'extra_info' => array('bus_extra_info' => $bus_extra_info, 'hotel_extra_info' => $hotel_extra_info, 'ticket_extra_info' => $ticket_extra_info)//附属数据供计算价格使用
  629. );
  630. foreach ($date_stock_arr as $dk => $dv) {
  631. $final_stock_arr['limit_total_num'] = min($final_stock_arr['limit_total_num'], $dv['limit_total_num']);
  632. $final_stock_arr['limit_adult_num'] = min($final_stock_arr['limit_adult_num'], $dv['limit_adult_num']);
  633. $final_stock_arr['max_total_num'] = min($final_stock_arr['max_total_num'], $dv['max_total_num']);
  634. $final_stock_arr['max_adult_num'] = min($final_stock_arr['max_adult_num'], $dv['max_adult_num']);
  635. $final_stock_arr['adult_cost'] += $dv['adult_cost'];
  636. $final_stock_arr['child_cost'] += $dv['child_cost'];
  637. $final_stock_arr['diff_cost'] += $dv['diff_cost'];
  638. }
  639. #4.3对库存做非负处理
  640. $final_stock_arr['ori_stock'] = array('limit_total_num' => $final_stock_arr['limit_total_num'], 'limit_adult_num' => $final_stock_arr['limit_adult_num'], 'max_total_num' => $final_stock_arr['max_total_num'], 'max_adult_num' => $final_stock_arr['max_adult_num']);
  641. $final_stock_arr['limit_total_num'] < 0 && $final_stock_arr['limit_total_num'] = 0;
  642. $final_stock_arr['limit_adult_num'] < 0 && $final_stock_arr['limit_adult_num'] = 0;
  643. $final_stock_arr['max_total_num'] < 0 && $final_stock_arr['max_total_num'] = 0;
  644. $final_stock_arr['max_adult_num'] < 0 && $final_stock_arr['max_adult_num'] = 0;
  645. $result['code'] = '0';
  646. $result['info'] = '获取组合产品库存成本信息成功';
  647. $result['list'] = $final_stock_arr;
  648. return $result;
  649. }
  650. /**
  651. * Function Description:获取组合产品子资源
  652. * Function Name: getTouristResource
  653. * @param $tourist_id
  654. *
  655. * @return array
  656. * @author 温依莅
  657. */
  658. public function getTouristResource($tourist_id)
  659. {
  660. $res = (new Query())->select([
  661. 'id',
  662. 'tourist_id',
  663. 'create_user_id',
  664. 'create_time',
  665. 'update_user_id',
  666. 'update_time',
  667. 'cancel_flag',
  668. 'res_type',
  669. 'top_res_id',
  670. 'sub_res_id',
  671. 'sub_res_id1',
  672. 'select_res_ids',
  673. 'select_res_ids1',
  674. 'extra_res_info',
  675. 'crowd_type',
  676. 'max_num',
  677. 'day_from_start',
  678. ])->from('opera_tourist_detail')
  679. ->where([
  680. 'tourist_id' => $tourist_id,
  681. 'cancel_flag' => 0
  682. ])->all();
  683. if (!$res) {
  684. $result['code'] = '1';
  685. $result['info'] = '无符合条件组合产品';
  686. return $result;
  687. }
  688. $result['code'] = '0';
  689. $result['info'] = '获取组合产品子资源成功';
  690. $result['list'] = array('tourist_id' => $tourist_id, 'res_info' => $res);
  691. return $result;
  692. }
  693. /**
  694. * Function Description:获取运营主体内部采购渠道id
  695. * Function Name: getPurchaseOrgId
  696. * @param $main_corp_id
  697. *
  698. * @return array
  699. * @author 温依莅
  700. */
  701. public function getPurchaseOrgId($main_corp_id)
  702. {
  703. $result = array();
  704. $res = (new Query())->select(['id', 'purchase_org_id'])->from('base_main_corporation')->where(['id' => $main_corp_id])->one();
  705. if (!$res) {
  706. $result['code'] = '1';
  707. $result['info'] = '获取运营主体内部采购渠道出错';
  708. return $result;
  709. }
  710. $result['code'] = '0';
  711. $result['info'] = '获取运营主体内部采购渠道成功';
  712. $result['list'] = array('purchase_org_id' => $res['purchase_org_id'], 'main_corp_id' => $main_corp_id);
  713. return $result;
  714. }
  715. /**
  716. * Function Description:获取运营主体id
  717. * Function Name: getTouristMainCorpId
  718. * @param int $user_id 用户id
  719. * @param int $main_corp_id 运营主体id,若非-1,则直接取该值,否则从user_id判断main_corp_id值
  720. *
  721. * @return mixed
  722. *
  723. * @author 温依莅
  724. */
  725. public function getTouristMainCorpId($user_id, $main_corp_id = -1)
  726. {
  727. $res = (new Query())->select('id,main_corp_id,user_name')->from('base_user')->where(['id' => $user_id, 'cancel_flag' => 0])->one();
  728. if (!$res) {
  729. $result['code'] = '1';
  730. $result['info'] = '无效用户';
  731. return $result;
  732. }
  733. $real_main_corp_id = ($main_corp_id == -1 ? $res['main_corp_id'] : $main_corp_id);
  734. if ($real_main_corp_id == 0) { //如果main_corp_id为0,下单时视为蜘蛛国旅(运营主体为1)处理
  735. $real_main_corp_id = 1;
  736. }
  737. $result['code'] = '0';
  738. $result['info'] = '获取运营主体成功';
  739. $result['list'] = array('user_id' => $user_id, 'main_corp_id' => $real_main_corp_id);
  740. return $result;
  741. }
  742. /**
  743. * Function Description:巴士根据票种,和票种出发时间判断班次run_id
  744. * Function Name: getBusRunInfo
  745. * @param int $prod_id 巴士票种id
  746. * @param string $run_date 出发日期
  747. * @param string $start_time 票种的出发时间
  748. *
  749. * @return array
  750. *
  751. * @author 温依莅
  752. */
  753. public function getBusRunInfo($prod_id, $run_date, $start_time)
  754. {
  755. $result = array();
  756. //1,判断日期格式是否正确
  757. if (!preg_match('/^(0[0-9]|1[0-9]|2[0-3])\:(0[0-9]|[1-5][0-9])$/', $start_time)) {
  758. $result['code'] = '1';
  759. $result['info'] = '巴士产品出发时间格式不正确';
  760. return $result;
  761. }
  762. //2,获取班次信息
  763. $res = (new Query())->select([
  764. 'rm.run_id',
  765. 'rm.run_date',
  766. 'rp.parent_prod_id as line_id',
  767. 'rp.prod_id',
  768. 'rs.station_res_id',
  769. 'rs.start_time',
  770. ])->from('run_prod as rp')
  771. ->leftJoin('run_main as rm', 'rm.run_id=rp.run_id')
  772. ->leftJoin('run_station rs', 'rp.start_station_res_id=rs.station_res_id')
  773. ->leftJoin('run_bus rb', 'rb.RUN_ID = rp.RUN_ID')
  774. ->where([
  775. 'rp.prod_id' => $prod_id,
  776. 'rm.run_date' => $run_date,
  777. 'rs.start_time' => $start_time,
  778. 'rp.cancel_flag' => 0,
  779. 'rb.run_bus_status' => 138,
  780. ])->limit(1)->one();
  781. if (!$res) {
  782. $reason = '票种' . $prod_id . '在' . $run_date . ' ' . $start_time . '无符合条件班次';
  783. $result['code'] = '1';
  784. $result['info'] = $reason;
  785. return $result;
  786. }
  787. $result['code'] = '0';
  788. $result['info'] = '获取巴士班次成功';
  789. $result['list'] = $res;
  790. return $result;
  791. }
  792. }