BookingForm.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  1. <?php
  2. /**
  3. * 重庆赤晓店信息科技有限公司
  4. * https://www.chixiaodian.com
  5. * Copyright (c) 2023 赤店商城 All rights reserved.
  6. */
  7. namespace app\modules\admin\models\booking;
  8. use app\models\District;
  9. use app\models\SaasUser;
  10. use app\models\Order;
  11. use app\models\Cash;
  12. use app\models\User;
  13. use app\models\Worker;
  14. use app\models\WorkerCatExt;
  15. use app\models\WorkerOrderExt;
  16. use app\models\WorkerCat;
  17. use app\models\WorkerLevel;
  18. use app\models\WorkerPic;
  19. use app\models\WorkerSetting;
  20. use app\models\OrderComment;
  21. use app\models\OrderDetail;
  22. use app\utils\Notice\NoticeSend;
  23. use app\modules\client\models\v1\LoginForm;
  24. use app\models\UserShareMoney;
  25. use app\modules\client\models\OrderComplete;
  26. use app\models\BookingGoodsCat;
  27. use app\models\BookingGoodsExt;
  28. use app\models\BookingOrderExt;
  29. use app\utils\OrderNo;
  30. use app\models\Goods;
  31. class BookingForm extends Model
  32. {
  33. public $store_id;
  34. public $verify_code;
  35. public $id;
  36. public $ids;
  37. public $name; //名称
  38. public $mobile;
  39. public $gender;
  40. public $age;
  41. public $form;
  42. public $type;
  43. public $cat_id;
  44. public $user;
  45. public $user_id;
  46. public $worker_id;
  47. public $worker_name;
  48. public $level;
  49. public $desc;
  50. public $tel;
  51. public $logo;
  52. public $status;
  53. public $open_status;
  54. public $reason;
  55. public $area;
  56. public $lat;
  57. public $lng;
  58. public $province_id;
  59. public $city_id;
  60. public $district_id;
  61. public $address;
  62. public $nickname;
  63. public $order_id;
  64. public $goods_id;
  65. public $goods_name;
  66. public $score;
  67. public $begin;
  68. public $end;
  69. public $key_word;
  70. public $is_hide;
  71. public $setting;
  72. public $pic_url;
  73. public function rules()
  74. {
  75. return [
  76. [['id', 'user_id', 'level', 'type', 'status', 'province_id', 'city_id', 'district_id', 'open_status', 'gender', 'age'], 'integer'],
  77. [['desc', 'name', 'tel', 'logo', 'reason', 'area', 'lat', 'lng', 'address', 'nickname', 'verify_code', 'cat_id'], 'string'],
  78. [['user', 'form', 'order_id', 'worker_id', 'worker_name', 'goods_name', 'score', 'begin', 'end', 'key_word', 'gender', 'is_hide', 'setting', 'pic_url', 'goods_id', 'ids'], 'safe'],
  79. ];
  80. }
  81. public function catSave($id = 0, $name = '', $pic_url = '', $sort = 100, $is_show = 1) {
  82. try{
  83. $model = $id ? BookingGoodsCat::findOne($id) : new BookingGoodsCat();
  84. $model->store_id = $this->store_id;
  85. $model->name = $name;
  86. $model->pic_url = $pic_url;
  87. $model->sort = $sort;
  88. $model->is_show = $is_show;
  89. $save = $model->save();
  90. if(!$save){
  91. \Yii::error([__METHOD__, $model->attributes]);
  92. throw new \Exception('操作失败,' . array_shift($model->getFirstErrors()));
  93. }
  94. return [
  95. 'code' => 0,
  96. 'msg' => '操作成功',
  97. ];
  98. }catch(\Exception $e){
  99. \Yii::error([__METHOD__, $e]);
  100. return [
  101. 'code' => 1,
  102. 'msg' => $e->getMessage(),
  103. ];
  104. }
  105. }
  106. public function catListSelect() {
  107. $query = BookingGoodsCat::find()->where(['store_id' => $this->store_id, 'is_delete' => 0, 'is_show' => 1]);
  108. $query->orderBy('sort desc');
  109. $query->select(['id', 'name', 'sort']);
  110. $res = $query->all();
  111. return [
  112. 'code' => 0,
  113. 'msg' => 'success',
  114. 'data' => $res,
  115. // 'q' => $query->createCommand()->getRawSql(),
  116. ];
  117. }
  118. public function catList() {
  119. $query = BookingGoodsCat::find()->where(['is_delete' => 0]);
  120. $this->store_id && $query->andWhere(['store_id' => $this->store_id]);
  121. if($this->name){
  122. $query->andWhere(['like', 'name', $this->name]);
  123. }
  124. if($this->status >= 0){
  125. $query->andWhere(['is_show' => $this->status]);
  126. }
  127. $query->orderBy('sort desc');
  128. $res = pagination_make($query);
  129. return [
  130. 'code' => 0,
  131. 'msg' => 'success',
  132. 'data' => $res,
  133. // 'q' => $query->createCommand()->getRawSql(),
  134. ];
  135. }
  136. public function catStatus ()
  137. {
  138. try {
  139. if ($this->ids) {
  140. $ids = explode(',', $this->ids);
  141. if (in_array($this->status, [0, 1])) {
  142. BookingGoodsCat::updateAll(['is_show' => $this->status], ['and', ['in', 'id', $ids], ['store_id' => $this->store_id]]);
  143. }
  144. if ((int)$this->status === 2) {
  145. BookingGoodsCat::updateAll(['is_delete' => 1], ['and', ['in', 'id', $ids], ['store_id' => $this->store_id]]);
  146. }
  147. }
  148. return [
  149. 'code' => 0,
  150. 'msg' => '操作成功!'
  151. ];
  152. } catch (\Exception $e) {
  153. return [
  154. 'code' => 1,
  155. 'msg' => $e->getMessage()
  156. ];
  157. }
  158. }
  159. public function catInfo($id = 0) {
  160. $model = BookingGoodsCat::findOne($id);
  161. return [
  162. 'code' => 0,
  163. 'msg' => '操作成功',
  164. 'data' => $model,
  165. ];
  166. }
  167. public static function bookingGoodsExtSave($store_id, $goods_id, $cat_id) {
  168. $goods_ext = BookingGoodsExt::findOne(['goods_id' => $goods_id]) ?? new BookingGoodsExt();
  169. $goods_ext->store_id = $store_id;
  170. $goods_ext->goods_id = $goods_id;
  171. $goods_ext->cat_id = $cat_id;
  172. if (!$goods_ext->save()) {
  173. \Yii::error([__METHOD__, $goods_ext->attributes]);
  174. return [
  175. 'code'=>1,
  176. 'msg'=>'预约商品保存错误' . array_shift($goods_ext->getFirstErrors()),
  177. ];
  178. }
  179. return [
  180. 'code' => 0,
  181. 'msg' => '保存成功',
  182. 'data' => $goods_ext,
  183. ];
  184. }
  185. public function bookingOrderCountByGoods($params) {
  186. $query = Order::find()->alias('o')->leftJoin(['boe' => BookingOrderExt::tableName()], 'o.id=boe.order_id');
  187. $query->leftJoin(['od' => OrderDetail::tableName()], 'o.id=od.order_id');
  188. $query->leftJoin(['gb' => \app\models\GoodsBook::tableName()], 'gb.goods_id=od.goods_id');
  189. $query->leftJoin(['bge' => BookingGoodsExt::tableName()], 'od.goods_id=bge.goods_id');
  190. $query->leftJoin(['bgc' => BookingGoodsCat::tableName()], 'bge.cat_id=bgc.id');
  191. if(empty($params['booking_time_start']) || empty($params['booking_time_end'])){
  192. return [
  193. 'code'=>1,
  194. 'msg'=>'请选择时间',
  195. ];
  196. }
  197. $query->andWhere([
  198. 'o.store_id' => $this->store_id,
  199. 'o.order_type' => 2,
  200. 'o.is_delete' => 0,
  201. 'o.is_recycle' => 0,
  202. ]);
  203. $query->andWhere([
  204. '!=',
  205. 'o.trade_status',
  206. 1,
  207. ]);
  208. if($params['md_id'] > 0){
  209. $query->andWhere(['o.md_id' => $params['md_id']]);
  210. }
  211. if($params['goods_name']){
  212. $query->andWhere(['like', 'od.goods_name', $params['goods_name']]);
  213. }
  214. if($params['booking_time_start']){
  215. $query->andWhere(['>=', 'boe.booking_time_end', $params['booking_time_start']]);
  216. }
  217. if($params['booking_time_end']){
  218. $query->andWhere(['<=', 'boe.booking_time_start', $params['booking_time_end']]);
  219. }
  220. $addSelect = ['gb.service_book', 'od.goods_id', 'od.goods_name', 'od.pic', 'bgc.name', 'count(1) order_count'];
  221. $query->groupBy('od.goods_id');
  222. $query->select($addSelect);
  223. $list = $query->asArray()->all();
  224. return [
  225. 'code' => 0,
  226. 'msg' => 'ok',
  227. 'data' => $list,
  228. 'md_id' => $params['md_id'],
  229. ];
  230. }
  231. public function bookingOrderCountByWorker($params) {
  232. $query = Order::find()->alias('o')->leftJoin(['boe' => BookingOrderExt::tableName()], 'o.id=boe.order_id');
  233. $query->leftJoin(['od' => OrderDetail::tableName()], 'o.id=od.order_id');
  234. $query->leftJoin(['gb' => \app\models\GoodsBook::tableName()], 'gb.goods_id=od.goods_id');
  235. if(empty($params['booking_time_start']) || empty($params['booking_time_end']) || empty($params['goods_id'])){
  236. return [
  237. 'code'=>1,
  238. 'msg'=>'参数错误',
  239. ];
  240. }
  241. $query->andWhere([
  242. 'o.store_id' => $this->store_id,
  243. 'o.order_type' => 2,
  244. 'o.is_delete' => 0,
  245. 'o.is_recycle' => 0,
  246. ]);
  247. $query->andWhere([
  248. '!=',
  249. 'o.trade_status',
  250. 1,
  251. ]);
  252. if($params['md_id'] > 0){
  253. $query->andWhere(['o.md_id' => $params['md_id']]);
  254. }
  255. if($params['goods_id']){
  256. $query->andWhere(['od.goods_id' => $params['goods_id']]);
  257. }
  258. if($params['booking_time_start']){
  259. $query->andWhere(['>=', 'boe.booking_time_end', $params['booking_time_start']]);
  260. }
  261. if($params['booking_time_end']){
  262. $query->andWhere(['<=', 'boe.booking_time_start', $params['booking_time_end']]);
  263. }
  264. $addSelect = ['boe.booking_time_start', 'boe.worker_id', 'boe.worker_name', 'count(1) order_count'];
  265. $query->groupBy('boe.booking_time_start, boe.worker_id');
  266. $query->select($addSelect);
  267. $list = $query->asArray()->all();
  268. $newList = [];
  269. foreach($list as $item){
  270. $btime = (explode(' ', $item['booking_time_start']))[1];
  271. $newList[$btime]['count'] += $item['order_count'];
  272. $newList[$btime]['list'][] = $item;
  273. }
  274. return [
  275. 'code' => 0,
  276. 'msg' => 'ok',
  277. 'data' => $newList,
  278. 'md_id' => $params['md_id'],
  279. ];
  280. }
  281. public function bookingOrderList($params) {
  282. $query = Order::find()->alias('o')->leftJoin(['boe' => BookingOrderExt::tableName()], 'o.id=boe.order_id');
  283. $query->leftJoin(['od' => OrderDetail::tableName()], 'o.id=od.order_id');
  284. $query->leftJoin(['u' => User::tableName()], 'u.id=o.user_id');
  285. if(empty($params['booking_time_start']) || empty($params['booking_time_end'])){
  286. return [
  287. 'code'=>1,
  288. 'msg'=>'请选择时间',
  289. ];
  290. }
  291. $query->andWhere([
  292. 'o.store_id' => $this->store_id,
  293. 'o.order_type' => 2,
  294. 'o.is_delete' => 0,
  295. 'o.is_recycle' => 0,
  296. ]);
  297. $query->andWhere([
  298. '!=',
  299. 'o.trade_status',
  300. 1,
  301. ]);
  302. if($params['md_id'] > 0){
  303. $query->andWhere(['o.md_id' => $params['md_id']]);
  304. }
  305. if($params['goods_name']){
  306. $query->andWhere(['like', 'od.goods_name', $params['goods_name']]);
  307. }
  308. if($params['worker_id']){
  309. $query->andWhere(['boe.worker_id' => $params['worker_id']]);
  310. }
  311. if($params['booking_time_start']){
  312. $query->andWhere(['>=', 'boe.booking_time_end', $params['booking_time_start']]);
  313. }
  314. if($params['booking_time_end']){
  315. $query->andWhere(['<=', 'boe.booking_time_start', $params['booking_time_end']]);
  316. }
  317. if($params['status_ext'] == 500){
  318. //已超时
  319. $query->andWhere(['and', ['<', 'boe.booking_time_end', BookingOrderExt::STATUS_EXT_START], ['>', 'boe.booking_time_end', time()]]);
  320. }elseif($params['status_ext'] == 600){
  321. //未分配
  322. $query->andWhere(['boe.worker_id' => 0]);
  323. }else{
  324. isset($params['status_ext']) && $params['status_ext'] > -1 && $query->andWhere(['boe.time_sys_confirm' => $params['status_ext']]);
  325. }
  326. $addSelect = ['u.binding', 'o.id', 'o.md_id', 'o.user_id', 'o.created_at', 'o.name', 'o.mobile', 'o.remark', 'od.goods_name', 'od.goods_id', 'od.attr', 'boe.worker_id', 'boe.worker_name', 'boe.status_ext', 'boe.time_sys_confirm'];
  327. $addSelect = array_merge($addSelect, ['IF(boe.booking_time_end < "'.date('Y-m-d H:i:s').'" AND boe.status_ext < '. BookingOrderExt::STATUS_EXT_START .', 1, 0) booking_time_out']);
  328. $query->select($addSelect);
  329. $query->orderBy(['boe.booking_time_start' => SORT_ASC, 'o.id' => SORT_ASC]);
  330. $list = $query->asArray()->all();
  331. foreach($list as &$item){
  332. if (empty($item['binding'])) {
  333. $item['nickname'] = $item['de_name'];
  334. $item['avatar'] = $item['avatar_url'];
  335. } else {
  336. $sass_user = SaasUser::findOne(['mobile' => $item['binding']]);
  337. if ($sass_user) {
  338. $item['nickname'] = $sass_user->name;
  339. $item['avatar'] = $sass_user->avatar;
  340. }
  341. }
  342. $tmp_attr = json_decode($item['attr'], true);
  343. $item['attr'] = $tmp_attr;
  344. $item['boe_stime'] = date('w', strtotime($tmp_attr['start_date']));
  345. $tmp_time = explode('-', $tmp_attr['time']);
  346. $item['boe_stime'] = $tmp_time[0];
  347. }
  348. return [
  349. 'code' => 0,
  350. 'msg' => 'ok',
  351. 'data' => $list,
  352. ];
  353. }
  354. public function bookingOrderSave($params) {
  355. $time = explode('-', $params['time']);
  356. $start_date = $params['date'] . ' ' . $time[0];
  357. $end_date = $params['date'] . ' ' . $time[1];
  358. $order = $params['order_id'] ? Order::findOne($params['order_id']) : new Order();
  359. if(!$params['order_id']){
  360. $order->created_at = time();
  361. $order->store_id = $this->store_id;
  362. $order->user_id = $params['user_id'];
  363. $order->order_no = OrderNo::getOrderNo(OrderNo::ORDER_MALL);
  364. $order->pay_price = 0;
  365. $order->version = cyy_version();
  366. $order->order_type = 2;
  367. $order->is_offline = 1;
  368. $order->order_origin = Order::ORDER_SOURCE_MANAGE;
  369. $order->integral = json_encode(['forehead' => 0, 'forehead_integral' => 0], JSON_UNESCAPED_UNICODE);
  370. $order->discount = 10;
  371. $order->first_price = 0;
  372. $order->second_price = 0;
  373. $order->third_price = 0;
  374. }
  375. if(isset($params['mobile']) && isset($params['name'])){
  376. $order->mobile = $params['mobile'];
  377. $order->name = $params['name'];
  378. $order->book_info = json_encode([
  379. 'name' => $params['name'],
  380. 'mobile' => $params['mobile'],
  381. ]);
  382. }
  383. isset($params['remark']) && $order->remark = $params['remark'];
  384. if(!$order->save()){
  385. \Yii::error([__METHOD__, $order->attributes]);
  386. return [
  387. 'code'=>1,
  388. 'msg'=>'订单信息保存错误' . array_shift($order->getFirstErrors()),
  389. ];
  390. }
  391. $order->refresh();
  392. $order->trade_status = Order::ORDER_FLOW_NO_SEND;
  393. $order->is_pay = 1;
  394. $order->pay_time = time();
  395. if($params['md_id']){
  396. $order->md_id = $params['md_id'];
  397. }
  398. if(!$order->save()){
  399. \Yii::error([__METHOD__, $order->attributes]);
  400. return [
  401. 'code'=>1,
  402. 'msg'=>'订单信息保存错误' . array_shift($order->getFirstErrors()),
  403. ];
  404. }
  405. if(!$params['order_id']){
  406. $goods = Goods::findOne($params['goods_id']);
  407. $order_detail = new OrderDetail();
  408. $order_detail->order_id = $order->id;
  409. $order_detail->goods_id = $goods->id;
  410. $order_detail->goods_name = $goods->name;
  411. $order_detail->attr = json_encode([
  412. 'start_date' => $start_date,
  413. 'end_date' => $end_date,
  414. 'time' => $params['time'],
  415. 'date' => $params['date'],
  416. 'price' => 0,
  417. ], JSON_UNESCAPED_UNICODE);
  418. $order_detail->pic = $goods->cover_pic;
  419. $order_detail->goods_info = json_encode($goods->toArray());
  420. if(!$order_detail->save()){
  421. \Yii::error([__METHOD__, $order_detail->attributes]);
  422. return [
  423. 'code'=>1,
  424. 'msg'=>'订单详情信息保存错误' . array_shift($order_detail->getFirstErrors()),
  425. ];
  426. }
  427. }
  428. $boe = BookingOrderExt::findOne(['order_id' => $order->id]);
  429. $boe->booking_time_start = $start_date;
  430. $boe->booking_time_end = $end_date;
  431. if($params['worker_id']){
  432. $boe->setWorker($params['worker_id'], $params['worker_name']);
  433. }
  434. if(!$boe->save()){
  435. \Yii::error([__METHOD__, $boe->attributes]);
  436. return [
  437. 'code'=>1,
  438. 'msg'=>'订单预约ext信息保存错误' . array_shift($boe->getFirstErrors()),
  439. ];
  440. }
  441. return [
  442. 'code' => 0,
  443. 'msg' => '保存成功',
  444. '$order' => $order,
  445. '$order_detail' => $order_detail,
  446. '$boe' => $boe,
  447. ];
  448. }
  449. //分配订单
  450. public function orderSetWorker($params)
  451. {
  452. $store_id = $this->store_id;
  453. $order_id = $params['order_id'];
  454. $boe = BookingOrderExt::findOne(['order_id' => $order_id, 'store_id' => $store_id]);
  455. $boe->setWorker($params['worker_id'], $params['worker_name']);
  456. if(!$boe->save()){
  457. \Yii::error([__METHOD__, $boe->attributes]);
  458. return [
  459. 'code'=>1,
  460. 'msg'=>'订单预约ext信息保存错误' . array_shift($boe->getFirstErrors()),
  461. ];
  462. }
  463. return [
  464. 'code' => 0,
  465. 'msg' => '保存成功',
  466. '$boe' => $boe,
  467. ];
  468. }
  469. //确认收款
  470. public function orderIsPay($params)
  471. {
  472. $store_id = $this->store_id;
  473. $order_id = $params['order_id'];
  474. if(empty($order_id)){
  475. return [
  476. 'code' => 1,
  477. 'msg' => '参数错误1',
  478. '$order_id' => $order_id,
  479. ];
  480. }
  481. $order = Order::findOne(['id' => $order_id, 'store_id' => $store_id, 'trade_status' => Order::ORDER_FLOW_DEFAULT]);
  482. if(empty($order)){
  483. return [
  484. 'code' => 1,
  485. 'msg' => '参数错误,订单不存在或状态异常',
  486. ];
  487. }
  488. $t = \Yii::$app->db->beginTransaction();
  489. try{
  490. $order = Order::find()->where('id = :id FOR UPDATE', [':id' => $order_id])->one();
  491. if(!$order){
  492. throw new \Exception('锁失败');
  493. }
  494. $order->is_pay = 1;
  495. $order->pay_type = 3;
  496. $order->pay_time = time();
  497. $order->trade_status = Order::ORDER_FLOW_NO_SEND;
  498. $save = $order->save();
  499. if(!$save){
  500. throw new \Exception(array_shift($order->getFirstErrors()));
  501. }
  502. // 支付完成后,相关操作
  503. $form = new OrderComplete();
  504. $form->order_id = $order->id;
  505. $form->order_type = 2;
  506. $form->store_id = $store_id;
  507. $form->notify();
  508. $t->commit();
  509. return [
  510. 'code' => 0,
  511. 'msg' => '操作成功',
  512. ];
  513. } catch (\Exception $ex) {
  514. $t->rollBack();
  515. return [
  516. 'code' => 1,
  517. 'msg' => '操作失败,' . $ex->getMessage(),
  518. ];
  519. }
  520. }
  521. //确认收货
  522. public function orderConfirm($params)
  523. {
  524. $store_id = $this->store_id;
  525. $order_id = $params['order_id'];
  526. if(empty($order_id)){
  527. return [
  528. 'code' => 1,
  529. 'msg' => '参数错误1',
  530. '$order_id' => $order_id,
  531. ];
  532. }
  533. $order = Order::findOne(['id' => $order_id, 'store_id' => $store_id, 'is_pay' => 1]);
  534. if(empty($order)){
  535. return [
  536. 'code' => 1,
  537. 'msg' => '参数错误,订单不存在或订单未付款',
  538. ];
  539. }
  540. $t = \Yii::$app->db->beginTransaction();
  541. try{
  542. $order = Order::find()->where('id = :id FOR UPDATE', [':id' => $order_id])->one();
  543. if(!$order){
  544. throw new \Exception('锁失败');
  545. }
  546. $order->trade_status = Order::ORDER_FLOW_CONFIRM;
  547. $order->confirm_time = time();
  548. $save = $order->save();
  549. if(!$save){
  550. throw new \Exception(array_shift($order->getFirstErrors()));
  551. }
  552. $t->commit();
  553. return [
  554. 'code' => 0,
  555. 'msg' => '操作成功',
  556. ];
  557. } catch (\Exception $ex) {
  558. $t->rollBack();
  559. return [
  560. 'code' => 1,
  561. 'msg' => '操作失败,' . $ex->getMessage(),
  562. ];
  563. }
  564. }
  565. }