ActivityCutPriceForm.php 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059
  1. <?php
  2. /**
  3. * 重庆赤晓店信息科技有限公司
  4. * https://www.chixiaodian.com
  5. * Copyright (c) 2023 赤店商城 All rights reserved.
  6. */
  7. namespace app\modules\admin\models;
  8. use app\jobs\storeSync\DiyCommon;
  9. use app\models\Coupon;
  10. use app\models\Cat;
  11. use app\models\Goods;
  12. use app\models\GoodsCat;
  13. use app\models\ActivityCutPrice;
  14. use app\models\ActivityCutPriceBanner;
  15. use app\models\ActivityCutPriceCat;
  16. use app\models\ActivityCutPriceGoods;
  17. use app\models\ActivityCutPriceOrder;
  18. use app\models\ActivityCutPriceLog;
  19. use app\models\Store;
  20. use app\models\StoreSyncExtLog;
  21. use app\models\User;
  22. use yii\base\Model;
  23. use app\models\Option;
  24. use app\constants\OptionSetting;
  25. use app\models\SaasUser;
  26. use app\models\Order;
  27. use app\modules\client\models\v1\order\OrderSubmitPreviewForm;
  28. use app\models\Attr;
  29. use app\models\AttrGroup;
  30. class ActivityCutPriceForm extends Model
  31. {
  32. public $store_id;
  33. public $saas_id;
  34. public $user_id;
  35. public $id;
  36. public $activity_id;
  37. public $ids;
  38. public $name;
  39. public $start_time;
  40. public $end_time;
  41. public $status;
  42. public $goods_ext;
  43. public $goods_ids;
  44. public $coupon_ids;
  45. public $goods_name;
  46. public $coupon_name;
  47. public $min_price;
  48. public $limit_time;
  49. public $cut_count;
  50. public $front_num;
  51. public $first_money_min;
  52. public $first_money_max;
  53. public $last_money_min;
  54. public $last_money_max;
  55. public $buy;
  56. public $is_platform = 0;
  57. public $is_platform_audit = 0;
  58. public $store_name;
  59. public function rules()
  60. {
  61. return [
  62. [['status', 'id', 'is_platform', 'is_platform_audit'], 'integer'],
  63. [['start_time', 'end_time', 'ids', 'name', 'store_name'], 'string'],
  64. [['goods_name', 'coupon_name', 'store_id', 'goods_ids', 'goods_ext', 'coupon_ids', 'buy_limit', 'activity_id',
  65. 'min_price', 'limit_time', 'cut_count', 'front_num', 'first_money_min', 'first_money_max',
  66. 'last_money_min', 'last_money_max', 'saas_id', 'user_id', 'buy'], 'safe'],
  67. ];
  68. }
  69. public function init() {
  70. parent::init();
  71. if(empty($this->store_id)){
  72. $this->store_id = get_store_id();
  73. }
  74. }
  75. public function search ()
  76. {
  77. try {
  78. $query = ActivityCutPrice::find()->where(['is_delete' => 0, 'store_id' => get_store_id()]);
  79. if ((int)$this->status === 1) {//未开始
  80. $query->andWhere(['>' , 'start_time', time()]);
  81. }
  82. if ((int)$this->status === 2) {//进行中
  83. $query->andWhere(['AND', ['<' , 'start_time', time()], ['>' , 'end_time', time()]]);
  84. }
  85. if ((int)$this->status === 3) { //已结束
  86. $query->andWhere(['<' , 'end_time', time()]);
  87. }
  88. if (!empty($this->name)) { //名称
  89. $query->andWhere(['LIKE' , 'name', $this->name]);
  90. }
  91. if (!empty($this->start_time)) {
  92. $query->andWhere(['>' , 'end_time', strtotime($this->start_time)]);
  93. }
  94. if (!empty($this->end_time)) {
  95. $query->andWhere(['<' , 'start_time', strtotime($this->end_time)]);
  96. }
  97. $query->andWhere(['is_platform' => $this->is_platform]);
  98. $query->orderBy('id DESC');
  99. $pagination = pagination_make($query);
  100. foreach ($pagination['list'] as &$item) {
  101. $item['is_platform_audit'] = (int)$item['is_platform_audit'];
  102. $item['publish'] = $item['status'];
  103. //获取活动状态
  104. if ($item['start_time'] > time()) {
  105. $item['status'] = 1;
  106. }
  107. if ($item['start_time'] < time() && $item['end_time'] > time()) {
  108. $item['status'] = 2;
  109. }
  110. if ($item['end_time'] < time()) {
  111. $item['status'] = 3;
  112. }
  113. //格式化时间
  114. $item['start_time'] = date("Y-m-d H:i:s", $item['start_time']);
  115. $item['end_time'] = date("Y-m-d H:i:s", $item['end_time']);
  116. $item['created_at'] = date("Y-m-d H:i:s", $item['created_at']);
  117. $item['updated_at'] = date("Y-m-d H:i:s", $item['updated_at']);
  118. $userCount = ActivityCutPriceOrder::find()->where(['activity_id' => $item['id']])->andWhere(['>', 'used_order_id', 0])->groupBy(['saas_id'])->count();
  119. $item['userCount'] = $userCount;
  120. $orderCount = ActivityCutPriceOrder::find()->where(['activity_id' => $item['id']])->andWhere(['>', 'used_order_id', 0])->count();
  121. $item['orderCount'] = $orderCount;
  122. $orderSum = ActivityCutPriceOrder::find()->where(['activity_id' => $item['id']])->andWhere(['>', 'used_order_id', 0])->sum('pay_price');
  123. $item['orderSum'] = $orderSum;
  124. }
  125. return [
  126. 'code' => 0,
  127. 'msg' => 'success',
  128. 'data' => [
  129. 'data' => $pagination['list'],
  130. 'pageNo' => $pagination['pageNo'],
  131. 'totalCount' => $pagination['totalCount'],
  132. ]
  133. ];
  134. } catch (\Exception $e) {
  135. return [
  136. 'code' => 1,
  137. 'msg' => $e->getMessage()
  138. ];
  139. }
  140. }
  141. public function listSelect() {
  142. $query = ActivityCutPrice::find()->where(['is_delete' => 0]);
  143. $this->store_id && $query->andWhere(['store_id' => $this->store_id]);
  144. if($this->name){
  145. $query->andWhere(['like', 'name', $this->name]);
  146. }
  147. if (!empty($this->start_time)) {
  148. $query->andWhere(['>' , 'end_time', strtotime($this->start_time)]);
  149. }
  150. if (!empty($this->end_time)) {
  151. $query->andWhere(['<' , 'start_time', strtotime($this->end_time)]);
  152. }
  153. $query->select('id, name');
  154. $query->orderBy('id desc');
  155. $res = $query->asArray()->all();
  156. return [
  157. 'code' => 0,
  158. 'msg' => 'success',
  159. 'data' => $res,
  160. ];
  161. }
  162. public static function sortGoods($goods_ext, $goods){
  163. $res = [];
  164. foreach($goods_ext as $eitem){
  165. foreach($goods as $gitem){
  166. if($gitem['id'] == $eitem['goods_id']){
  167. $res[] = $gitem;
  168. }
  169. }
  170. }
  171. return $res;
  172. }
  173. public function getInfo()
  174. {
  175. try {
  176. $activity = ActivityCutPrice::find()->where(['id' => $this->id])->one();
  177. if ($activity) {
  178. $activity_goods = Goods::find()->where(['in', 'id', explode(',', $activity->goods_ids)])->andWhere(['is_delete' => 0])->asArray()->all();
  179. $activity['start_time'] = date("Y-m-d H:i:s", $activity['start_time']);
  180. $activity['end_time'] = date("Y-m-d H:i:s", $activity['end_time']);
  181. $goods_ext = ActivityCutPriceGoods::findAll(['activity_id' => $activity->id, 'is_delete' => 0]);
  182. $activity_goods = self::sortGoods($goods_ext, $activity_goods);
  183. }
  184. return [
  185. 'code' => 0,
  186. 'msg' => '获取成功',
  187. 'data' => [
  188. 'activity_goods' => $activity_goods ?? [],
  189. 'goods_ext' => $goods_ext ?? [],
  190. 'activity' => $activity ?: [],
  191. ]
  192. ];
  193. } catch (\Exception $e) {
  194. return [
  195. 'code' => 1,
  196. 'msg' => $e->getMessage() . $e->getFile() . $e->getLine()
  197. ];
  198. }
  199. }
  200. public function save ()
  201. {
  202. $t = \Yii::$app->db->beginTransaction();
  203. try {
  204. if (!$this->name || !$this->start_time || !$this->end_time) {
  205. throw new \Exception("请将参数填充完整");
  206. }
  207. $activity = ActivityCutPrice::findOne($this->id);
  208. if (empty($activity)) {
  209. $activity = new ActivityCutPrice();
  210. $activity->store_id = $this->store_id;
  211. }
  212. $activity->name = $this->name;
  213. $activity->start_time = strtotime($this->start_time);
  214. $activity->end_time = strtotime($this->end_time);
  215. $activity->goods_ids = $this->goods_ids;
  216. $activity->min_price = $this->min_price ?: 0;
  217. $activity->limit_time = $this->limit_time;
  218. $activity->cut_count = $this->cut_count;
  219. $activity->front_num = $this->front_num;
  220. $activity->first_money_min = $this->first_money_min;
  221. $activity->first_money_max = $this->first_money_max;
  222. $activity->last_money_min = $this->last_money_min;
  223. $activity->last_money_max = $this->last_money_max;
  224. $activity->is_platform = intval($this->is_platform);
  225. $activity->buy = $this->buy;
  226. if (!$activity->save()) {
  227. throw new \Exception(array_shift($activity->getFirstErrors()));
  228. }
  229. if(!empty($this->goods_ext)){
  230. foreach($this->goods_ext as &$item){
  231. $item['activity_id'] = $activity->id;
  232. $item['store_id'] = $this->store_id;
  233. }
  234. $result = ActivityCutPriceGoods::saveList($this->goods_ext, $activity->id, $is_platform_audit);
  235. if ($result['code'] !== 0) {
  236. throw new \Exception($result['msg']);
  237. }
  238. if ($is_platform_audit) {
  239. $activity->is_platform_audit = 0;
  240. $activity->save();
  241. }
  242. }
  243. (new DiyCommon)->JobBehaviors($this->store_id, StoreSyncExtLog::TYPE_ACTIVITY_CUT_PRICE, [$activity->id]);
  244. $t->commit();
  245. return [
  246. 'code' => 0,
  247. 'msg' => '操作成功!'
  248. ];
  249. } catch (\Exception $e) {
  250. $t->rollBack();
  251. return [
  252. 'code' => 1,
  253. 'msg' => $e->getMessage()
  254. ];
  255. }
  256. }
  257. public function del ()
  258. {
  259. try {
  260. if ($this->ids) {
  261. $ids = explode(',', $this->ids);
  262. if (count($ids) === 1) {
  263. (new DiyCommon)->JobBehaviors($this->store_id, StoreSyncExtLog::TYPE_ACTIVITY_CUT_PRICE, $ids);
  264. }
  265. ActivityCutPrice::updateAll(['is_delete' => 1], ['and', ['in', 'id', $ids], ['store_id' => $this->store_id]]);
  266. }
  267. return [
  268. 'code' => 0,
  269. 'msg' => '操作成功!'
  270. ];
  271. } catch (\Exception $e) {
  272. return [
  273. 'code' => 1,
  274. 'msg' => $e->getMessage()
  275. ];
  276. }
  277. }
  278. public function conf(){
  279. $conf = Option::get(OptionSetting::ACTIVITY_CUT_PRICE_CONF, $this->store_id, 'store')['value'];
  280. if($conf){
  281. $conf = json_decode($conf, true);
  282. }else{
  283. $conf = ['conf' => [
  284. 'rule' => '砍价活动',
  285. ]];
  286. }
  287. return [
  288. 'code'=>0,
  289. 'msg'=>'ok',
  290. 'data' => $conf,
  291. ];
  292. }
  293. public function confSave($conf){
  294. if(!is_array($conf)){
  295. $conf = json_decode($conf, true);
  296. }
  297. $data = ['conf' => $conf];
  298. Option::set(OptionSetting::ACTIVITY_CUT_PRICE_CONF, json_encode($data), $this->store_id, 'store');
  299. return [
  300. 'code'=>0,
  301. 'msg'=>'保存成功'
  302. ];
  303. }
  304. public function catSave($id = 0, $name = '', $pic_url = '', $sort = 100, $is_show = 1) {
  305. try{
  306. $model = $id ? ActivityCutPriceCat::findOne($id) : new ActivityCutPriceCat();
  307. $model->store_id = $this->store_id;
  308. $model->name = $name;
  309. $model->pic_url = $pic_url;
  310. $model->sort = $sort;
  311. $model->is_show = $is_show;
  312. $save = $model->save();
  313. if(!$save){
  314. \Yii::error([__METHOD__, $model->attributes]);
  315. throw new \Exception('操作失败,' . array_shift($model->getFirstErrors()));
  316. }
  317. return [
  318. 'code' => 0,
  319. 'msg' => '操作成功',
  320. ];
  321. }catch(\Exception $e){
  322. \Yii::error([__METHOD__, $e]);
  323. return [
  324. 'code' => 1,
  325. 'msg' => $e->getMessage(),
  326. ];
  327. }
  328. }
  329. public function catList() {
  330. $query = ActivityCutPriceCat::find()->where(['is_delete' => 0]);
  331. $this->store_id && $query->andWhere(['store_id' => $this->store_id]);
  332. if($this->name){
  333. $query->andWhere(['like', 'name', $this->name]);
  334. }
  335. if($this->status >= 0){
  336. $query->andWhere(['is_show' => $this->status]);
  337. }
  338. $query->orderBy('sort desc');
  339. $res = pagination_make($query);
  340. return [
  341. 'code' => 0,
  342. 'msg' => 'success',
  343. 'data' => $res,
  344. 'q' => $query->createCommand()->getRawSql(),
  345. ];
  346. }
  347. public function catStatus ()
  348. {
  349. try {
  350. if ($this->ids) {
  351. $ids = explode(',', $this->ids);
  352. if (in_array($this->status, [0, 1])) {
  353. ActivityCutPriceCat::updateAll(['is_show' => $this->status], ['and', ['in', 'id', $ids], ['store_id' => $this->store_id]]);
  354. }
  355. if ((int)$this->status === 2) {
  356. ActivityCutPriceCat::updateAll(['is_delete' => 1], ['and', ['in', 'id', $ids], ['store_id' => $this->store_id]]);
  357. }
  358. }
  359. return [
  360. 'code' => 0,
  361. 'msg' => '操作成功!'
  362. ];
  363. } catch (\Exception $e) {
  364. return [
  365. 'code' => 1,
  366. 'msg' => $e->getMessage()
  367. ];
  368. }
  369. }
  370. public function catInfo($id = 0) {
  371. $model = ActivityCutPriceCat::findOne($id);
  372. return [
  373. 'code' => 0,
  374. 'msg' => '操作成功',
  375. 'data' => $model,
  376. ];
  377. }
  378. public function bannerSave($id = 0, $activity_id = 0, $name = '', $pic_url = '', $url = '', $sort = 100) {
  379. try{
  380. $model = $id ? ActivityCutPriceBanner::findOne($id) : new ActivityCutPriceBanner();
  381. $model->store_id = $this->store_id;
  382. $model->activity_id = $activity_id;
  383. $model->name = $name;
  384. $model->pic_url = $pic_url;
  385. $model->url = $url;
  386. $model->sort = $sort;
  387. $save = $model->save();
  388. if(!$save){
  389. \Yii::error([__METHOD__, $model->attributes]);
  390. throw new \Exception('操作失败,' . array_shift($model->getFirstErrors()));
  391. }
  392. return [
  393. 'code' => 0,
  394. 'msg' => '操作成功',
  395. ];
  396. }catch(\Exception $e){
  397. \Yii::error([__METHOD__, $e]);
  398. return [
  399. 'code' => 1,
  400. 'msg' => $e->getMessage(),
  401. ];
  402. }
  403. }
  404. public function bannerList() {
  405. $query = ActivityCutPriceBanner::find()->where(['is_delete' => 0]);
  406. $this->store_id && $query->andWhere(['store_id' => $this->store_id]);
  407. if($this->activity_id){
  408. $query->andWhere(['activity_id' => $this->activity_id]);
  409. }
  410. if($this->name){
  411. $query->andWhere(['like', 'name', $this->name]);
  412. }
  413. $query->orderBy('sort desc');
  414. $res = pagination_make($query);
  415. return [
  416. 'code' => 0,
  417. 'msg' => 'success',
  418. 'data' => $res,
  419. ];
  420. }
  421. public function bannerDel ()
  422. {
  423. try {
  424. if ($this->ids) {
  425. $ids = explode(',', $this->ids);
  426. ActivityCutPriceBanner::updateAll(['is_delete' => 1], ['and', ['in', 'id', $ids], ['store_id' => $this->store_id]]);
  427. }
  428. return [
  429. 'code' => 0,
  430. 'msg' => '操作成功!'
  431. ];
  432. } catch (\Exception $e) {
  433. return [
  434. 'code' => 1,
  435. 'msg' => $e->getMessage()
  436. ];
  437. }
  438. }
  439. public function getGoodsAttrItem($goods_ext, $mch_list)
  440. {
  441. // var_dump($mch_list);
  442. $attr_id_list = array_column($mch_list[0]['goods_list'][0]['attr'], 'attr_id');
  443. sort($attr_id_list);
  444. $goods = Goods::findOne($goods_ext['goods_id']);
  445. if (empty($goods)) {
  446. return null;
  447. }
  448. $attr = $goods['attr'];
  449. $attr_rows = json_decode($attr, true);
  450. if (empty($attr_rows)) {
  451. return null;
  452. }
  453. foreach ($attr_rows as $i => $attr_row) {
  454. $key = [];
  455. foreach ($attr_row['attr_list'] as $j => $attr) {
  456. $key[] = $attr['attr_id'];
  457. }
  458. sort($key);
  459. if (!array_diff($attr_id_list, $key)) {
  460. if (!$attr_rows[$i]['price']) {
  461. return null;
  462. }
  463. return $attr_rows[$i];
  464. }
  465. }
  466. return null;
  467. }
  468. public function getGoodsExtAttrItem($goods_ext, $mch_list)
  469. {
  470. // var_dump($mch_list);
  471. $attr_id_list = array_column($mch_list[0]['goods_list'][0]['attr'], 'attr_id');
  472. sort($attr_id_list);
  473. $attr = $goods_ext['attr'];
  474. $attr_rows = json_decode($attr, true);
  475. if (empty($attr_rows)) {
  476. return null;
  477. }
  478. foreach ($attr_rows as $i => $attr_row) {
  479. $key = [];
  480. foreach ($attr_row['attr_list'] as $j => $attr) {
  481. $key[] = $attr['attr_id'];
  482. }
  483. sort($key);
  484. if (!array_diff($attr_id_list, $key)) {
  485. if (!$attr_rows[$i]['price']) {
  486. return null;
  487. }
  488. return $attr_rows[$i];
  489. }
  490. }
  491. return null;
  492. }
  493. //进行中的订单
  494. public static function getHasOrder($user_id = 0, $saas_id = 0, $activity_id = 0, $goods_id = 0) {
  495. $saas_user = SaasUser::findOne($saas_id);
  496. $user_id = User::findOne(['binding'=>$saas_user->mobile,'store_id'=>get_store_id(),'is_delete'=>0])->id ?: $user_id;
  497. $query = ActivityCutPriceOrder::find()->where(['is_delete' => 0]);
  498. $query->andWhere([
  499. 'user_id' => $user_id,
  500. 'saas_id' => $saas_id,
  501. 'activity_id' => $activity_id,
  502. 'goods_id' => $goods_id,
  503. ]);
  504. $payQuery = Order::find()->select('id')->where(['is_pay' => 0, 'trade_status' => Order::ORDER_FLOW_DEFAULT]);
  505. $query->andWhere([
  506. 'or',
  507. ['>', 'end_time', time()],
  508. [
  509. 'and',
  510. ['>', 'used_order_id', 0],
  511. ['used_order_id' => $payQuery],
  512. ],
  513. ]);
  514. $query->orderBy('id DESC');
  515. $order = $query->one();
  516. return $order;
  517. }
  518. public function orderCreate($user_id = 0, $saas_id = 0, $activity_id = 0, $goods_id = 0, $mch_list = '') {
  519. try{
  520. $mch_list = json_decode($mch_list, true);
  521. $activity = ActivityCutPrice::activityAt($activity_id);
  522. if(!$activity){
  523. throw new \Exception('砍价活动不存在');
  524. }
  525. $store_id = $activity['store_id'] ?:get_store_id();
  526. if (!$user_id) {
  527. $saas_user = SaasUser::findOne($saas_id);
  528. if ($saas_user) {
  529. $user = User::findOne(['binding' => $saas_user->mobile, 'store_id' => $store_id, 'is_delete' => 0]);
  530. $user_id = $user->id ?: 0;
  531. }
  532. }
  533. $goods_ext = ActivityCutPriceGoods::findOne(['activity_id' => $activity_id, 'goods_id' => $goods_id, 'is_delete' => 0]);
  534. if(!$goods_ext){
  535. throw new \Exception('砍价商品不存在');
  536. }
  537. $mchPrice = $this->getGoodsAttrItem($goods_ext, $mch_list);
  538. $mchPriceExt = $this->getGoodsExtAttrItem($goods_ext, $mch_list);
  539. // var_dump($mchPrice);die;
  540. if(!$mchPriceExt['price']){
  541. \Yii::error([__METHOD__, $activity_id, $goods_id, $mch_list, $mchPriceExt]);
  542. throw new \Exception('砍价商品价格获取失败');
  543. }
  544. $price = $mchPrice['price'];
  545. $min_price = $mchPriceExt['price'];
  546. $model = new ActivityCutPriceOrder();
  547. $model->store_id = $store_id;
  548. $model->activity_id = $activity_id;
  549. $model->user_id = $user_id;
  550. $model->saas_id = $saas_id;
  551. $model->goods_id = $goods_id;
  552. $model->activity_goods_id = $goods_ext->id;
  553. $model->goods_id = $goods_id;
  554. $model->order_mch_list = json_encode($mch_list);
  555. $model->total_price = $price;
  556. $model->pay_price = $price;
  557. $model->buy = $activity['buy'];
  558. $model->min_price = $min_price;
  559. $model->is_platform = $this->is_platform ?: 0;
  560. $end_time = time() + $activity['limit_time'] * 3600;
  561. $model->end_time = $end_time > $activity['end_time'] ? $activity['end_time'] : $end_time;
  562. $save = $model->save();
  563. if(!$save){
  564. \Yii::error([__METHOD__, $model->attributes]);
  565. throw new \Exception('操作失败,' . array_shift($model->getFirstErrors()));
  566. }
  567. return [
  568. 'code' => 0,
  569. 'msg' => '操作成功',
  570. 'data' => $model->id,
  571. ];
  572. }catch(\Exception $e){
  573. \Yii::error([__METHOD__, $e]);
  574. return [
  575. 'code' => 1,
  576. 'msg' => $e->getMessage(),
  577. ];
  578. }
  579. }
  580. public function orderList() {
  581. $query = ActivityCutPriceOrder::find()
  582. ->alias('o')
  583. ->leftJoin(['a' => ActivityCutPrice::tableName()], 'o.activity_id = a.id')
  584. ->where(['o.is_delete' => 0, 's.is_delete' => 0])
  585. ->leftJoin(['s' => Store::tableName()], 'o.store_id = s.id');
  586. // ->leftJoin(['to' => Order::tableName()],'o.id=to.activity_cut_price_order_id')
  587. // ->andWhere(['to.is_delete' => 0, 'to.user_delete' => 0]);
  588. $this->saas_id && $query->andWhere(['o.saas_id' => $this->saas_id]);
  589. $this->user_id && $query->andWhere(['o.user_id' => $this->user_id]);
  590. if($this->activity_id){
  591. $query->andWhere(['o.activity_id' => $this->activity_id]);
  592. }
  593. if ($this->is_platform) {
  594. $query->andWhere(['o.is_platform' => 1]);
  595. } else {
  596. $query->andWhere(['o.store_id' => get_store_id()]);
  597. $this->store_id && $query->andWhere(['o.store_id' => $this->store_id]);
  598. }
  599. if($this->goods_name){
  600. $goods_query = Goods::find()->select('id')->where(['like', 'name', $this->goods_name]);
  601. $query->andWhere(['o.goods_id' => $goods_query]);
  602. }
  603. if ((int)$this->status === 0) {//进行中
  604. $query->andWhere(['>' , 'o.end_time', time()]);
  605. }
  606. if ((int)$this->status === 1) { //已结束
  607. $query->andWhere(['<' , 'o.end_time', time()]);
  608. }
  609. if ((int)$this->status === 2) { //已失败
  610. $query->andWhere(['o.buy' => 0]);
  611. $query->andWhere(['<' , 'o.end_time', time()]);
  612. $query->andWhere('o.pay_price > o.min_price');
  613. }
  614. if ((int)$this->status === 10) { //待付款
  615. $payQuery = Order::find()->select('id')->where(['is_pay' => 0]);
  616. $query->andWhere(['>', 'o.used_order_id', 0]);
  617. $query->andWhere(['o.used_order_id' => $payQuery]);
  618. }
  619. if ((int)$this->status === 11) { //已付款
  620. $payQuery = Order::find()->select('id')->where(['is_pay' => 1]);
  621. $query->andWhere(['o.used_order_id' => $payQuery]);
  622. }
  623. $query->select('o.*')->orderBy('o.id desc');
  624. $res = pagination_make($query);
  625. foreach($res['list'] as &$item){
  626. $store = Store::findOne($item['store_id']);
  627. $list['store_name'] = $store->name;
  628. $list['logo'] = $store->logo ?: Option::get(OptionSetting::STORE_LOGO, $list['store_id'], 'store', '');
  629. $list['store_id'] = $store->id;
  630. $item['status'] = ActivityCutPriceOrder::getStatus($item);
  631. $goods_info = Goods::find()->where(['id' => $item['goods_id']])->select('id,name,cover_pic')->one();
  632. $goods_cat = GoodsCat::find()->alias('gc')
  633. ->leftJoin(['c' => Cat::tableName()], 'gc.cat_id=c.id')
  634. ->where([ 'gc.goods_id' => $item['goods_id'] ])
  635. ->select(['c.name'])
  636. ->asArray()
  637. ->all();
  638. $mch_list = json_decode($item['order_mch_list'], true);
  639. $attr_id_list = array_column($mch_list[0]['goods_list'][0]['attr'], 'attr_id');
  640. sort($attr_id_list);
  641. $attr_list = Attr::find()->alias('a')
  642. ->select('ag.id AS attr_group_id,ag.attr_group_name,a.id AS attr_id,a.attr_name')
  643. ->leftJoin(['ag' => AttrGroup::tableName()], 'a.attr_group_id=ag.id')
  644. ->where(['a.id' => $attr_id_list, 'ag.store_id' => $this->store_id,])
  645. ->asArray()->all();
  646. $saasUser = SaasUser::findOne($item['saas_id']);
  647. $activity = ActivityCutPrice::findOne($item['activity_id']);
  648. $item['attr_list'] = $attr_list;
  649. $item['goods_info'] = $goods_info;
  650. $item['goods_cat'] = $goods_cat;
  651. $item['saasUser'] = $saasUser;
  652. $item['activity'] = $activity;
  653. $item['activity_finished'] = $activity->end_time < time() ? 1 : 0;
  654. }
  655. return [
  656. 'code' => 0,
  657. 'msg' => 'success',
  658. 'data' => $res,
  659. 'q' => $query->createCommand()->getRawSql(),
  660. ];
  661. }
  662. //判断商城订单自动取消时是否允许取消
  663. public static function orderCanCancel($mall_order) {
  664. $res = true;
  665. $order = ActivityCutPriceOrder::findOne(['used_order_id' => $mall_order['id']]);
  666. if($order){
  667. $activity = ActivityCutPrice::findOne($order->activity_id);
  668. if($activity){
  669. //活动没结束不允许取消
  670. if($activity->end_time > time()){
  671. $res = false;
  672. }
  673. }
  674. }
  675. return $res;
  676. }
  677. //生成商城订单时回调
  678. public static function orderUsed($order_id, $mall_order) {
  679. try{
  680. $order = ActivityCutPriceOrder::findOne($order_id);
  681. if(!$order){
  682. throw new \Exception('砍价订单异常' . $order_id);
  683. }
  684. if($order['used_order_id']){
  685. throw new \Exception('砍价订单已被使用' . $order['used_order_id']);
  686. }
  687. if($order['user_id'] != $mall_order['user_id']){
  688. throw new \Exception('砍价订单用户异常' . $order['user_id'] . $order['saas_id'] . $mall_order['user_id'] . $mall_order['saas_id']);
  689. }
  690. $activity = ActivityCutPrice::findOne($order['activity_id']);
  691. if($activity['end_time'] <= time()){
  692. throw new \Exception('已过砍价活动截止时间');
  693. }
  694. if ($order['buy'] == 0 && $order['pay_price'] > $order['min_price']) {
  695. throw new \Exception('砍价失败,没有砍到最低价');
  696. }
  697. $order->used_order_id = $mall_order->id;
  698. if($order->end_time > time()){
  699. $order->end_time = time();
  700. }
  701. $save = $order->save();
  702. if(!$save){
  703. \Yii::error([__METHOD__, $order->attributes]);
  704. throw new \Exception('操作失败,' . array_shift($order->getFirstErrors()));
  705. }
  706. //减活动库存
  707. $goods_ext = ActivityCutPriceGoods::findOne($order->activity_goods_id);
  708. if(!$goods_ext){
  709. \Yii::error([__METHOD__, $order->attributes]);
  710. throw new \Exception('砍价商品信息不存在'.$order->activity_goods_id);
  711. }
  712. $mch_list = json_decode($order->order_mch_list, true);
  713. $attr = array_column($mch_list[0]['goods_list'][0]['attr'], 'attr_id');
  714. sort($attr);
  715. $ext_attrs = json_decode($goods_ext['attr'], true);
  716. foreach ($ext_attrs as &$ext_attr) {
  717. $ext_attr_id = array_column($ext_attr['attr_list'], 'attr_id');
  718. if (empty(array_diff($ext_attr_id, $attr))) {
  719. if($ext_attr['num'] < 1){
  720. throw new \Exception('砍价商品库存不足'.$ext_attr['num']);
  721. }
  722. $ext_attr['num']--;
  723. }
  724. }
  725. $goods_ext->attr = json_encode($ext_attrs);
  726. $save = $goods_ext->save();
  727. if(!$save){
  728. \Yii::error([__METHOD__, $goods_ext->attributes]);
  729. throw new \Exception('操作失败,' . array_shift($goods_ext->getFirstErrors()));
  730. }
  731. return [
  732. 'code' => 0,
  733. 'msg' => '操作成功',
  734. ];
  735. }catch(\Exception $e){
  736. \Yii::error([__METHOD__, $e]);
  737. return [
  738. 'code' => 1,
  739. 'msg' => $e->getMessage(),
  740. ];
  741. }
  742. }
  743. public function orderDel ()
  744. {
  745. try {
  746. if ($this->ids) {
  747. $ids = explode(',', $this->ids);
  748. ActivityCutPriceOrder::updateAll(['is_delete' => 1], ['and', ['in', 'id', $ids], ['store_id' => $this->store_id]]);
  749. }
  750. return [
  751. 'code' => 0,
  752. 'msg' => '操作成功!'
  753. ];
  754. } catch (\Exception $e) {
  755. return [
  756. 'code' => 1,
  757. 'msg' => $e->getMessage()
  758. ];
  759. }
  760. }
  761. //帮砍
  762. public function logSave($user_id = 0, $saas_id = 0, $order_id = 0) {
  763. try{
  764. $has = ActivityCutPriceLog::findOne([
  765. 'order_id' => $order_id,
  766. 'saas_id' => $saas_id,
  767. ]);
  768. if($has){
  769. throw new \Exception('已经砍过');
  770. }
  771. $order = ActivityCutPriceOrder::findOne(['id' => $order_id, 'is_delete' => 0]);
  772. if(!$order){
  773. throw new \Exception('订单异常');
  774. }
  775. if($order['used_order_id']){
  776. throw new \Exception('砍价已转订单'.$order['used_order_id']);
  777. }
  778. $activity = ActivityCutPrice::findOne($order['activity_id']);
  779. if($activity['end_time'] <= time()){
  780. throw new \Exception('已过砍价活动截止时间');
  781. }
  782. if($order['end_time'] <= time()){
  783. throw new \Exception('已过砍价商品截止时间');
  784. }
  785. if($order['pay_price'] <= $order['min_price']){
  786. throw new \Exception('砍价已到最底价');
  787. }
  788. $count = ActivityCutPriceLog::find()->where(['order_id' => $order_id])->count();
  789. if($activity['cut_count'] && $count >= $activity['cut_count']){
  790. throw new \Exception('帮砍人数已达上限');
  791. }
  792. $cut_price = 0;
  793. if($count < $activity['front_num']){
  794. $cut_price = sprintf('%.2f', $activity['first_money_min'] + mt_rand()/mt_getrandmax() * ($activity['first_money_max']-$activity['first_money_min']));
  795. // \Yii::error([__METHOD__, $cut_price, mt_rand()/mt_getrandmax(), $activity['first_money_min'], $activity['first_money_max']]);
  796. }else{
  797. $cut_price = sprintf('%.2f', $activity['last_money_min'] + mt_rand()/mt_getrandmax() * ($activity['last_money_max']-$activity['last_money_min']));
  798. // \Yii::error([__METHOD__, $cut_price, mt_rand()/mt_getrandmax(), $activity['last_money_min'], $activity['last_money_max']]);
  799. }
  800. if($order['pay_price'] - $cut_price <= $order['min_price']){
  801. $cut_price = $order['pay_price'] - $order['min_price'];
  802. $order->end_time = time();
  803. // \Yii::error([__METHOD__, $cut_price]);
  804. }
  805. $model = new ActivityCutPriceLog();
  806. $model->store_id = $this->store_id;
  807. $model->order_id = $order_id;
  808. $model->user_id = $user_id;
  809. $model->saas_id = $saas_id;
  810. $model->cut_price = $cut_price;
  811. $save = $model->save();
  812. if(!$save){
  813. \Yii::error([__METHOD__, $model->attributes]);
  814. throw new \Exception('操作失败,' . array_shift($model->getFirstErrors()));
  815. }
  816. $order->pay_price -= $cut_price;
  817. $save = $order->save();
  818. if(!$save){
  819. \Yii::error([__METHOD__, $order->attributes]);
  820. throw new \Exception('操作失败,' . array_shift($order->getFirstErrors()));
  821. }
  822. return [
  823. 'code' => 0,
  824. 'msg' => '操作成功',
  825. 'data' => $model,
  826. ];
  827. }catch(\Exception $e){
  828. \Yii::error([__METHOD__, $e]);
  829. return [
  830. 'code' => 1,
  831. 'msg' => $e->getMessage(),
  832. ];
  833. }
  834. }
  835. /**
  836. * 审核列表
  837. */
  838. public function auditList() {
  839. try {
  840. $query = ActivityCutPrice::find()->alias('a')->where(['a.is_delete' => 0, 'a.is_platform' => 1, 's.is_delete' => 0]);
  841. $query->leftJoin(['s' => Store::tableName()], 's.id = a.store_id');
  842. if (intval($this->status) === 1) {//未开始
  843. $query->andWhere(['AND', ['>' , 'a.start_time', time()], ['a.status' => 1]]);
  844. }
  845. if (intval($this->status) === 2) {//进行中
  846. $query->andWhere(['AND', ['<' , 'a.start_time', time()], ['>' , 'a.end_time', time()], ['a.status' => 1]]);
  847. }
  848. if (intval($this->status) === 3) { //已结束
  849. $query->andWhere(['AND', ['<' , 'a.end_time', time()], ['a.status' => 1]]);
  850. }
  851. if (intval($this->status) === 4) { //已终止
  852. $query->andWhere(['a.status' => 0]);
  853. }
  854. if ($this->is_platform_audit > -1 && $this->is_platform_audit !== null) {
  855. $query->andWhere(['a.is_platform_audit' => $this->is_platform_audit]);
  856. }
  857. if (!empty($this->name)) { //名称
  858. $query->andWhere(['LIKE' , 'a.name', $this->name]);
  859. }
  860. if (!empty($this->store_name)) { //名称
  861. $query->andWhere(['LIKE' , 's.name', $this->store_name]);
  862. }
  863. //只有平台运营的商城或者单店铺的无独立小程序才展示商盟的营销活动
  864. if (\Yii::$app->prod_is_dandianpu()) {
  865. $store_id = Option::find()->where(['group' => 'store', 'name' => 'self_mini'])->select('store_id')->column();
  866. $query->andWhere(['NOT IN', 's.id', $store_id]);
  867. } else {
  868. $query->andWhere(['s.business_model' => 2]);
  869. }
  870. if (!empty($this->start_time) && !empty($this->end_time)) { //时间筛选
  871. $query->andWhere(['OR',
  872. ['AND',
  873. ['<=' , 'a.start_time', strtotime($this->start_time)],
  874. ['>=' , 'a.end_time',strtotime($this->end_time)]
  875. ],
  876. ['AND',
  877. ['<=' , 'a.start_time', strtotime($this->start_time)],
  878. ['<=' , 'a.end_time',strtotime($this->end_time)],
  879. ['>=' , 'a.end_time',strtotime($this->start_time)]
  880. ],
  881. ['AND',
  882. ['>=' , 'a.start_time', strtotime($this->start_time)],
  883. ['<=' , 'a.end_time',strtotime($this->end_time)]
  884. ],
  885. ['AND',
  886. ['>=' , 'a.start_time', strtotime($this->start_time)],
  887. ['>=' , 'a.end_time',strtotime($this->end_time)],
  888. ['<=' , 'a.start_time',strtotime($this->end_time)]
  889. ],
  890. ]);
  891. }
  892. $query->select('a.*, s.name store_name, s.logo, s.id store_id')->orderBy('a.created_at desc');
  893. $pagination = pagination_make($query);
  894. foreach ($pagination['list'] as &$item) {
  895. $item['logo'] = $item['logo'] ?: Option::get(OptionSetting::STORE_LOGO, $item['store_id'], 'store', '')['value'];
  896. //获取活动状态
  897. if (intval($item['status']) === 1) {
  898. if ($item['start_time'] > time()) {
  899. $item['status'] = 1;
  900. }
  901. if ($item['start_time'] < time() && $item['end_time'] > time()) {
  902. $item['status'] = 2;
  903. }
  904. if ($item['end_time'] < time()) {
  905. $item['status'] = 3;
  906. }
  907. } else {
  908. $item['status'] = 4;
  909. }
  910. $item['is_platform_audit'] = (int)$item['is_platform_audit'];
  911. $item['publish'] = $item['status'];
  912. //格式化时间
  913. $item['start_time'] = date("Y-m-d H:i:s", $item['start_time']);
  914. $item['end_time'] = date("Y-m-d H:i:s", $item['end_time']);
  915. $item['created_at'] = date("Y-m-d H:i:s", $item['created_at']);
  916. $item['updated_at'] = date("Y-m-d H:i:s", $item['updated_at']);
  917. $userCount = ActivityCutPriceOrder::find()->where(['activity_id' => $item['id']])->andWhere(['>', 'used_order_id', 0])->groupBy(['saas_id'])->count();
  918. $item['userCount'] = $userCount;
  919. $orderCount = ActivityCutPriceOrder::find()->where(['activity_id' => $item['id']])->andWhere(['>', 'used_order_id', 0])->count();
  920. $item['orderCount'] = $orderCount;
  921. $orderSum = ActivityCutPriceOrder::find()->where(['activity_id' => $item['id']])->andWhere(['>', 'used_order_id', 0])->sum('pay_price');
  922. $item['orderSum'] = $orderSum;
  923. }
  924. return [
  925. 'code' => 0,
  926. 'msg' => 'success',
  927. 'data' => [
  928. 'data' => $pagination['list'],
  929. 'pageNo' => $pagination['pageNo'],
  930. 'totalCount' => $pagination['totalCount'],
  931. ]
  932. ];
  933. } catch (\Exception $e) {
  934. return [
  935. 'code' => 1,
  936. 'msg' => $e->getMessage()
  937. ];
  938. }
  939. }
  940. /**
  941. * 处理审核
  942. */
  943. public function auditHandle() {
  944. try {
  945. $id = $this->id;
  946. $status = $this->status;
  947. $cut_activity = ActivityCutPrice::findOne(['id' => $id, 'is_platform' => 1, 'is_delete' => 0]);
  948. if (!$cut_activity) {
  949. throw new \Exception('活动不存在');
  950. }
  951. if (in_array($status, [1, 2])) {
  952. if (intval($cut_activity->is_platform_audit) !== 0) {
  953. throw new \Exception('活动已经审核');
  954. }
  955. $cut_activity->is_platform_audit = $status;
  956. }
  957. if (intval($status) === 3) {
  958. $cut_activity->is_delete = 1;
  959. }
  960. if (in_array($status, [4, 5])) {
  961. $cut_activity->status = intval($status - 4);
  962. }
  963. if (!$cut_activity->save()) {
  964. throw new \Exception(json_encode($cut_activity->errors, JSON_UNESCAPED_UNICODE));
  965. }
  966. return [
  967. 'code' => 0,
  968. 'msg' => '操作成功'
  969. ];
  970. } catch (\Exception $e) {
  971. return [
  972. 'code' => 1,
  973. 'msg' => $e->getMessage()
  974. ];
  975. }
  976. }
  977. }