|
@@ -0,0 +1,209 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace addons\shopro\library\activity\provider;
|
|
|
+
|
|
|
+use addons\shopro\service\StockSale;
|
|
|
+use addons\shopro\exception\ShoproException;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 砍价
|
|
|
+ */
|
|
|
+class Kan extends Base
|
|
|
+{
|
|
|
+ protected $rules = [
|
|
|
+ "is_commission" => "require|boolean",
|
|
|
+ "is_free_shipping" => "require|boolean",
|
|
|
+ "sales_show_type" => "require",
|
|
|
+ "limit_num" => "number|egt:0",
|
|
|
+ "order_auto_close" => "float|egt:0",
|
|
|
+ "team_num" => "require|number|egt:0",
|
|
|
+ ];
|
|
|
+
|
|
|
+
|
|
|
+ protected $message = [
|
|
|
+ 'team_num.require' => '请填写最多砍价人数',
|
|
|
+ ];
|
|
|
+
|
|
|
+
|
|
|
+ protected $default = [
|
|
|
+ "is_commission" => 0, // 是否参与分销
|
|
|
+ "is_free_shipping" => 0, // 是否包邮
|
|
|
+ "sales_show_type" => "real", // real=真实活动销量|goods=商品总销量(包含虚拟销量)
|
|
|
+ "limit_num" => 0, // 每人限购数量 0:不限购
|
|
|
+ "order_auto_close" => 0, // 订单自动关闭时间,如果为 0 将使用系统级订单自动关闭时间
|
|
|
+ "team_num" => 2, // 砍价人数,最少两人
|
|
|
+ ];
|
|
|
+
|
|
|
+
|
|
|
+ public function check($params, $activity_id = 0)
|
|
|
+ {
|
|
|
+ // 数据验证
|
|
|
+ $params = parent::check($params);
|
|
|
+
|
|
|
+ // 验证添加的活动商品是否至少设置了一个活动规格
|
|
|
+ $this->checkActivitySkuPrice($params['goods_list']);
|
|
|
+
|
|
|
+ // 检测活动之间是否存在冲突
|
|
|
+ $this->checkActivityConflict($params, $params['goods_list'], $activity_id);
|
|
|
+
|
|
|
+ return $params;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public function save($activity, $params = [])
|
|
|
+ {
|
|
|
+ $goodsList = $params['goods_list'];
|
|
|
+
|
|
|
+ $this->saveSkuPrice($goodsList, $activity);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ public function recoverSkuPrices($goods, $activity)
|
|
|
+ {
|
|
|
+ $activitySkuPrices = $activity['activity_sku_prices'];
|
|
|
+ $skuPrices = $goods->sku_prices;
|
|
|
+
|
|
|
+ foreach ($skuPrices as $key => &$skuPrice) {
|
|
|
+ $stock = $skuPrice->stock; // 下面要用
|
|
|
+ $skuPrice->stock = 0;
|
|
|
+ $skuPrice->sales = 0;
|
|
|
+ foreach ($activitySkuPrices as $activitySkuPrice) {
|
|
|
+ if ($skuPrice['id'] == $activitySkuPrice['goods_sku_price_id']) {
|
|
|
+ // 采用活动的 规格内容
|
|
|
+ $skuPrice->old_price = $skuPrice->price; // 保存原始普通商品规格的价格(计算活动的优惠)
|
|
|
+ $skuPrice->stock = ($activitySkuPrice['stock'] > $stock) ? $stock : $activitySkuPrice['stock']; // 活动库存不能超过商品库存
|
|
|
+ $skuPrice->sales = $activitySkuPrice['sales'];
|
|
|
+ $skuPrice->price = $activitySkuPrice['price'];
|
|
|
+ $skuPrice->status = $activitySkuPrice['status']; // 采用活动的上下架
|
|
|
+ $skuPrice->min_price = $activitySkuPrice['price']; // 当前活动规格最小价格,这里是秒杀价
|
|
|
+ $skuPrice->max_price = $activitySkuPrice['price']; // 用作计算活动中最大价格
|
|
|
+
|
|
|
+ // 记录相关活动类型
|
|
|
+ $skuPrice->activity_type = $activity['type'];
|
|
|
+ $skuPrice->activity_id = $activity['id'];
|
|
|
+ // 下单的时候需要存活动 的 sku_price_id)
|
|
|
+ $skuPrice->item_goods_sku_price = $activitySkuPrice;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return $skuPrices;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 这里要使用 shoproException 抛出异常
|
|
|
+ *
|
|
|
+ * @param array $buyInfo
|
|
|
+ * @param array $activity
|
|
|
+ * @return array
|
|
|
+ */
|
|
|
+ public function buyCheck($buyInfo, $activity)
|
|
|
+ {
|
|
|
+ $buy_type = request()->param('buy_type', 'kan');
|
|
|
+ $groupon_id = request()->param('kan_id', 0);
|
|
|
+ // 拼团
|
|
|
+ $rules = $activity['rules'];
|
|
|
+
|
|
|
+ $currentSkuPrice = $buyInfo['current_sku_price'];
|
|
|
+ $is_leader_discount = $currentSkuPrice['is_leader_discount'];
|
|
|
+
|
|
|
+ // 成团人数
|
|
|
+ $num = $rules['team_num'] ?? 1;
|
|
|
+ // 额外需要的库存
|
|
|
+ $need_add_num = 0;
|
|
|
+
|
|
|
+ // 要单独购买
|
|
|
+ if ($buy_type == 'alone') {
|
|
|
+ // 不允许单独购买
|
|
|
+ if (!$is_alone) {
|
|
|
+ throw new ShoproException('该商品不允许单独购买');
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 拼团,临时将拼团价设置为商品价格
|
|
|
+ if (!$groupon_id && $is_leader_discount) {
|
|
|
+ // 开新团,并且有团长优惠,使用优惠价格
|
|
|
+ $buyInfo['current_sku_price']['price'] = $currentSkuPrice['leader_price'];
|
|
|
+ } else {
|
|
|
+ // 参与团,或者没有团长优惠
|
|
|
+ $buyInfo['current_sku_price']['price'] = $currentSkuPrice['groupon_price'];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果是开新团
|
|
|
+ if (!$groupon_id && $buy_type == 'groupon') {
|
|
|
+ // 开团需要的最小库存
|
|
|
+ $need_add_num = ($num - 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 当前库存,小于要购买的数量
|
|
|
+ $need_num = $buyInfo['goods_num'] + ($need_add_num ?? 0);
|
|
|
+ if ($currentSkuPrice['stock'] < $need_num) {
|
|
|
+ if ($need_add_num && $is_alone && !$groupon_id && $buy_type == 'groupon') {
|
|
|
+ throw new ShoproException('商品库存不足以开团,请选择单独购买');
|
|
|
+ } else if ($buy_type == 'alone') {
|
|
|
+ throw new ShoproException('商品库存不足');
|
|
|
+ } else {
|
|
|
+ throw new ShoproException('该商品不允商品库存不足以开团许单独购买');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $buyInfo['is_commission'] = $rules['is_commission'] ?? 0; // 是否参与分销
|
|
|
+ return $buyInfo;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ public function buy($buyInfo, $activity)
|
|
|
+ {
|
|
|
+ $user = auth_user();
|
|
|
+ $buy_type = request()->param('buy_type', 'kan');
|
|
|
+ $groupon_id = request()->param('kan_id', 0);
|
|
|
+
|
|
|
+ // 参与现有团
|
|
|
+ if ($buy_type != 'alone' && $groupon_id) {
|
|
|
+ // 检测并获取要参与的团
|
|
|
+ $activityGroupon = $this->checkAndGetJoinGroupon($buyInfo, $user, $groupon_id);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 判断 并 增加 redis 销量
|
|
|
+ $stockSale = new StockSale();
|
|
|
+ $stockSale->cacheForwardSale($buyInfo);
|
|
|
+
|
|
|
+ // (开新团不判断)参与旧团 增加预拼团人数,上面加入团的时候已经判断过一次了,所以这里 99.99% 会加入成功的
|
|
|
+ if (isset($activityGroupon) && $activityGroupon) {
|
|
|
+ // 增加拼团预成员人数
|
|
|
+ $goods = $buyInfo['goods'];
|
|
|
+ $activity = $goods['activity'];
|
|
|
+ $this->grouponCacheForwardNum($activityGroupon, $activity, $user);
|
|
|
+ }
|
|
|
+
|
|
|
+ return $buyInfo;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ public function buyOk($order, $user)
|
|
|
+ {
|
|
|
+ // 不需要处理
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 拼团购买失败
|
|
|
+ *
|
|
|
+ * @param \think\Model $order
|
|
|
+ * @param string $type
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public function buyFail($order, $type)
|
|
|
+ {
|
|
|
+ // 判断扣除预销量 (活动信息还在 redis)
|
|
|
+ $stockSale = new StockSale();
|
|
|
+ $stockSale->cacheBackSale($order);
|
|
|
+ }
|
|
|
+}
|