Promotion.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | A3Mall
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2020 http://www.a3-mall.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Author: xzncit <158373108@qq.com>
  8. // +----------------------------------------------------------------------
  9. namespace mall\basic;
  10. use mall\utils\BC;
  11. use think\facade\Db;
  12. use think\facade\Request;
  13. class Promotion {
  14. private static $array = [
  15. "0"=>"满额打折",
  16. "1"=>"满额优惠金额",
  17. "2"=>"满额送积分",
  18. "3"=>"满额免运费"
  19. ];
  20. public static function getType($type=''){
  21. return isset(self::$array[$type]) ? self::$array[$type] : self::$array;
  22. }
  23. public static function run($data){
  24. switch($data["type"]){
  25. case "1":
  26. return self::point($data);
  27. case "2":
  28. case "3":
  29. case "4":
  30. case "5":
  31. return self::activity($data);
  32. case "0":
  33. default:
  34. return self::discount($data);
  35. }
  36. }
  37. private static function point($order){
  38. if(($point = Db::name("promotion_point")
  39. ->where("unix_timestamp(now()) between start_time AND end_time")
  40. ->where(["id"=>$order["activity_id"],"status"=>0])->find()) == false){
  41. throw new \Exception("您要兑换的商品已过期",0);
  42. }
  43. $goods = current($order["item"]);
  44. $real_point = 0;
  45. if(isset($goods["spec_key"])){
  46. $pointItem = Db::name("promotion_point_item")->where([
  47. "pid"=>$order["activity_id"],
  48. "spec_key"=>$goods["spec_key"]
  49. ])->find();
  50. foreach($order["item"] as $k=>$v){
  51. $order["item"][$k]["market_price"] = (int)$pointItem["market_price"];
  52. $order["item"][$k]["real_price"] = (int)$pointItem["sell_price"];
  53. $order["item"][$k]["sell_price"] = (int)$pointItem["sell_price"];
  54. }
  55. if($goods["goods_nums"] > $pointItem["store_nums"]){
  56. throw new \Exception("商品库存不足",0);
  57. }
  58. $real_point = intval($pointItem["sell_price"]) * $goods["goods_nums"];
  59. }else{
  60. if($goods["goods_nums"] > $point["store_nums"]){
  61. throw new \Exception("商品库存不足",0);
  62. }
  63. $real_point = $point["point"] * $goods["goods_nums"];
  64. }
  65. $order["real_point"] = $real_point;
  66. $order["payable_amount"] = $order["real_freight"];
  67. $order["point"] = 0;
  68. $order["exp"] = 0;
  69. return $order;
  70. }
  71. private static function activity($order){
  72. $id = $order["activity_id"];
  73. $num = 0;
  74. foreach($order["item"] as $val){
  75. $num += $val["goods_nums"];
  76. }
  77. switch ($order["type"]){
  78. case "2":
  79. $regiment = Db::name("promotion_regiment")
  80. ->where("unix_timestamp(now()) between start_time AND end_time")
  81. ->where(["id"=>$id,"status"=>0])->find();
  82. if(empty($regiment)){
  83. throw new \Exception("您要购买的商品团购已结束",0);
  84. }
  85. if($num < $regiment["limit_min_count"]){
  86. throw new \Exception("团购商品每人只能兑换{$regiment["limit_min_count"]}件",0);
  87. }else if($num > $regiment["limit_max_count"]){
  88. throw new \Exception("团购商品每人只能兑换{$regiment["limit_max_count"]}件",0);
  89. }
  90. $goods = current($order["item"]);
  91. if(isset($goods["spec_key"])){
  92. $regimentItem = Db::name("promotion_regiment_item")->where([
  93. "pid"=>$order["activity_id"],
  94. "spec_key"=>$goods["spec_key"]
  95. ])->find();
  96. foreach($order["item"] as $k=>$v){
  97. $order["item"][$k]["market_price"] = $regimentItem["market_price"];
  98. $order["item"][$k]["real_price"] = $regimentItem["sell_price"];
  99. $order["item"][$k]["sell_price"] = $regimentItem["sell_price"];
  100. }
  101. if($goods["goods_nums"] > $regimentItem["store_nums"]){
  102. throw new \Exception("商品库存不足",0);
  103. }
  104. $real_amount = BC::mul($regimentItem["sell_price"],$goods["goods_nums"]);
  105. }else{
  106. if($goods["goods_nums"] > $regiment["store_nums"]){
  107. throw new \Exception("商品库存不足",0);
  108. }
  109. $real_amount = BC::mul($regiment["sell_price"],$goods["goods_nums"]);
  110. }
  111. $order["real_amount"] = $real_amount;
  112. $order["payable_amount"] = BC::add($order['real_freight'],$order["real_amount"]);
  113. $order["point"] = 0;
  114. $order["exp"] = 0;
  115. break;
  116. case "3":
  117. if(($seckill = Db::name("promotion_second")
  118. ->where("unix_timestamp(now()) between start_time AND end_time")
  119. ->where(["id"=>$id,"status"=>0])->find()) == false){
  120. throw new \Exception("您要购买的商品秒杀已结束",0);
  121. }
  122. $goods = current($order["item"]);
  123. if(isset($goods["spec_key"])){
  124. $secondItem = Db::name("promotion_second_item")->where([
  125. "pid"=>$order["activity_id"],
  126. "spec_key"=>$goods["spec_key"]
  127. ])->find();
  128. foreach($order["item"] as $k=>$v){
  129. $order["item"][$k]["market_price"] = $secondItem["market_price"];
  130. $order["item"][$k]["real_price"] = $secondItem["sell_price"];
  131. $order["item"][$k]["sell_price"] = $secondItem["sell_price"];
  132. }
  133. if($goods["goods_nums"] > $secondItem["store_nums"]){
  134. throw new \Exception("商品库存不足",0);
  135. }
  136. $real_amount = BC::mul($secondItem["sell_price"],$goods["goods_nums"]);
  137. }else{
  138. if($goods["goods_nums"] > $seckill["store_nums"]){
  139. throw new \Exception("商品库存不足",0);
  140. }
  141. $real_amount = BC::mul($seckill["sell_price"],$goods["goods_nums"]);
  142. }
  143. $order["real_amount"] = $real_amount;
  144. $order["payable_amount"] = BC::add($order['real_freight'],$order["real_amount"]);
  145. $order["point"] = 0;
  146. $order["exp"] = 0;
  147. break;
  148. case '4':
  149. if(($row = Db::name("promotion_price")->where("id",$id)->find()) == false){
  150. throw new \Exception("您要购买的商品活动已结束",0);
  151. }
  152. $price = floatval(Db::name("promotion_price_item")->where([
  153. "pid"=>$row["id"],
  154. "group_id"=>Users::get("group_id")
  155. ])->value("price"));
  156. if($price > 0){
  157. foreach($order["item"] as $key=>$val){
  158. $order["item"][$key]['sell_price'] = $price;
  159. $order["item"][$key]['real_price'] = $price;
  160. }
  161. $data["promotions"] = $order["promotions"] > 0 ? $order["promotions"]+$price : $price;
  162. $order["real_amount"] = $price;
  163. $order["payable_amount"] = BC::add($order['real_freight'],$price);
  164. }
  165. $order["point"] = 0;
  166. $order["exp"] = 0;
  167. break;
  168. case "5":
  169. if(($group = Db::name("promotion_group")
  170. ->where("unix_timestamp(now()) between start_time AND end_time")
  171. ->where(["id"=>$id,"status"=>0])->find()) == false){
  172. throw new \Exception("您要购买的拼团商品已结束",0);
  173. }
  174. $goods = current($order["item"]);
  175. if(isset($goods["spec_key"])){
  176. $groupItem = Db::name("promotion_group_item")->where([
  177. "pid"=>$order["activity_id"],
  178. "spec_key"=>$goods["spec_key"]
  179. ])->find();
  180. foreach($order["item"] as $k=>$v){
  181. $order["item"][$k]["market_price"] = $groupItem["market_price"];
  182. $order["item"][$k]["real_price"] = $groupItem["sell_price"];
  183. $order["item"][$k]["sell_price"] = $groupItem["sell_price"];
  184. }
  185. if($goods["goods_nums"] > $groupItem["store_nums"]){
  186. throw new \Exception("商品库存不足",0);
  187. }
  188. $real_amount = BC::mul($groupItem["sell_price"],$goods["goods_nums"]);
  189. }else{
  190. if($goods["goods_nums"] > $group["store_nums"]){
  191. throw new \Exception("商品库存不足",0);
  192. }
  193. $real_amount = BC::mul($group["sell_price"],$goods["goods_nums"]);
  194. }
  195. $order["real_amount"] = $real_amount;
  196. $order["payable_amount"] = BC::add($order['real_freight'],$order["real_amount"]);
  197. $order["point"] = 0;
  198. $order["exp"] = 0;
  199. break;
  200. }
  201. return $order;
  202. }
  203. private static function discount($order){
  204. if(($data = Db::name("promotion_order")
  205. ->where("unix_timestamp(now()) between start_time AND end_time AND {$order['payable_amount']} >= amount")
  206. ->order("amount DESC")
  207. ->find()) == false){
  208. return $order;
  209. }
  210. switch($data["type"]){
  211. case 0: // 打折
  212. $payable_amount = ($order["payable_amount"] * $data["expression"]) / 100;
  213. $order["discount"] = $order["payable_amount"] - $payable_amount;
  214. $order["payable_amount"] = $payable_amount;
  215. $order["promotion_explain"] = "购物满" . $data["amount"] . "元,优惠{$order["discount"]}元。";
  216. break;
  217. case 1: // 满额优惠
  218. $order["payable_amount"] -= $data["expression"];
  219. $order["promotions"] = $data["expression"];
  220. $order["promotion_explain"] = "购物满" . $data["amount"] . "元,优惠{$data["expression"]}元。";
  221. break;
  222. case 2: // 送积分
  223. $order["point"] += $data["expression"];
  224. $order["promotion_explain"] = "购物满" . $data["amount"] . "元,赠送{$data["expression"]}积分。";
  225. break;
  226. case 3: // 免运费
  227. $order["real_freight"] = 0;
  228. $order["promotion_explain"] = "购物满" . $data["amount"] . "元,免运费。";
  229. break;
  230. }
  231. return $order;
  232. }
  233. public static function checkOrderType($id,$product_id,$num,$type){
  234. $data = [
  235. "goods_id"=>is_array($id) && !empty($id[0]) ? $id[0] : $id,
  236. "product_id"=>$product_id,
  237. "nums"=>$num,
  238. "spec_key"=>"",
  239. "type"=>$type,
  240. "activity_id"=>0
  241. ];
  242. switch($type){
  243. case "group":
  244. if(($group = Db::name("promotion_group")
  245. ->where("store_nums",">","0")
  246. ->where("end_time",">",time())
  247. ->where(["id"=>$id,"status"=>0])->find()) == false){
  248. throw new \Exception("您选择的拼团商品已下架",0);
  249. }
  250. $data["activity_id"] = $group["id"];
  251. $data["goods_id"] = $group["goods_id"];
  252. break;
  253. case "second":
  254. if(($second = Db::name("promotion_second")
  255. ->where("store_nums",">","0")
  256. ->where("end_time",">",time())
  257. ->where(["id"=>$id,"status"=>0])->find()) == false){
  258. throw new \Exception("您选择的秒杀商品已下架",0);
  259. }
  260. $data["activity_id"] = $second["id"];
  261. $data["goods_id"] = $second["goods_id"];
  262. break;
  263. case "point":
  264. if(($point = Db::name("promotion_point")
  265. ->where("store_nums",">","0")
  266. ->where("end_time",">",time())
  267. ->where(["id"=>$id,"status"=>0])->find()) == false){
  268. throw new \Exception("您选择的积分商品已下架",0);
  269. }
  270. $data["activity_id"] = $point["id"];
  271. $data["goods_id"] = $point["goods_id"];
  272. break;
  273. case "regiment":
  274. if(($regiment = Db::name("promotion_regiment")
  275. ->where("store_nums",">","0")
  276. ->where("end_time",">",time())
  277. ->where(["id"=>$id,"status"=>0])->find()) == false){
  278. throw new \Exception("您选择的团购商品已下架",0);
  279. }
  280. if($num > $regiment["limit_max_count"]){
  281. throw new \Exception("团购商品,只允许购买{$regiment["limit_max_count"]}件");
  282. }else if($regiment["limit_min_count"] < $num){
  283. throw new \Exception("购买商品不能小于{$regiment["limit_min_count"]}件");
  284. }
  285. $data["activity_id"] = $regiment["id"];
  286. $data["goods_id"] = $regiment["goods_id"];
  287. break;
  288. case "special":
  289. if(($special = Db::name("promotion_price")->where(["id"=>$id])->find()) == false){
  290. throw new \Exception("您选择的特价商品已下架",0);
  291. }
  292. $data["activity_id"] = $special["id"];
  293. $data["goods_id"] = $special["goods_id"];
  294. break;
  295. }
  296. if(Db::name("goods_item")->where("goods_id",$data["goods_id"])->count()){
  297. if(($products=Db::name("goods_item")->where("goods_id",$data["goods_id"])->where("id",$product_id)->find()) == false){
  298. throw new \Exception("您选择的商品已下架",0);
  299. }
  300. $data["spec_key"] = $products["spec_key"];
  301. }
  302. $data["type"] = Order::getOrderType($type);
  303. return $data;
  304. }
  305. public static function updateStatus($order){
  306. if($order["type"] == 0){
  307. return true;
  308. }
  309. switch($order["type"]){
  310. case 1: // 积分
  311. if(!Db::name("promotion_point")->where(["id"=>$order["activity_id"]])->count()){
  312. return true;
  313. }
  314. $goods = current($order["item"]);
  315. Db::name("promotion_point")
  316. ->where(["id"=>$order["activity_id"]])
  317. ->update([
  318. "sum_count"=>Db::raw("sum_count+".$goods["goods_nums"]),
  319. "store_nums"=>Db::raw("store_nums-".$goods["goods_nums"])
  320. ]);
  321. break;
  322. case 2: // 团购
  323. if(!Db::name("promotion_regiment")->where(["id"=>$order["activity_id"]])->count()){
  324. return true;
  325. }
  326. $goods = current($order["item"]);
  327. Db::name("promotion_regiment")
  328. ->where(["id"=>$order["activity_id"]])
  329. ->update([
  330. "sum_count"=>Db::raw("sum_count+".$goods["goods_nums"]),
  331. "store_nums"=>Db::raw("store_nums-".$goods["goods_nums"])
  332. ]);
  333. break;
  334. case 3: // 秒杀
  335. if(!Db::name("promotion_second")->where(["id"=>$order["activity_id"]])->count()){
  336. return true;
  337. }
  338. $goods = current($order["item"]);
  339. Db::name("promotion_second")
  340. ->where(["id"=>$order["activity_id"]])
  341. ->update([
  342. "sum_count"=>Db::raw("sum_count+".$goods["goods_nums"]),
  343. "store_nums"=>Db::raw("store_nums-".$goods["goods_nums"])
  344. ]);
  345. break;
  346. case 5:
  347. if(!$group=Db::name("promotion_group")->where(["id"=>$order["activity_id"]])->find()){
  348. return true;
  349. }
  350. $goods = current($order["item"]);
  351. Db::name("promotion_group")
  352. ->where(["id"=>$order["activity_id"]])
  353. ->update([
  354. "sum_count"=>Db::raw("sum_count+".$goods["goods_nums"]),
  355. "store_nums"=>Db::raw("store_nums-".$goods["goods_nums"])
  356. ]);
  357. $kid = Request::param("kid","0","intval");
  358. $data = [
  359. "pid"=>0,
  360. "user_id"=>\mall\basic\Users::get("id"),
  361. "order_id"=>$order["order_id"],
  362. "goods_nums"=>$goods["goods_nums"],
  363. "order_amount"=>$order["order_amount"],
  364. "group_id"=>$order["activity_id"],
  365. "goods_id"=>$goods["goods_id"],
  366. "goods_title"=>$goods["title"],
  367. "people"=>1,
  368. "sell_price"=>$goods["real_price"],
  369. "start_time"=>time(),
  370. "end_time"=>strtotime("+{$group['effective_time']} hours"),
  371. "is_refund"=>0,
  372. "status"=>1,
  373. "create_time"=>time()
  374. ];
  375. if($kid != 0 && ($og = Db::name("order_group")->where([
  376. "id"=>$kid,
  377. "group_id"=>$order["activity_id"],
  378. "goods_id"=>$goods["goods_id"],
  379. "is_refund"=>0,
  380. "status"=>1
  381. ])->find()) != false){
  382. $data["pid"] = $kid;
  383. $data["people"] = $og["people"] + 1;
  384. Db::name("order_group")->where("id",$kid)->inc("people")->update();
  385. }
  386. Db::name("order_group")->insert($data);
  387. break;
  388. }
  389. }
  390. }