AdoptGoodsForm.php 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  1. <?php
  2. /**
  3. * 重庆赤晓店信息科技有限公司
  4. * https://www.chixiaodian.com
  5. * Copyright (c) 2023 赤店商城 All rights reserved.
  6. */
  7. namespace app\plugins\adopt\models\client;
  8. use app\models\Address;
  9. use app\plugins\adopt\models\AdoptGoodsDevice;
  10. use app\models\Coupon;
  11. use app\models\GoodsBook;
  12. use app\models\GoodsCat;
  13. use app\models\GoodsFullMinus;
  14. use app\models\MchGoodsCat;
  15. use app\models\MdGoods;
  16. use app\models\Option;
  17. use app\models\VerifyCard;
  18. use app\models\Favorite;
  19. use app\models\Goods;
  20. use app\models\GoodsPic;
  21. use app\models\Order;
  22. use app\models\PostageRules;
  23. use app\models\Shop;
  24. use app\models\TerritorialLimitation;
  25. use app\modules\client\models\v1\common\CommonGoods;
  26. use app\modules\client\models\v1\diy\GetInfo;
  27. use app\modules\client\models\v1\mch\ShopDataForm;
  28. use app\plugins\adopt\models\AdoptGoods;
  29. use app\utils\Tools;
  30. use yii\base\Model;
  31. use yii\helpers\Json;
  32. class AdoptGoodsForm extends Model
  33. {
  34. public $id;
  35. public $user_id;
  36. public $store_id;
  37. public $mch_id;
  38. public $shop_id;
  39. public $address_id;
  40. public $verify_card_id;
  41. public function rules()
  42. {
  43. return [
  44. [['id'], 'required'],
  45. [['mch_id', 'shop_id', 'address_id'], 'integer'],
  46. [['user_id'], 'safe'],
  47. ];
  48. }
  49. /**
  50. * 排序类型$sort 1--综合排序 2--销量排序
  51. */
  52. public function search()
  53. {
  54. if (!$this->validate()) {
  55. return $this->getErrorSummary(false)[0];
  56. }
  57. $goods = Goods::findOne([
  58. 'id' => $this->id,
  59. 'is_delete' => 0,
  60. 'status' => 1,
  61. 'store_id' => $this->store_id,
  62. 'product_type' => Goods::GOODS_TYPE_ADOPT,
  63. ]);
  64. $verify_card = [];
  65. if (!empty($goods->verify_card_id)) {
  66. $ids = explode(',', $goods->verify_card_id);
  67. $verify_card = Tools::getVerifyList($ids);
  68. } else {
  69. $verify_card = [];
  70. }
  71. if (get_md_id()) {
  72. $md_goods = MdGoods::findOne(['md_id' => get_md_id(), 'goods_id' => $this->id]);
  73. if ($md_goods) {
  74. if ($md_goods->status == 0) {
  75. return [
  76. 'code' => 1,
  77. 'msg' => '商品已下架'
  78. ];
  79. }
  80. } else {
  81. if (!$goods) {
  82. return [
  83. 'code' => 1,
  84. 'msg' => '商品已下架'
  85. ];
  86. }
  87. }
  88. } else {
  89. if (!$goods) {
  90. return [
  91. 'code' => 1,
  92. 'msg' => '商品已下架'
  93. ];
  94. }
  95. }
  96. $mch = null;
  97. if ($goods->mch_id) {
  98. $mch = $this->getMch($goods);
  99. if (!$mch) {
  100. return [
  101. 'code' => 1,
  102. 'msg' => '店铺已经打烊了哦~'
  103. ];
  104. }
  105. }
  106. $pic_list = GoodsPic::find()->select('pic_url')->where(['goods_id' => $goods->id, 'is_delete' => 0])->asArray()->all();
  107. $is_favorite = 0;
  108. if ($this->user_id) {
  109. $exist_favorite = Favorite::find()->where(['user_id' => $this->user_id, 'goods_id' => $goods->id, 'is_delete' => 0])->exists();
  110. if ($exist_favorite) {
  111. $is_favorite = 1;
  112. }
  113. }
  114. $service_list = explode(',', $goods->service);
  115. // 默认商品服务
  116. if (!$goods->service) {
  117. $option = Option::get('good_services', $this->store_id, 'admin', []);
  118. foreach ($option as $item) {
  119. if (!empty($item['is_default'])) {
  120. $service_list = explode(',', $item['service']);
  121. break;
  122. }
  123. }
  124. }
  125. $new_service_list = [];
  126. if (is_array($service_list)) {
  127. foreach ($service_list as $item) {
  128. $item = trim($item);
  129. if ($item) {
  130. $new_service_list[] = $item;
  131. }
  132. }
  133. }
  134. // 门店逻辑
  135. $is_md = false;
  136. if (get_md_id()) {
  137. $md_goods = MdGoods::findOne(['goods_id' => $goods->id, 'md_id' => get_md_id()]);
  138. if ($md_goods) {
  139. $is_md = true;
  140. }
  141. }
  142. $new_price = $is_md ? $md_goods->price : $goods->price;
  143. $price_attr = $is_md ? Json::decode($md_goods->attr) : Json::decode($goods->attr);
  144. $price = [];
  145. if (is_array($price_attr)) {
  146. foreach ($price_attr as $v) {
  147. if (is_object($v) && $v->price > 0) {
  148. $price[] = $v->price;
  149. } else {
  150. $price[] = floatval($new_price);
  151. }
  152. }
  153. } else {
  154. $price = [$goods->price];
  155. }
  156. $res_url = GetInfo::getVideoInfo($goods->video_url);
  157. $goods->video_url = $res_url['url'];
  158. if ($goods->is_negotiable) {
  159. $min_price = Goods::GOODS_NEGOTIABLE;
  160. } else {
  161. $min_price = sprintf('%.2f', min($price));
  162. }
  163. $res = CommonGoods::getMMPrice([
  164. 'attr' => $is_md ? $md_goods->attr : $goods->attr,
  165. 'attr_setting_type' => $goods->attr_setting_type,
  166. 'share_type' => $goods->share_type,
  167. 'share_commission_first' => $goods->share_commission_first,
  168. 'price' => $new_price,
  169. 'individual_share' => $goods->individual_share,
  170. 'mch_id' => $goods->mch_id,
  171. 'is_level' => $goods->is_level,
  172. 'use_attr' => $goods->use_attr,
  173. ]);
  174. $attr = $price_attr;
  175. $goodsPrice = $new_price;
  176. $isMemberPrice = false;
  177. if ($res['user_is_member'] === true && count($attr) === 1 && $attr[0]['attr_list'][0]['attr_name'] == '默认') {
  178. $goodsPrice = $res['min_member_price'] ? $res['min_member_price'] : $new_price;
  179. $isMemberPrice = true;
  180. }
  181. $GoodsFullMinus = GoodsFullMinus::find()
  182. ->select('*')
  183. ->where(['store_id' => $this->store_id, 'goods_id' => $goods->id])
  184. ->orderBy('full_minus_num ASC')->asArray()->all();
  185. $adopt_goods = AdoptGoods::findOne([
  186. 'goods_id' => $this->id,
  187. 'is_delete' => 0,
  188. 'store_id' => $this->store_id,
  189. ]);
  190. $device_id = AdoptGoodsDevice::find()->where(['goods_id'=>$goods['id'],'is_delete'=>0])->select('device_id')->column();
  191. $data = [
  192. 'id' => $goods->id,
  193. 'status' => $goods->status,
  194. 'pic_list' => $pic_list,
  195. 'attr' => $is_md ? $md_goods->attr : $goods->attr,
  196. 'cover_pic' => $goods->cover_pic,
  197. 'is_negotiable' => $goods->is_negotiable,
  198. 'max_price' => sprintf('%.2f', max($price)),
  199. 'min_price' => $min_price,
  200. 'name' => $goods->name,
  201. 'cat_id' => $goods->cat_id,
  202. 'price' => sprintf('%.2f', $goodsPrice),
  203. 'detail' => $goods->detail,
  204. 'sales' => $goods->getSalesVolume() + ($is_md ? $md_goods->virtual_sales : $goods->virtual_sales),
  205. 'attr_group_list' => $goods->getAttrGroupList(),
  206. 'num' => $goods->getNum(),
  207. 'is_favorite' => $is_favorite,
  208. 'service_list' => $new_service_list,
  209. 'original_price' => sprintf('%.2f', $goods->original_price),
  210. 'video_url' => $goods->video_url,
  211. 'unit' => $goods->unit,
  212. 'use_attr' => intval($goods->use_attr),
  213. 'mch' => $mch,
  214. 'max_share_price' => sprintf('%.2f', $res['max_share_price']),
  215. 'min_member_price' => sprintf('%.2f', $res['min_member_price']),
  216. 'is_share' => $res['is_share'],
  217. 'is_level' => $res['is_level'],
  218. 'is_member_price' => $isMemberPrice,
  219. 'full_minus' => $GoodsFullMinus,
  220. 'verify_card_id' => $verify_card,
  221. 'goods_share_title' => $goods->goods_share_title,
  222. 'goods_share_desc' => $goods->goods_share_desc,
  223. 'goods_share_logo' => $goods->goods_share_logo,
  224. 'product_type' => $goods->product_type,
  225. 'growth_cycle' => $adopt_goods->growth_cycle,
  226. 'desc' => $adopt_goods->desc,
  227. 'yield' => $adopt_goods->yield,
  228. 'varieties' => $adopt_goods->varieties,
  229. 'adopt_income' => Json::decode($adopt_goods->adopt_income),
  230. 'self_pick_date' => Json::decode($adopt_goods->self_pick_date),
  231. 'self_pick_times' => Json::decode($adopt_goods->self_pick_times),
  232. 'remaining_num' => $goods->getNum() - ($goods->getSalesVolume() + ($is_md ? $md_goods->virtual_sales : $goods->virtual_sales)),
  233. 'device_id' => $device_id,
  234. 'integral' => json_decode($goods->integral, true),
  235. ];
  236. $now_date = strtotime(date('Y-m-d'));
  237. $goods_book = GoodsBook::findOne(['goods_id' => $goods->id]);
  238. // 预约参数配置
  239. if ($data['product_type'] == Goods::GOODS_TYPE_DATE) {
  240. if ($goods_book && !empty($goods_book->date_book)) {
  241. $date_book = Json::decode($goods_book->date_book);
  242. $count = 0;
  243. foreach ($date_book as $value) {
  244. if (strtotime($value['date']) >= $now_date) {
  245. $count++;
  246. }
  247. }
  248. if ($count <= 0) {
  249. return [
  250. 'code' => 1,
  251. 'msg' => '商品预约数据不存在'
  252. ];
  253. }
  254. $data['date_book'] = [
  255. 'date_book' => $date_book,
  256. 'date' => count($date_book)
  257. ];
  258. } else {
  259. return [
  260. 'code' => 1,
  261. 'msg' => '该商品暂无可预约数据'
  262. ];
  263. }
  264. }
  265. if ($data['product_type'] == Goods::GOODS_TYPE_TIME) {
  266. if ($goods_book && !empty($goods_book->service_book)) {
  267. $service_book = Json::decode($goods_book->service_book);
  268. $count = 0;
  269. foreach ($service_book['data'] as &$value) {
  270. if (strtotime($value['date']) >= $now_date) {
  271. foreach ($value['time'] as &$m) {
  272. foreach ($m['times'] as &$n) {
  273. if (strtotime(date('Y-m-d H:i:s')) <= strtotime(date('Y-m-d ' . $n['time']))) {
  274. $count++;
  275. }
  276. }
  277. }
  278. }
  279. }
  280. if ($count <= 0) {
  281. return [
  282. 'code' => 1,
  283. 'msg' => '该商品暂无可预约数据'
  284. ];
  285. }
  286. $data['service_book'] = $service_book;
  287. } else {
  288. return [
  289. 'code' => 1,
  290. 'msg' => '商品服务预约配置有误'
  291. ];
  292. }
  293. }
  294. return [
  295. 'code' => 0,
  296. 'data' => $data
  297. ];
  298. }
  299. // 快速给购买商品
  300. public function quickGoods($twocatid)
  301. {
  302. $goods = Goods::find()
  303. ->where([
  304. 'store_id' => $this->store_id,
  305. 'is_delete' => 0,
  306. 'status' => 1,
  307. 'quick_purchase' => 1
  308. ])
  309. ->andWhere([
  310. 'in', 'cat_id', $twocatid
  311. ])->asArray()
  312. ->all();
  313. foreach ($goods as $key => &$value) {
  314. $value['attr'] = json_decode($value['attr']);
  315. foreach ($value['attr'] as $key2 => $value2) {
  316. foreach ($value2->attr_list as $key3 => $value3) {
  317. $value['attr_name'] = $value3->attr_name;
  318. }
  319. $value['num'] = 0;
  320. }
  321. }
  322. return [
  323. 'code' => 0,
  324. 'data' => [
  325. 'list' => $goods,
  326. ],
  327. ];
  328. }
  329. /**
  330. * 获取优惠详情
  331. */
  332. public function getYouhui()
  333. {
  334. if (!$this->validate()) {
  335. return $this->getErrorSummary(false)[0];
  336. }
  337. $data = [];
  338. $goods = Goods::findOne($this->id);
  339. // 是否赠送积分
  340. $integral = json_decode($goods->integral, true);
  341. if ($integral['give'] > 0) {
  342. $data[] = [
  343. 'name' => '赠送积分',
  344. 'content' => '购买赠送' . $integral['give'] . '积分'
  345. ];
  346. }
  347. if ($integral['forehead'] > 0) {
  348. $data[] = [
  349. 'name' => '积分抵扣',
  350. 'content' => '最高可抵扣' . $integral['forehead'] . '元'
  351. ];
  352. }
  353. $goods_card = Goods::getGoodsCard($goods->id);
  354. foreach ($goods_card as $card) {
  355. $data[] = [
  356. 'name' => '卡券',
  357. 'content' => $card['name']
  358. ];
  359. }
  360. // 核销卡列表获取
  361. // 获取商品已添加核销卡
  362. if (empty($goods->verify_card_id)) {
  363. $goods_verify_card_list = [];
  364. } else {
  365. $verify_cards = explode(',', $goods['verify_card_id']);
  366. foreach ($verify_cards as $k => $v) {
  367. $verifyCard = VerifyCard::find()->select(['id', 'name'])->where(['id' => $v, 'is_delete' => 0])->asArray()->one();
  368. if ($verifyCard) {
  369. $goods_verify_card_list[] = $verifyCard;
  370. }
  371. }
  372. }
  373. foreach ((array)$goods_verify_card_list as $verify) {
  374. $data[] = [
  375. 'name' => '核销卡',
  376. 'content' => $verify['name']
  377. ];
  378. }
  379. $coupon_list = Coupon::getList($goods->mch_id);
  380. $coupon_list_res = [];
  381. foreach ($coupon_list as $coupon) {
  382. if ($coupon['appoint_type'] !== 3) {
  383. if ($coupon['appoint_type'] == 0) {
  384. $coupon_list_res[] = $coupon;
  385. } else {
  386. if ($coupon['appoint_type'] == 2) {
  387. $goods_id_arr = array_column($coupon['goods'], 'id');
  388. if (in_array($goods->id, $goods_id_arr) || empty($goods_id_arr)) {
  389. $coupon_list_res[] = $coupon;
  390. }
  391. } else {
  392. if ($coupon['appoint_type'] == 1) {
  393. if ($goods->mch_id > 0) {
  394. $cat_list = MchGoodsCat::find()->where([
  395. 'goods_id' => $goods->id,
  396. ])->all();
  397. } else {
  398. $cat_list = GoodsCat::find()->where([
  399. 'goods_id' => $goods->id,
  400. 'is_delete' => 0,
  401. 'store_id' => get_store_id()
  402. ])->all();
  403. }
  404. $cat_id_arr = array_column($coupon['cat'], 'id');
  405. if (empty($cat_id_arr)) {
  406. $coupon_list_res[] = $coupon;
  407. } else {
  408. foreach ($cat_list as $cat) {
  409. if (in_array($cat->cat_id, $cat_id_arr) || empty($cat_id_arr)) {
  410. $coupon_list_res[] = $coupon;
  411. break;
  412. }
  413. }
  414. }
  415. }
  416. }
  417. }
  418. }
  419. }
  420. $dataRes = [
  421. 'data' => $data,
  422. 'coupon' => $coupon_list_res
  423. ];
  424. return [
  425. 'code' => 0,
  426. 'data' => $dataRes
  427. ];
  428. }
  429. /**
  430. * @description: 获取商品收货地址
  431. * @param {*}
  432. * @return {*}
  433. */
  434. public function getAddress()
  435. {
  436. if ($this->address_id) {
  437. $query = Address::find()->where(['store_id' => get_store_id(), 'is_delete' => 0, 'id' => $this->address_id]);
  438. if (is_platform()) {
  439. $address = $query->andWhere([
  440. 'user_id' => get_saas_user_id()
  441. ])->one();
  442. } else {
  443. $address = $query->andWhere([
  444. 'user_id' => get_user_id()
  445. ])->one();
  446. }
  447. } else {
  448. $query = Address::find()->where(['store_id' => get_store_id(), 'is_delete' => 0]);
  449. if (is_platform()) {
  450. $query->andWhere([
  451. 'user_id' => get_saas_user_id()
  452. ]);
  453. } else {
  454. $query->andWhere([
  455. 'user_id' => get_user_id()
  456. ]);
  457. }
  458. $address = $query->orderBy(['is_default' => SORT_DESC])->one();
  459. }
  460. $goods = Goods::findOne($this->id);
  461. // 计算运费
  462. $express_price = $this->getExpressPrice($address, $goods);
  463. // 计算区域限制购买
  464. $is_area = $this->getTerritorialLimitation($address, $goods);
  465. $shop_id = null;
  466. $shop = null;
  467. if ($this->shop_id) {
  468. $shop_id = $this->shop_id;
  469. } else {
  470. $order = Order::find()->where([
  471. 'is_offline' => 1,
  472. 'user_id' => get_user_id()
  473. ])->orderBy(['id' => SORT_DESC])->one();
  474. if ($order) {
  475. $shop_id = $order->shop_id;
  476. }
  477. }
  478. if ($shop_id) {
  479. $shop = Shop::findOne($shop_id);
  480. }
  481. return [
  482. 'code' => 0,
  483. 'data' => [
  484. 'address' => $address,
  485. 'shop' => $shop,
  486. 'express_price' => $express_price,
  487. 'is_area' => $is_area
  488. ]
  489. ];
  490. }
  491. /**
  492. * 门店推荐
  493. */
  494. public function mchRecommend()
  495. {
  496. $goods_list = Goods::find()->where([
  497. 'mch_id' => $this->mch_id,
  498. 'status' => 1,
  499. 'is_delete' => 0
  500. ])->orderBy(['sort' => SORT_ASC])
  501. ->select(['id', 'name', 'cover_pic', 'price'])->limit(6)->all();
  502. return [
  503. 'code' => 0,
  504. 'data' => [
  505. 'list' => $goods_list
  506. ]
  507. ];
  508. }
  509. /**
  510. * 猜你喜欢
  511. */
  512. public function guessLike()
  513. {
  514. $cat_list = GoodsCat::find()->where(['goods_id' => $this->id, 'is_delete' => 0])->all();
  515. $cat_id = [];
  516. foreach ($cat_list as $val) {
  517. $cat_id[] = $val->cat_id;
  518. }
  519. $goods_list = Goods::find()->alias('g')
  520. ->leftJoin(['gc' => GoodsCat::tableName()], 'gc.goods_id=g.id')
  521. ->where([
  522. 'g.status' => 1,
  523. 'g.is_delete' => 0,
  524. 'gc.cat_id' => $cat_id
  525. ])->orderBy(['g.sort' => SORT_DESC])
  526. ->select(['g.id', 'g.name', 'g.cover_pic', 'g.price'])->groupBy('gc.goods_id')->limit(6)->all();
  527. return [
  528. 'code' => 0,
  529. 'data' => [
  530. 'list' => $goods_list
  531. ]
  532. ];
  533. }
  534. /**
  535. * 计算单个商品的运费
  536. */
  537. protected function getExpressPrice($address, $goods)
  538. {
  539. $expressPrice = 0;
  540. if ($address) {
  541. //再通过运费规则计算运费
  542. $expressPrice = PostageRules::getExpressPrice($goods->store_id, $address->city_id, $goods, 1, $address->province_id);
  543. }
  544. return $expressPrice >= 0 ? $expressPrice : 0;
  545. }
  546. /**
  547. * 计算单个商品是否区域限制购买
  548. */
  549. protected function getTerritorialLimitation($address, $goods)
  550. {
  551. $isArea = 0;
  552. if ($address) {
  553. $area = TerritorialLimitation::findOne([
  554. 'store_id' => get_store_id(),
  555. 'is_delete' => 0,
  556. 'is_enable' => 1,
  557. ]);
  558. if ($area) {
  559. $city_id = []; //限制的地区ID
  560. $detail = json_decode($area->detail);
  561. if (!is_array($detail)) {
  562. $detail = [];
  563. }
  564. foreach ($detail as $key => $value) {
  565. foreach ($value->province_list as $key2 => $value2) {
  566. $city_id[] = $value2->id;
  567. }
  568. }
  569. $addressArr = [
  570. $address['province_id'],
  571. $address['city_id'],
  572. $address['district_id']
  573. ];
  574. $addressArray = array_intersect($addressArr, $city_id);
  575. if (empty($addressArray)) {
  576. $isArea = 1;
  577. }
  578. }
  579. }
  580. return $isArea;
  581. }
  582. /**
  583. * User: chiyanying
  584. * Date: 2020/9/27
  585. * Time: 17:27
  586. * Notes:获取单个商品信息
  587. */
  588. public static function getGoods($goods_id = 0, $tore_id = 0, $type = 0)
  589. {
  590. if ($type == 0) {
  591. $form = new GoodsForm();
  592. $form->id = $goods_id;
  593. $form->store_id = $tore_id;
  594. return $form->search()['data'];
  595. }
  596. }
  597. /**
  598. * 获取店铺信息
  599. */
  600. public function getMch($goods)
  601. {
  602. $f = new ShopDataForm();
  603. $f->mch_id = $goods->mch_id;
  604. $shop = $f->getShop();
  605. if (isset($shop['code']) && $shop['code'] == 1) {
  606. return null;
  607. }
  608. return $shop;
  609. }
  610. }