OrderService.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. <?php
  2. namespace app\common\service;
  3. use app\common\model\Admin;
  4. use app\common\model\Goods;
  5. use app\common\model\GoodsCart;
  6. use app\common\model\GoodsSku;
  7. use app\common\model\User;
  8. use app\common\validate\KillService;
  9. use think\Collection;
  10. class OrderService extends BaseService {
  11. /** @var User */
  12. protected $user;
  13. protected $coupon_use;
  14. protected $coupon_id;
  15. /** @var 1直接购买2购物车买 */
  16. protected $frm;
  17. protected $goods=[];
  18. protected $cartSkuIds=null;
  19. protected $submit=false;
  20. protected $clearCart=false;
  21. /**
  22. * @param User $user
  23. */
  24. public function setUser(User $user)
  25. {
  26. $this->user = $user;
  27. }
  28. /**
  29. * @param $cartSkuIds
  30. */
  31. public function setCartSkuIds($cartSkuIds): void
  32. {
  33. $this->cartSkuIds = $cartSkuIds;
  34. }
  35. /**
  36. * @param bool $submit
  37. */
  38. public function setSubmit(bool $submit): void
  39. {
  40. $this->submit = $submit;
  41. }
  42. /**
  43. * @param bool $clearCart
  44. */
  45. public function setClearCart(bool $clearCart): void
  46. {
  47. $this->clearCart = $clearCart;
  48. }
  49. /**
  50. * @return bool
  51. */
  52. public function isClearCart(): bool
  53. {
  54. return $this->clearCart;
  55. }
  56. /**
  57. * @return bool
  58. */
  59. public function isSubmit(): bool
  60. {
  61. return $this->submit;
  62. }
  63. /**
  64. * @return User
  65. */
  66. public function getUser(): User
  67. {
  68. return $this->user;
  69. }
  70. /**
  71. * @param array $goods
  72. */
  73. public function setGoods(array $goods): void
  74. {
  75. $this->goods = $goods;
  76. }
  77. /**
  78. * @param mixed $frm
  79. */
  80. public function setFrm($frm): void
  81. {
  82. $this->frm = $frm;
  83. }
  84. /**
  85. * @param mixed $coupon_use
  86. */
  87. public function setCouponUse($coupon_use): void
  88. {
  89. $this->coupon_use = $coupon_use;
  90. }
  91. /**
  92. * @param mixed $coupon_id
  93. */
  94. public function setCouponId($coupon_id): void
  95. {
  96. $this->coupon_id = $coupon_id;
  97. }
  98. /**
  99. * @return Collection
  100. */
  101. public function getGoods()
  102. {
  103. $goods=$this->goods;
  104. if($this->frm==1) {
  105. $newGoods=[];
  106. foreach ($goods as $sku_id=>$info){
  107. $sku=GoodsSku::with(['goods'])->find($sku_id);
  108. if(!$sku||!$sku->goods){
  109. $this->error('规格或商品不存在');
  110. }
  111. $temp=[];
  112. $temp['num']=$info['num'];
  113. $temp['num_install']=$info['num_install'];
  114. $temp['sku']=$sku;
  115. $temp['goods']=$sku->goods;
  116. $temp['goods_id']=$sku['goods_id'];
  117. $temp['goods_sku_id']=$sku['id'];
  118. $newGoods[]=$temp;
  119. }
  120. return collection($newGoods);
  121. }else{
  122. $map=[];
  123. if(!is_null($this->cartSkuIds)){
  124. if(is_array($this->cartSkuIds) && empty($this->cartSkuIds)){
  125. return collection([]);
  126. }else{
  127. $map['goods_sku_id']=['in',$this->cartSkuIds];
  128. }
  129. }
  130. foreach ($this->goods as $skuId=>$numArr){
  131. $this->getUser()->cart()->where('goods_sku_id',$skuId)->update([
  132. 'num'=>$numArr['num'],
  133. 'num_install'=>$numArr['num_install'],
  134. ]);
  135. }
  136. return $this->getUser()->cart()
  137. ->where($map)
  138. ->with(['goods','sku'])
  139. ->select();
  140. }
  141. }
  142. public function calculate(){
  143. $info=[
  144. 'amount_total'=>0,
  145. 'amount_pay'=>0,
  146. 'amount_coupon'=>0,
  147. //'amount_goods'=>0,
  148. //'amount_goods_real'=>0,
  149. 'amount_coupon_kill'=>0,
  150. 'amount_coupon_level'=>0,
  151. 'amount_install'=>0,
  152. 'amount_discount'=>0,
  153. 'amount_cmn'=>0,
  154. 'coupon'=>[],
  155. ];
  156. $user=$this->getUser();
  157. $info['goods']=$this->getGoods();
  158. $killOpen=KillService::open();
  159. #提交订单操作
  160. $skuIds=[];
  161. if($this->isSubmit()) {
  162. foreach ($info['goods'] as $key=>$goods) {
  163. $sku = GoodsSku::lock(true)->find($goods['sku']['id']);
  164. $num=$goods['num'];
  165. $stock='num_stock';
  166. $goods['is_kill']=0;
  167. if($killOpen && $sku->goods()->value('is_kill')){
  168. $stock='num_stock_kill';
  169. $goods['is_kill']=1;
  170. }
  171. if($num>$sku[$stock]){
  172. $this->error('库存不足');
  173. }
  174. try {
  175. $sku->goods()->setInc('num_sell',$goods['num']);
  176. $sku->setDec($stock,$goods['num']);
  177. $sku->setInc('num_sell',$goods['num']);
  178. }catch (\Exception $e){
  179. $this->error('库存不足');
  180. }
  181. $sku->save();
  182. $skuIds[]=$goods['sku']['id'];
  183. $info['goods']->offsetSet($key,$goods);
  184. }
  185. }
  186. $info['num']=array_sum(array_column($info['goods']->toArray(),'num'));
  187. $info['num_install']=array_sum(array_column($info['goods']->toArray(),'num_install'));
  188. $injectCoupon=false;
  189. foreach ($info['goods'] as $key=>&$goods){
  190. if(!$goods['sku']||!$goods['goods']){
  191. $this->del($goods,'规格或商品不存在');
  192. continue;
  193. }
  194. if($goods['goods']['status']!=Goods::STATUS_NORMAL){
  195. $this->del($goods,"商品[{$goods['goods']['name']}]已下架");
  196. continue;
  197. }
  198. list($amountReal,$couponKill)=$this->getAmount($goods['sku'],$goods['goods'],$goods['num']);
  199. $goods['amount_pay']=0;
  200. $goods['amount_coupon']=0;
  201. $goods['amount_goods']=$amountReal;
  202. $goods['amount_goods_real']=$amountReal;
  203. $goods['amount_total']=$amountReal;
  204. $goods['amount_coupon_kill']=$couponKill;
  205. $goods['amount_install']=InstallService::getFee([$goods['sku']['id']=>$goods]);
  206. if(!empty($this->coupon_use) && !$injectCoupon){
  207. $coupon=$user->coupon()->lock($this->isSubmit())->findOrFail($this->coupon_id);
  208. if($coupon->checkCanUse($goods['amount_goods'],$goods['goods_id'])){
  209. $couponAmount=$coupon['amount'];
  210. $goods['coupon_id']=$coupon['id'];
  211. $goods['amount_coupon']=$couponAmount;
  212. $goods['amount_goods_real']=bcadd($goods['amount_goods_real'],-$couponAmount);
  213. if($this->isSubmit()){
  214. $coupon->setUse();
  215. }
  216. $injectCoupon=true;
  217. }
  218. }
  219. $goods['amount_coupon_level']=$this->getUser()->getLevelDiscount($goods['amount_goods_real']);
  220. $goods['amount_goods_real']=bcsub($goods['amount_goods_real'],$goods['amount_coupon_level']);
  221. $goods['amount_total']=bcadd($goods['amount_total'],$goods['amount_install']);
  222. $goods['amount_pay']=bcAddAll($goods['amount_goods_real'],$goods['amount_install']);
  223. $goods['amount_discount']=bcAddAll($goods['amount_coupon'],$goods['amount_coupon_kill'],$goods['amount_coupon_level']);
  224. $goods['amount_cmn']=Admin::getCmn($goods['amount_pay']);
  225. $info['amount_pay']=bcadd($info['amount_pay'],$goods['amount_pay']);
  226. $info['amount_total']=bcadd($info['amount_total'],$goods['amount_total']);
  227. $info['amount_coupon']=bcadd($info['amount_coupon'],$goods['amount_coupon']);
  228. $info['amount_coupon_kill']=bcadd($info['amount_coupon_kill'],$goods['amount_coupon_kill']);
  229. $info['amount_coupon_level']=bcadd($info['amount_coupon_level'],$goods['amount_coupon_level']);
  230. $info['amount_install']=bcadd($info['amount_install'],$goods['amount_install']);
  231. $info['amount_discount']=bcadd($info['amount_discount'],$goods['amount_discount']);
  232. $info['amount_cmn']=bcadd($info['amount_cmn'],$goods['amount_cmn']);
  233. $info['goods']->offsetSet($key,$goods);
  234. }
  235. if($this->coupon_use && !$injectCoupon){
  236. $this->error('优惠券不符合使用规则');
  237. }
  238. if(!$this->isSubmit()){
  239. $coupon=$user->coupon()->canUse()->select();
  240. $fitCoupon=[];
  241. foreach ($info['goods'] as $good){
  242. foreach ($coupon as $oneCoupon){
  243. if($oneCoupon->checkCanUse($good['amount_goods']??0,$good['goods_id'])){
  244. $fitCoupon[$oneCoupon['id']]=$oneCoupon;
  245. }
  246. }
  247. }
  248. $info['coupon']=array_values($fitCoupon);
  249. }
  250. #等级折扣金额
  251. //$info['amount_coupon_level']=$this->getUser()->getLevelDiscount($info['amount_goods_real']);
  252. //$info['amount_pay']=bcsub($info['amount_pay'],$info['amount_coupon_level']);
  253. //$info['amount_discount']=bcAddAll($info['amount_discount'],$info['amount_coupon'],$info['amount_coupon_kill'],$info['amount_coupon_level']);
  254. #删除购物车
  255. if($this->isClearCart()){
  256. $this->getUser()
  257. ->cart()
  258. ->whereIn('goods_sku_id',$skuIds)
  259. ->delete();
  260. }
  261. return $info;
  262. }
  263. /**
  264. * @param $sku GoodsSku
  265. */
  266. public static function getAmount($sku,$goods,$num){
  267. #价格,秒杀优惠金额
  268. $amount=$sku->calcAmount($num,'amount_ladder');
  269. $amountKill=$sku->calcAmount($num,'amount_kill_ladder');
  270. if(KillService::open() && $goods['is_kill']){
  271. return [$amountKill,bcsub($amount,$amountKill)];
  272. }else{
  273. return [$amount,0];
  274. }
  275. }
  276. protected function del($goods,$msg){
  277. if($this->frm==2){
  278. $this->getUser()->cart()->where('goods_id',$goods['goods_id'])->where('goods_sku_id',$goods['goods_sku_id'])->delete();
  279. }else{
  280. $this->error($msg);
  281. }
  282. }
  283. }