Trolley.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. <?php
  2. namespace app\api\controller;
  3. use app\common\model\StoreGoods;
  4. use app\common\model\StoreGoodsItem;
  5. use app\common\service\ExpressService;
  6. use think\Db;
  7. use app\common\model\ShoppingTrolley;
  8. use app\common\model\DeliveryAddress;
  9. use think\Exception;
  10. /**
  11. * @title 购物车
  12. * @controller Trolley
  13. * @group base
  14. */
  15. class Trolley extends Base
  16. {
  17. protected $no_login = ['delComment'];// 不需要登录的
  18. public function initialize()
  19. {
  20. parent::initialize();
  21. $path = explode('/',$this->request->path());
  22. if(!in_array(end($path),$this->no_login)) parent::checkLogin();
  23. }
  24. /**
  25. * @title 获取购物车商品数量
  26. * @desc 获取购物车商品数量
  27. * @author qc
  28. * @url /api/Trolley/getTrolleyNum
  29. * @method GET
  30. * @header name:Authorization require:1 desc:Token
  31. * @param name:goods_id type:int default:-- desc:商品id(商品id不传查全部的)
  32. * @return name:total_num type:int default:-- desc:购物车商品数量
  33. */
  34. public function getTrolleyNum()
  35. {
  36. $where = [];
  37. $where['user_id'] = $this->user_id;
  38. if($goods_id = input('get.goods_id',0)) $where['goods_id'] = $goods_id;
  39. $total_num = ShoppingTrolley::where($where)->sum('num');
  40. $this->success('ok',['total_num'=>$total_num]);
  41. }
  42. /**
  43. * @title 获取购物车列表
  44. * @desc 获取购物车列表
  45. * @author qc
  46. * @url /api/Trolley/getTrolleyList
  47. * @method GET
  48. * @header name:Authorization require:1 desc:Token
  49. * @return name:id type:int default:-- desc:购物车记录id
  50. * @return name:goods_id type:int default:-- desc:商品id
  51. * @return name:goods_name type:string default:-- desc:商品名称
  52. * @return name:goods_status type:int default:-- desc:商品状态(1上架,0下架)
  53. * @return name:cover type:string default:-- desc:商品封面
  54. * @return name:deleted_status type:string default:-- desc:商品删除状态(1删除,0未删除)
  55. * @return name:num type:int default:-- desc:数量
  56. * @return name:goods_id type:int default:-- desc:商品id
  57. * @return name:goods_id type:int default:-- desc:商品id
  58. * @return name:spec_id type:int default:-- desc:规格id
  59. * @return name:goods_spec type:int default:-- desc:规格
  60. * @return name:goods_no type:int default:-- desc:货号
  61. * @return name:original_price type:float default:-- desc:规格原价(下划线价格)
  62. * @return name:sell_price type:float default:-- desc:规格售价
  63. */
  64. public function getTrolleyList()
  65. {
  66. $join_field = 't.id,t.num,t.spec_id,t.goods_id,i.goods_spec,g.cover,i.goods_no,i.is_deleted,i.original_price,i.sell_price,i.weight,g.name goods_name,g.status goods_status,g.is_deleted deleted_status';
  67. $list = ShoppingTrolley::field($join_field)
  68. ->alias('t')
  69. ->where(['t.user_id'=>$this->user_id])
  70. ->leftJoin('StoreGoodsItem i','i.id = t.spec_id')
  71. ->leftJoin('StoreGoods g','t.goods_id = g.id')
  72. ->order('t.id desc')
  73. ->select()->toArray();
  74. $this->success('ok',['list'=>$list]);
  75. }
  76. /**
  77. * @title 商品添加购物车(按规格加入)
  78. * @desc 商品某个规格加入多少
  79. * @author qc
  80. * @url /api/Trolley/addTrolley
  81. * @method POST
  82. * @header name:Authorization require:1 desc:Token
  83. * @param name:goods_id type:int require:1 default:0 desc:商品id
  84. * @param name:spec_id type:int require:1 default:0 desc:规格id
  85. * @param name:num type:int default:1 desc:数量
  86. */
  87. public function addTrolley()
  88. {
  89. $goods_id = input('post.goods_id');
  90. $spec_id = input('post.spec_id');
  91. $num = input('post.num',1);
  92. if(!$goods_id || !$spec_id) $this->error('请选择商品');
  93. if($num <=0 ) $this->error('添加数量有误');
  94. Db::startTrans();
  95. try {
  96. // 商品详情
  97. $goods_info = StoreGoods::with(['itemList'=>function($query)use($spec_id){
  98. return $query->where('id',$spec_id)->where('is_deleted',0);
  99. }])->where('id',$goods_id)->where('is_deleted',0)->where('status',1)->find();
  100. if(!$goods_info) throw new Exception('商品已下架');
  101. $goods_info = $goods_info->toArray();
  102. if(empty($goods_info['item_list'])) throw new Exception('该规格已下架');
  103. if($goods_info['item_list'][0]['stock'] < $num) throw new Exception('库存不足');
  104. $trolley_id = ShoppingTrolley::checkTrolley($this->user_id,$goods_id,$spec_id);
  105. // 添加到购物车
  106. if($trolley_id) {
  107. ShoppingTrolley::where('id',$trolley_id)->setInc('num',$num);
  108. }else{
  109. $trolley_info = [
  110. 'user_id' => $this->user_id,
  111. 'goods_id' => $goods_id,
  112. 'spec_id' => $spec_id,
  113. 'goods_no' => $goods_info['item_list'][0]['goods_no'],
  114. 'num' => $num,
  115. ];
  116. ShoppingTrolley::create($trolley_info);
  117. }
  118. // 扣减库存
  119. StoreGoods::where('id',$goods_id)->setDec('stock',$num);
  120. StoreGoodsItem::where('id',$spec_id)->setDec('stock',$num);
  121. Db::commit();
  122. }catch (\Exception $e){
  123. $this->is_commit = false;
  124. $this->ret_msg = $e->getMessage();
  125. Db::rollback();
  126. }
  127. $this->is_commit ? $this->success('添加成功'):$this->error($this->ret_msg);
  128. }
  129. /**
  130. * @title 修改购物车商品数量
  131. * @desc 修改购物车商品数量
  132. * @author qc
  133. * @url /api/Trolley/changeTrolleyNum
  134. * @method POST
  135. * @header name:Authorization require:1 desc:Token
  136. * @param name:trolley_id type:int require:1 default:0 desc:购物车记录id
  137. * @param name:num type:int require:1 default:1 desc:变更数量
  138. * @param name:type type:int require:1 default:1 desc:变更类型(1增加2扣减)
  139. */
  140. public function changeTrolleyNum()
  141. {
  142. $trolley_id = input('post.trolley_id');
  143. $num = input('post.num',1);
  144. $type = input('post.type',1);
  145. if(!in_array($type,[1,2])) $this->error('变更可类型错误');
  146. Db::startTrans();
  147. try {
  148. $trolley_info = ShoppingTrolley::get($trolley_id);
  149. if(!$trolley_info) $this->exception('记录不存在!');
  150. $goods_info = StoreGoods::getGoodsSpec($trolley_info->goods_id,$trolley_info->spec_id);
  151. if($type == 1){
  152. if(!$goods_info) $this->exception('商品已下架');
  153. if(empty($goods_info['item_list'])) $this->exception('该规格已下架');
  154. if($goods_info['item_list'][0]['stock'] < $num)$this->exception('库存不足');
  155. ShoppingTrolley::where('id',$trolley_id)->setInc('num',$num);
  156. StoreGoods::where('id',$trolley_info->goods_id)->setDec('stock',$num);// 扣减商品库存
  157. StoreGoodsItem::where('id',$trolley_info->spec_id)->setDec('stock',$num);// 扣减规格库存
  158. }else{
  159. if($trolley_info->num < $num) $this->exception('扣减数量有误');
  160. if($trolley_info->num > $num){
  161. ShoppingTrolley::where('id',$trolley_id)->setDec('num',$num);//扣减数量
  162. }else{
  163. ShoppingTrolley::where('id',$trolley_id)->delete();//删除记录
  164. }
  165. StoreGoods::where('id',$trolley_info->goods_id)->setInc('stock',$num);//增加商品库存
  166. StoreGoodsItem::where('id',$trolley_info->spec_id)->setInc('stock',$num);//增加规格库存
  167. }
  168. Db::commit();
  169. }catch (\Exception $e){
  170. $this->ret_msg = $e->getMessage();
  171. $this->is_commit = false;
  172. Db::rollback();
  173. }
  174. $this->is_commit ? $this->success('操作成功') : $this->error($this->ret_msg);
  175. }
  176. /**
  177. * @title 删除购物车记录
  178. * @desc 删除购物车记录
  179. * @author qc
  180. * @url /api/Trolley/cancelTrolleyList
  181. * @method POST
  182. * @header name:Authorization require:1 desc:Token
  183. * @param name:ids type:string require:1 default:0 desc:购物车记录id(多条用逗号隔开)
  184. */
  185. public function cancelTrolleyList()
  186. {
  187. $ids = input('post.ids');
  188. if(!$ids) $this->error('请选择要删除的数据');
  189. $trolley_list = ShoppingTrolley::where('id','in',$ids)->select();
  190. Db::startTrans();
  191. foreach ($trolley_list as $trolley_info) {
  192. StoreGoods::where('id',$trolley_info->goods_id)->setInc('stock',$trolley_info->num);//增加商品库存
  193. StoreGoodsItem::where('id',$trolley_info->spec_id)->setInc('stock',$trolley_info->num);//增加规格库存
  194. }
  195. ShoppingTrolley::where('id','in',$ids)->delete();
  196. Db::commit();
  197. $this->success('删除成功');
  198. }
  199. /**
  200. * @title 某商品是否添加到购物
  201. * @desc 获取某商品添加到购物车规格及数量
  202. * @author qc
  203. * @url /api/Trolley/getTrolleyByGoodsId
  204. * @method GET
  205. * @header name:Authorization require:1 desc:Token
  206. * @param name:goods_id type:int default:1 desc:商品id
  207. * @return name:spec_id type:int default:-- desc:规格id
  208. * @return name:num type:int default:-- desc:数量
  209. */
  210. public function getTrolleyByGoodsId()
  211. {
  212. $goods_id = input('get.goods_id');
  213. $list = ShoppingTrolley::field('id,goods_id,spec_id,goods_no,num')
  214. ->where(['user_id'=>$this->user_id,'goods_id'=>$goods_id])
  215. ->order('id desc')
  216. ->select();
  217. $this->success('ok',['list'=>$list?$list->toArray() : null ]);
  218. }
  219. /**
  220. * @title 购物车订单确认
  221. * @desc 购物车订单确认
  222. * @author qc
  223. * @url /api/Trolley/confirmTrolleyList
  224. * @method GET
  225. * @header name:Authorization require:1 desc:Token
  226. * @param name:ids type:int default:1 desc:购物车记录id(多条用逗号隔开)
  227. * @return name:goods_id type:int default:-- desc:商品id
  228. * @return name:goods_name type:string default:-- desc:商品名称
  229. * @return name:goods_status type:int default:-- desc:商品状态(1上架,0下架)
  230. * @return name:deleted_status type:string default:-- desc:删除状态(1删除,0未删除)
  231. * @return name:cover type:string default:-- desc:封面
  232. * @return name:item_list type:array default:-- desc:添加该商品的规格列表
  233. * @return name:item_list.spec_id type:int default:-- desc:规格id
  234. * @return name:item_list.goods_no type:int default:-- desc:货号
  235. * @return name:item_list.original_price type:float default:-- desc:规格原价
  236. * @return name:item_list.sell_price type:float default:-- desc:规格售价
  237. * @return name:item_list.goods_spec type:string default:-- desc:规格
  238. * @return name:total_money type:float default:-- desc:商品总金额【不含运费】
  239. * @return name:freight type:float default:-- desc:运费
  240. * @return name:freight_code type:int default:1 desc:运费提示编号【1所选地址支持发货,0所选地址不支持发货】
  241. * @return name:freight_msg type:string default:-- desc:运费提示信息【freight_code=1忽略】
  242. */
  243. public function confirmTrolleyList()
  244. {
  245. $ids = input('get.ids');
  246. $trolley_goods = ShoppingTrolley::field('goods_id')
  247. ->where('user_id',$this->user_id)
  248. ->where('id','in',$ids)
  249. ->group('goods_id')
  250. ->select();
  251. if(!$trolley_goods) $this->error('请选择商品');
  252. $goods_ids = array_column($trolley_goods->toArray(),'goods_id');
  253. $freight = 0;
  254. $list = [];
  255. $total_money = 0;
  256. $goods_list = StoreGoods::where('id','in',$goods_ids)->select()->toArray();
  257. $address_info = DeliveryAddress::where(['user_id'=>$this->user_id,'is_mr'=>1])->find();
  258. foreach ($goods_list as $goods_info){
  259. $trolley_data = ['goods_id'=>$goods_info['id'],'goods_name'=>$goods_info['name'],'goods_status'=>$goods_info['status'],'cover'=>$goods_info['cover'],'deleted_status'=>$goods_info['is_deleted']];
  260. $trolley_data['item_list'] = ShoppingTrolley::field('t.*,i.original_price,i.sell_price,i.goods_spec')
  261. ->alias('t')
  262. ->where('t.id','in',$ids)
  263. ->where('t.goods_id',$goods_info['id'])
  264. ->leftJoin('StoreGoodsItem i','i.id = t.spec_id')
  265. ->select()->toArray();
  266. foreach ($trolley_data['item_list'] as $iv){
  267. $total_money = bcadd(bcmul($iv['num'],$iv['sell_price'],2),$total_money,2);
  268. }
  269. $list[] = $trolley_data;
  270. $fre_num = array_sum(array_column($trolley_data['item_list'],'num'));
  271. if($address_info) {
  272. $goods_freight = ExpressService::getGoodsExpressPrice($goods_info,$address_info->id,$fre_num);
  273. if($goods_freight['code'] !=200){
  274. $this->is_commit = false;
  275. $this->ret_msg = $goods_freight['msg'];
  276. }
  277. $freight += $goods_freight['freight']; // 商品运费
  278. }
  279. }
  280. $this->success('ok',[
  281. 'list'=>$list,
  282. 'total_money'=>$total_money,
  283. 'address_info'=>$address_info ? $address_info->toArray():null,
  284. 'freight' =>$freight,
  285. 'freight_msg' => $this->ret_msg,
  286. 'freight_code' => $this->is_commit ? 1 :0
  287. ]);
  288. }
  289. }