GoodsActivity.php 5.1 KB
<?php

namespace addons\groupon\library\traits\model\goods;

use addons\groupon\exception\Exception;
use addons\groupon\library\traits\ActivityCache;
use addons\groupon\model\Goods;
use addons\groupon\model\Activity;
use addons\groupon\model\OrderItem;
use addons\groupon\model\Order;
use think\Cache;
use think\Db;

trait GoodsActivity
{
    use ActivityCache;

    /**
     * 处理商品活动
     *
     * @param [type] $detail
     * @param [type] $sku_price
     * @return void
     */
    public static function operActivity($detail, $sku_price)
    {
        $detail = self::operActivitySkuPrice($detail, $sku_price);

        $activityDiscountType = [
            'full_reduce',      // 满减
            'full_discount',    // 满折
            'full_gift'         // 满赠
        ];
        $detail = self::operActivityDiscount($detail, $activityDiscountType);
        
        return $detail;
    }


    /**
     * 处理商品折扣活动
     *
     * @param object $detail     商品详情
     * @param object $activityDiscountType       要查詢的活动类型
     * @return array
     */
    public static function operActivityDiscount($detail, $activityDiscountType = []) {
        $activities = (new self)->getActivityDiscount($detail['id'], $activityDiscountType);

        $activityDiscountsTags = [];
        $activityDiscountsTypes = [];
        foreach ($activities as $key => $activity) {
            $activityDiscountsTypes[] = $activity['type'];
            $activityDiscountsTags[] = $activity['tag'];
        }

        $detail->activity_discounts = $activities;
        $detail->activity_discounts_types = join(',', array_filter(array_unique($activityDiscountsTypes)));
        $detail->activity_discounts_tags = array_filter(array_unique($activityDiscountsTags));
        return $detail;
    }



    // 处理活动规格
    public static function operActivitySkuPrice($detail, $sku_price)
    {
        if ($detail['activity_status'] == 'ing') {
            foreach ($sku_price as $key => $sku) {
                $sku_price[$key]['price'] = $sku['activity_price'];
            }
        }

        // 移除下架的规格
        foreach ($sku_price as $key => $sku) {
            if ($sku['status'] != 'up') {
                unset($sku_price[$key]);
            }
        }

        if ($detail['activity_status'] == 'ing') {
            // 活动开始的时候,price 就是活动价
            $prices = array_column($sku_price, 'price');
            $detail['price'] = $prices ? min($prices) : $detail['price'];      // min 里面不能是空数组
        } else if ($detail['activity_status'] == 'waiting') {
            // 活动未开始的时候,计算拿到最小活动价格,用来在活动未开始的时候,显示即将开始的活动价格
            $activityPrices = array_column($sku_price, 'activity_price');
            $detail['activity_price'] = $activityPrices ? min($activityPrices) : $detail['price'];
        }

        $detail['sales'] += $detail['show_sales'];

        $detail['sku_price'] = array_values($sku_price);
        $detail['stock'] = array_sum(array_column($sku_price, 'stock'));

        return $detail;
    }

    
    /**
     * (已测试)获取商品对应的促销活动(满减,满赠等,自动判断查询 redis 或者 数据库),只查询进行中的
     *
     * @param [type] $goods_id
     * @param array $activityTypes
     * @param array $type  all:获取当前商品参与的指定类型的所有活动,first:只取第一条
     * @return array
     */
    public function getActivityDiscount($goods_id, $activityTypes = [], $type = 'all')
    {
        if ($this->hasRedis()) {
            // 如果有活动,读取 redis,优惠类活动,自动过滤非活动时间的
            $activity = $this->getGoodsActivityDiscount($goods_id, $activityTypes, $type);
        } else {
            // 没有配置 redis,,这里只查询 进行中 的活动
            $activity = Activity::ing()
                ->where(function ($query) use ($goods_id) {
                    // goods_ids 里面有当前商品,或者 goods_ids 为null(所有商品都参与)
                    $query->where('find_in_set(' . $goods_id . ',goods_ids)')
                        ->whereOr('goods_ids', null);
                })
                ->where('type', 'in', $activityTypes)
                ->{$type == 'all' ? 'select' : 'find'}();
        }

        if ($type == 'all') {
            $newActivity = [];
            foreach ($activity as $act) {
                $newActivity[] = $this->formatActivityDiscount($act);
            }
        } else {
            $newActivity = $this->formatActivityDiscount($activity);
        }

        return $newActivity;
    }



    /**
     * (已测试)格式化促销活动的标签
     *
     * @param [type] $activity
     * @return void
     */
    public function formatActivityDiscount($activity) {
        $rules = $activity['rules'];

        $tags = Activity::formatRuleTags($activity['type'], $rules);
        
        $activity['tag'] = $tags[0] ?? '';
        $activity['tags'] = $tags;

        return $activity;
    }
}