GoodsController.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. <?php
  2. namespace addons\Mch\api\modules\v1\controllers;
  3. use addons\Coupon\common\enums\AddonsCouponEnum;
  4. use addons\Coupon\common\models\AddonsCoupon;
  5. use addons\Coupon\common\models\AddonsCouponMemberRelate;
  6. use addons\Coupon\common\models\AddonsCouponUserRelate;
  7. use addons\Mch\common\models\Mch;
  8. use common\enums\OrderCommentEnum;
  9. use common\enums\StatusEnum;
  10. use common\logic\common\GoodsLogic;
  11. use common\models\cart\Cart;
  12. use common\models\common\Region;
  13. use common\models\diy\DiyComponentsData;
  14. use common\models\goods\Goods;
  15. use common\models\goods\GoodsCateRelate;
  16. use api\controllers\OnAuthController;
  17. use common\models\mall\MallAddons;
  18. use common\models\order\OrderComments;
  19. use common\models\user\User;
  20. use common\models\user\UserLevel;
  21. use common\models\user\UserPartitionRelationship;
  22. use yii\db\Expression;
  23. /**
  24. * 默认控制器
  25. *
  26. * Class DefaultController
  27. * @package addons\Store\api\modules\v1\controllers
  28. */
  29. class GoodsController extends OnAuthController
  30. {
  31. public $modelClass = '';
  32. /**
  33. * 不用进行登录验证的方法
  34. *
  35. * 例如: ['index', 'update', 'create', 'view', 'delete']
  36. * 默认全部需要验证
  37. *
  38. * @var array
  39. */
  40. protected $authOptional = ['index', 'detail', 'cate-goods-list', 'list', 'recommend', 'comments-list','coupon-list'];
  41. /**
  42. * 分类商品列表
  43. * @return mixed|void
  44. */
  45. public function actionCateGoodsList()
  46. {
  47. $params = \Yii::$app->request->get();
  48. $res = \Yii::$app->services->validate->validate($params, [
  49. [['mch_id'], 'required'],
  50. [['cate_id'], 'safe'],
  51. [['goods_name'], 'string'],
  52. ]);
  53. if ($res === false) return $this->error(\Yii::$app->services->validate->getErrorMessage());
  54. $mch_id = $params['mch_id'];
  55. $where[] = ['mch_id' => $mch_id, 'mall_id' => $this->mall_id, 'check_status' => 1, 'is_on_sale' => 1, 'status' => StatusEnum::ENABLED];
  56. if (!empty($params['cate_id'])) {
  57. $goods_cate_relate_list = GoodsCateRelate::findAll(['cate_id' => $params['cate_id']]);
  58. $goods_id_arr = array_column($goods_cate_relate_list, 'goods_id');
  59. $where[] = ['id' => $goods_id_arr];
  60. }
  61. if (!empty(trim($params['goods_name']))) $where[] = ['like', 'goods_name', trim($params['goods_name'])];
  62. $params['where'] = $where;
  63. $params['select'] = 'id,goods_name,cover_pic,price,(sales_num+virtual_sales) as sales_num,original_price,status,stock,attr_groups,attr_groups_format';
  64. $params['order'] = 'sort asc';
  65. $params['with'] = ['attr' => function ($query) {
  66. $query->select('id,goods_id,name,price,sign_id,stock,pic_url,original_price');
  67. }, 'extra'];
  68. $goods_list = Goods::listPage($params);
  69. $list = Cart::getCartList($this->user_id);
  70. $goods_num_arr = [];
  71. foreach ($list as $v) {
  72. $row = json_decode($v, true);
  73. if (isset($goods_num_arr[$row['goods_id']])) {
  74. $goods_num_arr[$row['goods_id']] += $row['num'];
  75. } else {
  76. $goods_num_arr[$row['goods_id']] = $row['num'];
  77. }
  78. }
  79. if (!empty($goods_list['list'])) {
  80. foreach ($goods_list['list'] as &$item) {
  81. $item['member_buy_limit_setting'] = empty($item['extra']['member_buy_limit_setting']) ? '' : json_decode($item['extra']['member_buy_limit_setting'], true);
  82. unset($item['extra']);
  83. $item['num'] = !empty($goods_num_arr[$item['id']]) ? $goods_num_arr[$item['id']] : 0;
  84. $item['status'] = empty($item['stock']) ? 0 : 1;
  85. }
  86. $goods_list['list'] = DiyComponentsData::getMemberPrice($this->mall_id, $goods_list['list'], 1, $this->user_id??0);
  87. $user_level = UserLevel::findOne(['mall_id' => $this->mall_id, 'level' => $this->user['level'], 'status' => StatusEnum::ENABLED]);
  88. foreach ($goods_list['list'] as &$item){
  89. //额外会员设置
  90. if($user_level && !empty($user_level['member_price_is_show'])){
  91. $item['member_price_is_show'] = $user_level['member_price_is_show'];
  92. }
  93. }
  94. }
  95. return $this->success('操作成功', $goods_list);
  96. }
  97. public function actionDetail()
  98. {
  99. $goods_id = \Yii::$app->request->get('goods_id', 0);
  100. $mch_id = \Yii::$app->request->get('mch_id', 0);
  101. $mall_id = $this->mall_id;
  102. $addonsFields = \Yii::$app->request->get('addonsFields', '');
  103. try {
  104. $select = 'id,is_on_sale,goods_name,price,original_price,unit,attr_groups_format,attr_groups,area_limit,is_attr,is_show_stock,video_url,stock,video_cover_pic,cover_pic,bannar_pic,sales_num,virtual_sales,is_show_sales,detail,services,status,goods_source';
  105. $user_id = $this->user_id ?? 0;
  106. $params['mall_id'] = $mall_id;
  107. $params['where'] = [['id' => $goods_id], ['mall_id' => $mall_id], ['mch_id' => $mch_id], ['check_status' => 1], ['is_on_sale' => 1], ['status' => StatusEnum::ENABLED]];
  108. $params['is_array'] = true;
  109. $params['with'] = [
  110. 'attr' => function ($query) {
  111. $query->orderBy('price asc')->select('id,goods_id,goods_no,name,original_price,pic_url,price,sign_id,sort,status,version,weight,stock');
  112. }, 'extra'
  113. ];
  114. $params['order'] = false;
  115. $params['select'] = $select;
  116. $params['goods_id'] = $goods_id;
  117. $goods = GoodsLogic::GetDetail($this->mall_id, $params, $this->user);
  118. if (empty($goods)) throw new \Exception("商品不存在");
  119. foreach ($goods['attr'] as $k => &$item) {
  120. if ($k == 0) {
  121. $goods['attr_id'] = $item['id'];
  122. $goods['price'] = $item['price'];
  123. $goods['original_price'] = $item['original_price'];
  124. break;
  125. }
  126. }
  127. if (!empty($goods['is_attr'])) $goods['stock'] = array_sum(array_column($goods['attr'], 'stock'));//多规格,按规格库存累计
  128. if (!empty($user)) {
  129. //基础会员等级折扣
  130. $user_level = UserLevel::findOne(['mall_id' => $mall_id, 'level' => $user['level'], 'status' => StatusEnum::ENABLED]);
  131. if (isset($user_level)) {
  132. $discount = $user_level['discount'] ?? 0;
  133. $goods['price_type'] = '会员优惠';
  134. $is_member_price = $goods['extra']['is_member_price'] ?? 2;
  135. $goods['is_member_price'] = $is_member_price;
  136. if ($is_member_price != 2) {
  137. if (!empty($goods['extra']['is_member_price']) && !empty($goods['extra']['member_price_setting'])) {
  138. $member_price_setting = Json::decode($goods['extra']['member_price_setting'], true);
  139. }
  140. $goods['price'] = bcdiv($goods['price'] * $discount, 10, 2);
  141. if (empty($goods['is_attr'])) {
  142. if (isset($member_price_setting[$user['level']])) {
  143. $goods['price'] = $member_price_setting[$user['level']];
  144. foreach ($goods['attr'] as &$item) {
  145. $item['price'] = $goods['price'];
  146. }
  147. }
  148. } else {
  149. $attr_price_arr = [];
  150. foreach ($goods['attr'] as $k => &$item) {
  151. $item['price'] = bcdiv($item['price'] * $discount, 10, 2); //全局等级会员价
  152. if (isset($member_price_setting['level' . $user['level']][$item['sign_id']])) {
  153. //商品独立设置的会员价
  154. $item['price'] = $member_price_setting['level' . $user['level']][$item['sign_id']];
  155. }
  156. $attr_price_arr[$item['price']] = ['id' => $item['id'], 'price' => $item['price'], 'original_price' => $item['original_price']];
  157. }
  158. ksort($attr_price_arr);
  159. $attr_arr = array_shift($attr_price_arr);
  160. $goods['attr_id'] = $attr_arr['id'] ?? 0;
  161. $goods['price'] = $attr_arr['price'] ?? 0;
  162. $goods['original_price'] = $attr_arr['original_price'] ?? 0;
  163. }
  164. }
  165. }
  166. }
  167. $mch = Mch::getOne([['id' => $mch_id], ['status' => StatusEnum::ENABLED]], true, [], false,
  168. 'id,store_name,logo_img,province_id,city_id,district_id,address,customer_service');
  169. $region = Region::lists(['where' => [['id' => [$mch['province_id'], $mch['city_id'], $mch['district_id']]]], 'index' => 'id', 'id,name']);
  170. $mch['province'] = $region[$mch['province_id']]['name'] ?? '';
  171. $mch['city'] = $region[$mch['city_id']]['name'] ?? '';
  172. $mch['district'] = $region[$mch['district_id']]['name'] ?? '';
  173. $mch['customer_service'] = !empty($mch['customer_service']) ? json_decode($mch['customer_service'], true) : ['web_service_url' => ''];
  174. unset($mch['province_id']);
  175. unset($mch['city_id']);
  176. unset($mch['district_id']);
  177. $goods['member_buy_limit_setting'] = json_decode($goods['extra']['member_buy_limit_setting'], true);
  178. unset($goods['extra']);
  179. if ($addonsFields) {
  180. if($this->platform == User::PLATFORM_MP_WX){
  181. is_string($addonsFields) && $addonsFields = json_decode($addonsFields, true);
  182. }else{
  183. $addonsFields = is_string($addonsFields) ? explode(',', $addonsFields) : $addonsFields;
  184. }
  185. $goods = Goods::getAddonsGoodsSetting($this->mall_id, $addonsFields, $goods, 'detail');
  186. }
  187. $goods['is_bind_popups'] = UserPartitionRelationship::getIsNeedPopups($this->mall_id, $this->user_id ?? 0);
  188. return $this->success('获取成功', ['goods' => $goods, 'mch' => $mch]);
  189. } catch (\Exception $e) {
  190. return $this->error($e->getMessage());
  191. }
  192. }
  193. /**
  194. * 商品评价列表
  195. * @return mixed|void
  196. */
  197. public function actionCommentsList()
  198. {
  199. $params = \Yii::$app->request->get();
  200. $res = \Yii::$app->services->validate->validate($params, [
  201. [['mch_id'], 'required', 'message' => 'mch_id必传'],
  202. [['limit', 'page', 'type', 'goods_id'], 'safe']
  203. ]);
  204. if ($res === false) return $this->error(\Yii::$app->services->validate->getErrorMessage());
  205. $data['comments'] = [];
  206. $data['good_rate'] = 0;//满意度
  207. $where = ['mall_id' => $this->mall_id, 'mch_id' => $params['mch_id'], 'status' => StatusEnum::ENABLED,];
  208. if (!empty($params['goods_id'])) $where['goods_id'] = $params['goods_id'];
  209. $total = OrderComments::find()->where($where)->count();
  210. $data['comment_count'][0] = ['name' => OrderCommentEnum::OC_ALL, 'count' => $total ?? 0];
  211. $good_num = OrderComments::find()->where($where)->andWhere(['in', 'score', OrderCommentEnum::OC_PRAISE_SCORES])->count();
  212. $data['comment_count'][1] = ['name' => OrderCommentEnum::OC_PRAISE, 'count' => $good_num ?? 0];
  213. $count = OrderComments::find()->where($where)->andWhere(['in', 'score', OrderCommentEnum::OC_MIDDLE_SCORES])->count();
  214. $data['comment_count'][2] = ['name' => OrderCommentEnum::OC_MIDDLE, 'count' => $count ?? 0];
  215. $count = OrderComments::find()->where($where)->andWhere(['in', 'score', OrderCommentEnum::OC_NEGATIVE_SCORES])->count();
  216. $data['comment_count'][3] = ['name' => OrderCommentEnum::OC_NEGATIVE, 'count' => $count ?? 0];
  217. $count = OrderComments::find()->where($where)->andWhere(['<>', 'pic_url', '[]'])->count();
  218. $data['comment_count'][4] = ['name' => '有图', 'count' => $count ?? 0];
  219. $where = [];
  220. $where[] = ['mall_id' => $this->mall_id];
  221. $where[] = ['status' => StatusEnum::ENABLED];
  222. if (!empty($params['goods_id'])) $where[] = ['goods_id' => $params['goods_id']];
  223. $where[] = ['mch_id' => $params['mch_id']];
  224. if (!empty($params['type'])) {
  225. switch ($params['type']) {
  226. case OrderCommentEnum::TYPE1://差评
  227. $where[] = ['in', 'score', OrderCommentEnum::OC_NEGATIVE_SCORES];
  228. break;
  229. case OrderCommentEnum::TYPE2://中评
  230. $where[] = ['in', 'score', OrderCommentEnum::OC_MIDDLE_SCORES];
  231. break;
  232. case OrderCommentEnum::TYPE4://好评
  233. $where[] = ['in', 'score', OrderCommentEnum::OC_PRAISE_SCORES];
  234. break;
  235. case OrderCommentEnum::TYPE5://有图
  236. $where[] = ['<>', 'pic_url', '[]'];
  237. break;
  238. }
  239. }
  240. $params['where'] = $where;
  241. $params['select'] = '*';
  242. $params['order'] = 'is_top desc,id desc';
  243. $order_comments_list = OrderComments::listPage($params);
  244. if (!empty($order_comments_list['list'])) {
  245. $user_id_arr = array_column($order_comments_list['list'], 'user_id');
  246. $user_list = User::findAll(['id' => $user_id_arr]);
  247. $user_arr = [];
  248. foreach ($user_list as $v) {
  249. $user_arr[$v['id']] = ['nickname' => $v['nickname'], 'avatar_url' => $v['avatar_url'], 'level' => $v['level']];
  250. }
  251. foreach ($order_comments_list['list'] as &$v) {
  252. $v['pic_url'] = !empty($v['pic_url']) ? json_decode($v['pic_url'], true) : [];
  253. $comment['nickname'] = $comment['avatar_url'] = '';
  254. if (isset($user_arr[$v['user_id']])) {
  255. $user = $user_arr[$v['user_id']];
  256. $v['nickname'] = $user['nickname'];
  257. $v['avatar_url'] = $user['avatar_url'];
  258. $v['level'] = $user['level'];
  259. }
  260. }
  261. $data['comments'] = $order_comments_list;
  262. }
  263. return $this->success('操作成功', $data);
  264. }
  265. public function actionCouponList()
  266. {
  267. if (\Yii::$app->request->isGet) {
  268. $params = \Yii::$app->request->get();
  269. $res = \Yii::$app->services->validate->validate($params, [
  270. [['goods_id','mch_id'], 'required'],
  271. ]);
  272. if (!MallAddons::isInstall($this->mall_id, 'Coupon')) {
  273. return $this->success('操作成功', []);
  274. }
  275. $mch_id = $params['mch_id'];
  276. if ($res === false) return $this->error(\Yii::$app->services->validate->getErrorMessage());
  277. $where[] = ['mall_id' => $this->mall_id, 'status' => StatusEnum::ENABLED, 'is_public_receive' => 1, 'coupon_status' => AddonsCouponEnum::STATUS_RECEIVING, 'store_id' => ''];
  278. $where[] = ['>', 'total_count', 0];
  279. $where[] = ['appoint_type' => 5];
  280. $where[] = new Expression("FIND_IN_SET({$mch_id},mch_id)");
  281. $params['where'] = $where;
  282. $params['select'] = 'id,mch_id,type,begin_at,end_at,min_price,sub_price,discount,discount_limit,coupon_status,name,is_receive_limit,receive_count,is_member,total_count';
  283. $params['order'] = 'created_at desc';
  284. $list = AddonsCoupon::listPage($params);
  285. if (!empty($list['list'])) {
  286. $coupon_ids = array_column($list['list'], 'id');
  287. if (!empty($this->user_id)) {
  288. $coupon_user_relate_list = AddonsCouponUserRelate::lists([
  289. 'where' =>
  290. [
  291. ['coupon_id' => $coupon_ids],
  292. ['user_id' => $this->user_id],
  293. ['status' => StatusEnum::ENABLED],
  294. ['or', ['is_giving' => 0], ['is_giving' => 1, 'giving_status' => AddonsCouponEnum::GIVING_STATUS1]],
  295. ],
  296. 'select' => 'count(id) as counts,coupon_id',
  297. 'group' => 'coupon_id',
  298. 'index' => 'coupon_id'
  299. ]);
  300. }
  301. foreach ($list['list'] as &$item) {
  302. $item['is_receive'] = 0;
  303. $item['counts'] = 0;
  304. if (!empty($coupon_user_relate_list[$item['id']])) {
  305. $item['counts'] = $coupon_user_relate_list[$item['id']]['counts'];
  306. if (1 == $item['is_member']) {
  307. // 限制会员等级领取
  308. $member_levels = AddonsCouponMemberRelate::find()
  309. ->select('member_level')
  310. ->where(['mall_id' => $this->mall_id, 'coupon_id' => $item['id']])
  311. ->asArray()
  312. ->column();
  313. if (!in_array($this->user->level, $member_levels)) $item['is_receive'] = 1;
  314. }
  315. if (1 == $item['is_receive_limit'] && $item['counts'] >= $item['receive_count']) $item['is_receive'] = 1;
  316. }
  317. // 剩余可领取数量
  318. if (1 == $item['is_receive_limit']) {
  319. $item['remainder_count'] = $item['receive_count'] - $item['counts'];
  320. } else {
  321. $item['remainder_count'] = $item['total_count'];
  322. }
  323. }
  324. }
  325. $list['coupon_status_map'] = AddonsCouponEnum::getCouponStatusMap();
  326. return $this->success('操作成功', $list);
  327. }
  328. }
  329. }