MdGroupActivitiesForm.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. <?php
  2. /**
  3. * MdGroupActivitiesForm.php
  4. * todo 文件描述
  5. * Created on 2024/3/19 13:34
  6. * @author: hankaige
  7. */
  8. namespace app\modules\admin\models;
  9. use app\jobs\MdGroupActivitiesJob;
  10. use app\models\DeliveryRules;
  11. use app\models\Goods;
  12. use app\models\MdGroupActivities;
  13. use app\models\MdGroupActivitiesGoods;
  14. use app\models\Order;
  15. use yii\base\Model;
  16. use yii\helpers\ArrayHelper;
  17. use yii\helpers\Json;
  18. class MdGroupActivitiesForm extends Model
  19. {
  20. public $store_id;
  21. public $id = 0;
  22. public $name;
  23. public $start_time;
  24. public $end_time;
  25. public $type = 0;
  26. public $rules = 0;
  27. public $status = 1;
  28. public $goods;
  29. public $ids;
  30. public function rules(): array
  31. {
  32. return [
  33. [
  34. [
  35. 'id',
  36. 'status',
  37. 'type',
  38. 'rules',
  39. 'status'
  40. ],
  41. 'integer'
  42. ],
  43. [
  44. [
  45. 'name',
  46. 'start_time',
  47. 'end_time',
  48. ],
  49. 'string'
  50. ],
  51. [
  52. 'goods',
  53. 'safe'
  54. ],
  55. [
  56. 'start_time',
  57. 'compare',
  58. 'compareAttribute' => 'end_time',
  59. 'operator' => '<'
  60. ],
  61. [
  62. 'id',
  63. 'required',
  64. 'on' => [
  65. 'item',
  66. 'status'
  67. ]
  68. ],
  69. ['ids','string','on'=>'del'],
  70. ['ids','required','on'=>'del'],
  71. [
  72. [
  73. 'name',
  74. 'start_time',
  75. 'end_time',
  76. 'type',
  77. 'rules',
  78. 'goods'
  79. ],
  80. 'required',
  81. 'on' => ['create']
  82. ],
  83. ];
  84. }
  85. /**
  86. * 获取活动列表
  87. * @return array
  88. * @author: hankaige
  89. * @Time: 2024/3/19 13:48
  90. */
  91. public function list(): array
  92. {
  93. $query = MdGroupActivities::find()->where([
  94. 'store_id' => $this->store_id,
  95. 'is_delete' => 0
  96. ]);
  97. if (!empty($this->start_time)) {
  98. $query->andWhere([
  99. '<=',
  100. 'start_time',
  101. strtotime($this->start_time)
  102. ]);
  103. }
  104. if (!empty($this->end_time)) {
  105. $query->andWhere([
  106. '>=',
  107. 'end_time',
  108. strtotime($this->end_time)
  109. ]);
  110. }
  111. if (!empty($this->name)) {
  112. $query->andWhere([
  113. 'like',
  114. 'name',
  115. $this->name
  116. ]);
  117. }
  118. switch ($this->status) {
  119. case 1:
  120. $query->andWhere([
  121. '>=',
  122. 'start_time',
  123. time()
  124. ]);
  125. break;
  126. case 2:
  127. $query->andWhere([
  128. 'and',
  129. [
  130. '<=',
  131. 'start_time',
  132. time()
  133. ],
  134. [
  135. '>=',
  136. 'end_time',
  137. time()
  138. ]
  139. ]);
  140. break;
  141. case 3:
  142. $query->andWhere([
  143. '<=',
  144. 'end_time',
  145. time()
  146. ]);
  147. break;
  148. default:
  149. break;
  150. }
  151. $result = pagination_make($query, FALSE, 'created_at DESC');
  152. foreach ($result['list'] as &$item) {
  153. $temp = $item;
  154. $item = ArrayHelper::toArray($item);
  155. $item['start_time'] = date('Y-m-d H:i:s', $item['start_time']);
  156. $item['end_time'] = date('Y-m-d H:i:s', $item['end_time']);
  157. // 商品数量
  158. $item['goods_number'] = count($temp->goods);
  159. // 支付金额
  160. $item['order_price'] = Order::find()->where(['md_group_activities_id'=>$temp['id'],'is_pay'=>1])->andWhere(['!=','trade_status',1])->sum('pay_price') ?? 0;
  161. // 订单数量
  162. $item['order_number'] = Order::find()->where(['md_group_activities_id'=>$temp['id'],'is_pay'=>1])->andWhere(['!=','trade_status',1])->count() ?? 0;
  163. $item['activity_status'] = $temp->activityStatus;
  164. }
  165. return [
  166. 'code' => 0,
  167. 'data' => $result
  168. ];
  169. }
  170. /**
  171. * 创建一个活动
  172. * @return array
  173. * @author: hankaige
  174. * @Time: 2024/3/19 14:52
  175. */
  176. public function createItem(): array
  177. {
  178. // 验证数据
  179. if (!$this->validate()) {
  180. return [
  181. 'code' => 1,
  182. 'msg' => $this->getErrorSummary(FALSE)[0]
  183. ];
  184. }
  185. $t = \Yii::$app->db->beginTransaction();
  186. try {
  187. if ($this->id == 0) {
  188. $model = new MdGroupActivities();
  189. } else {
  190. $model = MdGroupActivities::findOne($this->id);
  191. }
  192. $model->name = $this->name;
  193. $model->store_id = $this->store_id;
  194. $model->start_time = strtotime($this->start_time);
  195. $model->end_time = strtotime($this->end_time);
  196. $model->type = $this->type;
  197. $model->rules = $this->rules;
  198. $model->status = $this->status;
  199. // 存在已添加过的消息队列 就先删除消息队列
  200. if($model->jobs_id){
  201. \Yii::$app->queue->remove($model->jobs_id);
  202. }
  203. // 重新添加消息队列 延迟时间为 活动结束时间 - 当前时间
  204. $model->jobs_id = queue_push(new MdGroupActivitiesJob(['activity_id' => $model->id]), $this->end_time - time());
  205. if (!$model->save()) {
  206. $t->rollBack();
  207. return [
  208. 'code' => 1,
  209. 'msg' => $model->getErrors()
  210. ];
  211. }
  212. // 先删除之前的活动商品记录
  213. MdGroupActivitiesGoods::updateAll(['is_delete' => 1], [
  214. 'activities_id' => $model->id,
  215. 'is_delete' => 0
  216. ]);
  217. // 处理之前存在的活动商品
  218. $goodsArray = [];
  219. $field = [
  220. 'activities_id',
  221. 'goods_id',
  222. 'use_attr',
  223. 'attr',
  224. 'price',
  225. 'sale_num',
  226. 'created_at',
  227. 'updated_at',
  228. 'is_delete'
  229. ];
  230. foreach ($this->goods as $item) {
  231. $goods = Goods::find()->where([
  232. 'id' => $item['id'],
  233. 'is_delete' => 0,
  234. 'status' => 1
  235. ])->one();
  236. if ((int)$goods->use_attr === 1 && $item['attr']) {
  237. foreach ($item['attr'] as $value) {
  238. if (!isset($value['attr_list']) || !isset($value['group_price'])) {
  239. throw new \Exception("保存失败, 商品" . $goods->name . '规格参数错误');
  240. }
  241. if ($value['group_price'] > $value['price']) {
  242. throw new \Exception("保存失败, 商品" . $goods->name . '团购价需小于售价');
  243. }
  244. }
  245. $activityPrice = $item['attr'][0]['group_price'];
  246. $activityAttr = json_encode($item['attr']);
  247. } else {
  248. $attr = json_decode($goods->attr, TRUE);
  249. $attr[0]['group_price'] = $activityPrice = (float)$item['group_price'];
  250. $activityAttr = json_encode($attr);
  251. if ($activityPrice > $goods->price) {
  252. throw new \Exception("保存失败, 商品" . $goods->name . '团购价需小于售价');
  253. }
  254. }
  255. $goodsItem = [
  256. $model->id,
  257. $item['id'],
  258. $item['use_attr'],
  259. $activityAttr,
  260. $activityPrice,
  261. $item['sale_num'],
  262. time(),
  263. 0,
  264. 0
  265. ];
  266. $goodsArray[] = $goodsItem;
  267. }
  268. // 执行批量插入
  269. $res = \Yii::$app->db->createCommand()->batchInsert(MdGroupActivitiesGoods::tableName(), $field, $goodsArray)->execute();
  270. if ($res <= 0) {
  271. $t->rollBack();
  272. return [
  273. 'code' => 1,
  274. 'msg' => '插入活动商品失败'
  275. ];
  276. }
  277. $t->commit();
  278. return [
  279. 'code' => 0,
  280. 'msg' => '活动创建成功'
  281. ];
  282. } catch (\Throwable $e) {
  283. $t->rollBack();
  284. return [
  285. 'code' => 1,
  286. 'msg' => $e->getMessage()
  287. ];
  288. }
  289. }
  290. /**
  291. * 获取一个活动详情
  292. * @return array
  293. * @author: hankaige
  294. * @Time: 2024/3/19 14:56
  295. */
  296. public function item(): array
  297. {
  298. if (!$this->validate()) {
  299. return [
  300. 'code' => 1,
  301. 'msg' => $this->getErrorSummary(FALSE)[0]
  302. ];
  303. }
  304. $model = MdGroupActivities::find()->where([
  305. 'id' => $this->id,
  306. 'is_delete' => 0
  307. ])->one();
  308. if (empty($model)) {
  309. $model = new MdGroupActivities();
  310. } else {
  311. $model['start_time'] = date('Y-m-d H:i:s', $model['start_time']);
  312. $model['end_time'] = date('Y-m-d H:i:s', $model['end_time']);
  313. }
  314. $activityGoods = [];
  315. if (!empty($model->goods)) {
  316. foreach ($model->goods as $value) {
  317. // 如果没有设置规格图片 规格字段没有图片的时候
  318. $activityGoods[] = [
  319. 'id' => $value->goods_id,
  320. 'name' => $value->goods->name,
  321. 'cover_pic' => $value->goods->cover_pic,
  322. 'attr' => Json::decode($value->attr, TRUE),
  323. 'use_attr' => (string)$value->goods->use_attr,
  324. 'price' => $value->goods->price,
  325. 'goods_num' => $value->goods->goods_num,
  326. 'sale_num' => $value->sale_num,
  327. 'group_price' => $value->price
  328. ];
  329. }
  330. }
  331. $model = ArrayHelper::toArray($model);
  332. $model['goods'] = $activityGoods;
  333. return [
  334. 'code' => 0,
  335. 'data' => $model
  336. ];
  337. }
  338. /**
  339. * 删除活动
  340. * @return array
  341. * @author: hankaige
  342. * @Time: 2024/3/19 15:19
  343. */
  344. public function del(): array
  345. {
  346. if (!$this->validate()) {
  347. return [
  348. 'code' => 1,
  349. 'msg' => $this->getErrorSummary(FALSE)[0]
  350. ];
  351. }
  352. $list = MdGroupActivities::find()->where([
  353. 'id' => explode(',',$this->ids),
  354. 'is_delete' => 0
  355. ])->all();
  356. if (count($list) <= 0) {
  357. return [
  358. 'code' => 1,
  359. 'msg' => '选择要删除的活动'
  360. ];
  361. }
  362. $error = 0;
  363. foreach ($list as $item) {
  364. if (time() < $item->start_time || time() > $item->end_time) {
  365. $item->is_delete = 1;
  366. $item->save();
  367. // 删除活动商品
  368. MdGroupActivitiesGoods::updateAll(['is_delete' => 1], ['activities_id' => $item->id]);
  369. } else {
  370. $error++;
  371. }
  372. }
  373. if ($error > 0) {
  374. return [
  375. 'code' => 1,
  376. 'msg' => '存在' . $error . '个进进行中的活动',
  377. ];
  378. } else {
  379. return [
  380. 'code' => 0,
  381. 'msg' => '操作成功'
  382. ];
  383. }
  384. }
  385. // diy 获取活动列表
  386. public function diyGetActivitiesList()
  387. {
  388. $list = MdGroupActivities::find()->where(['store_id'=>$this->store_id,'is_delete'=>0])->andWhere(['and',['<=','start_time',time()],['>=','end_time',time()]])->all();
  389. foreach($list as &$item){
  390. $goodsItem = $this->getGoodsList($item);
  391. $item = ArrayHelper::toArray($item);
  392. $item['goods_list'] = $goodsItem;
  393. }
  394. return ['code'=>0,'data'=>[
  395. 'list'=>$list
  396. ]];
  397. }
  398. // 通过获取获取活动商品信息
  399. public function getGoodsListByActivity()
  400. {
  401. if(empty($this->id)){
  402. return ['code'=>1,'msg'=>'活动ID不能为空'];
  403. }
  404. $activity = MdGroupActivities::findOne($this->id);
  405. $goodslist = $this->getGoodsList($activity);
  406. return [
  407. 'code'=>0,
  408. 'data' => [
  409. 'data' => $goodslist
  410. ]
  411. ];
  412. }
  413. protected function getGoodsList($activity)
  414. {
  415. $goodsItem = [];
  416. foreach($activity->goods as $value){
  417. $delivery_rules = DeliveryRules::find()->where(['id' => $value->goods->delivery_rules_id, 'is_delete' => 0, 'store_id' => get_store_id()])->select('type, times, days')->asArray()->one();
  418. if ($delivery_rules) {
  419. $delivery_rules['times'] = (int)$delivery_rules['type'] === 1 ? '' : date("m月d日 H:i:s", $delivery_rules['times']);
  420. }
  421. $goodsItem[] = [
  422. 'cover_pic' => $value->goods->cover_pic,
  423. 'name' => $value->goods->name,
  424. 'original_price' => $value->goods->original_price,
  425. 'price' => $value->price,
  426. 'virtual_sales' => $value->sale_num,
  427. 'delivery_rules' => $delivery_rules ?: null
  428. ];
  429. }
  430. return $goodsItem;
  431. }
  432. }