TechniciansController.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. <?php
  2. namespace addons\ReservationService\api\modules\v1\controllers;
  3. use addons\ReservationService\common\enums\ReservationServiceEnum;
  4. use addons\ReservationService\common\services\BackendService;
  5. use addons\ReservationService\common\services\TechniciansService;
  6. use addons\SecondaryCard\common\models\SecondaryCard;
  7. use addons\Store\common\enums\ReserveServiceEnum;
  8. use addons\Store\common\models\Store;
  9. use addons\Store\common\models\StoreGoodsReserve;
  10. use addons\Store\common\models\StoreGoodsReserveSku;
  11. use addons\Store\common\services\StoreReserveSettingService;
  12. use api\controllers\OnAuthController;
  13. use common\models\goods\GoodsReserve;
  14. use common\models\goods\GoodsReserveSku;
  15. use common\models\goods\GoodsReserveTime;
  16. use common\models\mall\MallAddons;
  17. use Yii;
  18. /**
  19. * Class TechniciansController
  20. * @package addons\ReservationService\api\modules\v1\controllers
  21. */
  22. class TechniciansController extends OnAuthController
  23. {
  24. public $modelClass = '';
  25. /**
  26. * 不用进行登录验证的方法
  27. *
  28. * 例如: ['index', 'update', 'create', 'view', 'delete']
  29. * 默认全部需要验证
  30. *
  31. * @var array
  32. */
  33. protected $authOptional = [];
  34. /**
  35. * 技师搜索
  36. * @desc 适用于 根据商品搜索对应技师,技师搜索页
  37. */
  38. public function actionSearch()
  39. {
  40. $post = Yii::$app->request->get();
  41. $valid = Yii::$app->services->validate->validate($post, [
  42. [['goods_id','min_age','max_age','gender','sort','limit', 'page','sku_id', 'store_id'], 'integer'],
  43. [['name','date','time', 'date', 'time'], 'string'],
  44. [['lat','lng'], 'string'],
  45. [['lat','lng'], 'required'],
  46. [['secondary_card_id','store_cate_id','id'], 'safe'],
  47. ]);
  48. if ($valid === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  49. $page = $post['page'] ?? 1;
  50. $limit = $post['limit'] ?? 10;
  51. $post['mall_id'] = $this->mall_id;
  52. if(!empty($post['secondary_card_id'])){
  53. $res = TechniciansService::searchBySecondaryCard($post,$page,$limit);
  54. }else{
  55. $res = TechniciansService::search($post,$page,$limit);
  56. }
  57. return $this->success('成功', $res);
  58. }
  59. /**
  60. * 获取时间
  61. * @return mixed|void
  62. */
  63. public function actionGetTime()
  64. {
  65. $get = Yii::$app->request->get();
  66. $valid = Yii::$app->services->validate->validate($get, [
  67. [['goods_id','sku_id', 'store_id'], 'integer'],
  68. [['secondary_card_id','start'], 'safe'],
  69. ]);
  70. if ($valid === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  71. $days = 7;
  72. if(!empty($get['secondary_card_id'])) {
  73. if(!MallAddons::isInstall($this->mall_id,'SecondaryCard')){
  74. return $this->error('没有安装次卡插件' );
  75. }
  76. $select = 'id,reservation_time_type,reservation_time,reservation_model,appointment_interval_duration,reservation_type';
  77. $secondary_card = SecondaryCard::getOne([['id'=>$get['secondary_card_id']]],true,[],false,$select);
  78. $data = [];
  79. if($secondary_card['reservation_type']==0){
  80. return $this->success('成功', $data);
  81. }
  82. if($secondary_card['reservation_model']==1){
  83. //预约模式:1:预约门店;2:预约服务人
  84. $secondary_card['reservation_time'] = isset($secondary_card['reservation_time'])?json_decode($secondary_card['reservation_time'],true):[];
  85. if(!empty($secondary_card['reservation_time'])){
  86. foreach ($secondary_card['reservation_time'] as $item){
  87. $data[] = $this->getStoreTimeList($item,$secondary_card['appointment_interval_duration']);
  88. }
  89. }
  90. $times = array_column($data,'time');
  91. array_multisort($times,SORT_ASC,$data);
  92. return $this->success('成功', $data);
  93. }
  94. $service_min = $secondary_card['appointment_interval_duration'] ?: 10; //服务分钟
  95. $store_reserve_setting = (new StoreReserveSettingService(['mall_id' => $this->mall_id, 'store_id' => $get['store_id']]))->detail();
  96. $range_end = $store_reserve_setting['range_end'];
  97. $range_end_arr = ReserveServiceEnum::RANGE_END_ARR_MAP;
  98. $days = $range_end_arr[$range_end] ?? 7;
  99. }else{
  100. if (empty($get['store_id'])) {
  101. $goods_reserve = GoodsReserve::findOne(['goods_id' => $get['goods_id'], 'reserve_type' => GoodsReserve::RESERVE_TYPE_SERVICE]);
  102. if (!$goods_reserve) return $this->error('项目不存在');
  103. $sku = GoodsReserveSku::findOne(['id' => $get['sku_id'], 'goods_id' => $get['goods_id']]);
  104. if (!$sku) return $this->error('项目不存在');
  105. $data = BackendService::getSetting($this->mall_id);
  106. $range_end = $data['basic']['range_end'] ?? 1;
  107. $range_end_arr = ReservationServiceEnum::RANGE_END_ARR_MAP;
  108. } else {
  109. $goods_reserve = StoreGoodsReserve::findOne(['goods_id' => $get['goods_id'], 'reserve_type' => GoodsReserve::RESERVE_TYPE_SERVICE]);
  110. if (!$goods_reserve) return $this->error('项目不存在');
  111. $sku = StoreGoodsReserveSku::findOne(['id' => $get['sku_id'], 'goods_id' => $get['goods_id']]);
  112. if (!$sku) return $this->error('项目不存在');
  113. $store_reserve_setting = (new StoreReserveSettingService(['mall_id' => $this->mall_id, 'store_id' => $get['store_id']]))->detail();
  114. $range_end = $store_reserve_setting['range_end'];
  115. $range_end_arr = ReserveServiceEnum::RANGE_END_ARR_MAP;
  116. }
  117. $service_min = $sku['service_min'] ?: 10; //服务分钟
  118. $days = $range_end_arr[$range_end] ?? 7;
  119. }
  120. if (!empty($get['store_id'])) {
  121. $store = Store::findOne(['id' => $get['store_id']]);
  122. $business_time_start = $store['business_time_start'];
  123. $time1 = date('Y-m-d') . ' ' . $business_time_start . ':00';
  124. } else {
  125. $time1 = date('Y-m-d 00:00:00');
  126. }
  127. $time2 = date('Y-m-d 23:59:59');
  128. $buff = [];
  129. for($i=strtotime($time1) ;$i<=strtotime($time2) ; $i=$i+60*$service_min){
  130. $buff[]=date("H:i",$i);
  131. }
  132. $date_list = [];
  133. $time = time();
  134. if (!empty($get['store_id'])) {
  135. $store = Store::findOne(['id' => $get['store_id']]);
  136. $business_time_start = $store['business_time_start'];
  137. $business_time_end = $store['business_time_end'];
  138. $obj = new StoreReserveSettingService(['mall_id' => $this->mall_id, 'store_id' => $get['store_id']]);
  139. $store_reserve_setting = $obj->detail();
  140. $range_start = $store_reserve_setting['range_start'];
  141. $range_start_time = $obj->getRangeStartTime($range_start);
  142. } else {
  143. $data = BackendService::getSetting($this->mall_id);
  144. $range_start_time = TechniciansService::getRangeStartTime($data['basic']['range_start'] ?? 0);
  145. }
  146. $time += $range_start_time;
  147. //切割时间
  148. for ($i = 0; $i < $days; $i++) {
  149. $time_list = $buff;
  150. $date = date('Y-m-d', strtotime("+ $i days"));
  151. foreach ($time_list as $key => $val) {
  152. $temp = strtotime($date . ' ' . $val . ':00');
  153. if ($i == 0) {
  154. if ($time > $temp) {
  155. unset($time_list[$key]);
  156. continue;
  157. }
  158. if (!empty($get['store_id'])) {
  159. $start_time = strtotime($date . ' ' . $business_time_start . ':00');
  160. $end_time = strtotime($date . ' ' . $business_time_end . ':00');
  161. if ($temp < $start_time || $temp > $end_time) {
  162. unset($time_list[$key]);
  163. }
  164. }
  165. } else {
  166. if (!empty($get['store_id'])) {
  167. $start_time = strtotime($date . ' ' . $business_time_start . ':00');
  168. $end_time = strtotime($date . ' ' . $business_time_end . ':00');
  169. if ($temp < $start_time || $temp > $end_time) {
  170. unset($time_list[$key]);
  171. }
  172. }
  173. }
  174. }
  175. $time_list = array_values($time_list);
  176. $arr = ['date' => $date,'week_day' => GoodsReserveTime::getWeekDay($date),'time_list' => $time_list,'is_reserve'=>1];
  177. $date_list[] = $arr;
  178. }
  179. if(!empty($get['start'])){
  180. $start_time = strtotime($get['start'].' 00:00:00');
  181. $i=0;
  182. $temp_date_list = array_column($date_list,null,'date');
  183. $date_list = [];
  184. while (true){
  185. if($i>=7){
  186. break;
  187. }
  188. $time_list = $buff;
  189. if($start_time == strtotime(date('Y-m-d').' 00:00:00')){
  190. foreach($time_list as $key => $val){
  191. if($time > strtotime(date('Y-m-d '.$val))){
  192. unset($time_list[$key]);
  193. }
  194. }
  195. $time_list = array_values($time_list);
  196. }
  197. $temp_time = $start_time + $i*86400;
  198. $date = date('Y-m-d',$temp_time);
  199. $is_reserve = 0;
  200. if(isset($temp_date_list[$date])){
  201. $is_reserve = 1;
  202. }
  203. $date_list[]=['date'=>$date, 'week_day' => GoodsReserveTime::getWeekDay($date),'time_list' => $time_list,'is_reserve'=>$is_reserve];
  204. $i++;
  205. }
  206. }
  207. return $this->success('成功', $date_list);
  208. }
  209. private function getStoreTimeList($item,$reservation_model){
  210. $day = $item['day'];
  211. $date_arr = [];
  212. for ($i=0;$i<7;$i++){
  213. $date = date('Y-m-d', strtotime("+ $i days"));
  214. $week = date("w", strtotime($date));
  215. $date_arr[$week] = $date;
  216. }
  217. $date = $date_arr[$day];
  218. $time_start = $item['time_start'];
  219. $time = time();
  220. $today_date = date('Y-m-d',$time);
  221. $arr = [];
  222. if($date != $today_date) {
  223. $arr = [$time_start];
  224. }
  225. $time_end = $item['time_end'];
  226. $end = strtotime($date . ' ' . $time_end . ':00');
  227. while (true) {
  228. $temp_time = strtotime($date . ' ' . $time_start . ':00') + $reservation_model * 60;
  229. if ($temp_time > $end) break;
  230. $time_start = date('H:i', $temp_time);
  231. if($date == date('Y-m-d',$time)){
  232. if(strtotime($date.' '.$time_start.':00')>$time){
  233. if($date==$today_date){
  234. if($temp_time>$time+3600){
  235. $arr[] = $time_start;
  236. }
  237. }else{
  238. $arr[] = $time_start;
  239. }
  240. }
  241. }else{
  242. if($date==$today_date){
  243. if($temp_time>$time+3600){
  244. $arr[] = $time_start;
  245. }
  246. }else{
  247. $arr[] = $time_start;
  248. }
  249. }
  250. }
  251. return ['time'=>strtotime($date.' 00:00:00'),'date' => $date, 'time_list' => $arr, 'week_day' => GoodsReserveTime::getWeekDay($date)];
  252. }
  253. /**
  254. * 获取某日的时间段
  255. * @return mixed|null
  256. * @throws \Exception
  257. */
  258. public function actionGetTimes()
  259. {
  260. $get = Yii::$app->request->get();
  261. $valid = Yii::$app->services->validate->validate($get, [
  262. [['goods_id','min_age','max_age','gender','sort','limit', 'page','sku_id', 'store_id'], 'integer'],
  263. [['name','date','time', 'date', 'time'], 'string'],
  264. [['lat','lng'], 'string'],
  265. [['lat','lng'], 'required'],
  266. [['store_cate_id','tech_user_id'], 'safe'],
  267. ]);
  268. if ($valid === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  269. $get['mall_id'] = $this->mall_id;
  270. $get['limit'] = 1000;
  271. $get['page'] = 1;
  272. $res = TechniciansService::getTimes($get);
  273. return $this->success('成功', $res);
  274. }
  275. /**
  276. * 服务人员页面-平台-可预约日期
  277. * @return mixed|null
  278. */
  279. public function actionGetDate()
  280. {
  281. try {
  282. $get = Yii::$app->request->get();
  283. $get['mall_id']= $this->mall_id;
  284. $date_list = TechniciansService::getDate($get);
  285. return $this->success('成功', $date_list);
  286. }catch (\Exception $e){
  287. return $this->error($e->getMessage());
  288. }
  289. }
  290. public function actionCheckDate()
  291. {
  292. $post = Yii::$app->request->get();
  293. $valid = Yii::$app->services->validate->validate($post, [
  294. [['lat','lng','goods_id','sku_id','date'], 'required'],
  295. [['goods_id','sku_id'], 'integer'],
  296. [['date'], 'string'],
  297. ]);
  298. if ($valid === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  299. $post['mall_id'] = $this->mall_id;
  300. try {
  301. $res = TechniciansService::checkDate($post,1,1);
  302. }catch (\Exception $e){
  303. return $this->error($e->getMessage());
  304. }
  305. return $this->success('成功', $res);
  306. }
  307. public function actionReservationDate()
  308. {
  309. try {
  310. $get = Yii::$app->request->get();
  311. $valid = Yii::$app->services->validate->validate($get, [
  312. [['goods_id','sku_id','tech_user_id'], 'required'],
  313. [['goods_id','sku_id','tech_user_id'], 'integer'],
  314. [['store_id','lat','lng',], 'safe'],
  315. ]);
  316. if ($valid === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  317. $get['mall_id'] = $this->mall_id;
  318. try {
  319. $res = TechniciansService::getReservationDate($get);
  320. }catch (\Exception $e){
  321. return $this->error($e->getMessage());
  322. }
  323. return $this->success('成功', $res);
  324. }catch (\Exception $e){
  325. return $this->error($e->getMessage());
  326. }
  327. }
  328. /**
  329. * -服务时间列表
  330. * @return mixed|null
  331. */
  332. public function actionServiceTimeList()
  333. {
  334. try {
  335. $params = \Yii::$app->request->get();
  336. $rules = [
  337. [['sku_id','id'], 'required'],
  338. [['start'], 'safe'],
  339. ];
  340. $res = \Yii::$app->services->validate->validate($params, $rules);
  341. if (!$res) return $this->error(\Yii::$app->services->validate->getErrorMessage());
  342. $params['mall_id'] = $this->mall_id;
  343. $list = TechniciansService::serviceTimeList($params);
  344. return $this->success('获取成功', $list);
  345. }catch (\Exception $e){
  346. return $this->error($e->getMessage());
  347. }
  348. }
  349. /**
  350. * h5端-预约时间列表-到店分配/技师不选项
  351. * @return mixed|null
  352. */
  353. public function actionReservationTimeList()
  354. {
  355. try {
  356. $params = \Yii::$app->request->get();
  357. $rules = [
  358. [['sku_id'], 'required'],
  359. [['date'], 'safe'],
  360. ];
  361. $res = \Yii::$app->services->validate->validate($params, $rules);
  362. if (!$res) return $this->error(\Yii::$app->services->validate->getErrorMessage());
  363. if(empty($params['date'])){
  364. $params['date'] = date('Y-m-d');
  365. }
  366. $list = (new StoreReserveSettingService(['mall_id' => $this->mall_id, 'store_id' => $params['store_id']]))->toStoreReservationTimeList($params);
  367. return $this->success('获取成功', $list);
  368. }catch (\Exception $e){
  369. return $this->error($e->getMessage());
  370. }
  371. }
  372. }