| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372 |
- <?php
- namespace App\Module\Shop\Logics;
- use App\Module\Shop\Models\ShopCategory;
- use App\Module\Shop\Models\ShopItem;
- use App\Module\Shop\Models\ShopPromotion;
- use App\Module\Shop\Models\ShopPromotionItem;
- use App\Module\Shop\Models\ShopPurchaseLog;
- use Carbon\Carbon;
- use Illuminate\Database\Eloquent\Collection;
- /**
- * 商店逻辑类
- *
- * 处理商店相关的业务逻辑,包括获取商品列表、检查购买限制等。
- * 该类是商店模块的核心业务逻辑处理类,由ShopService调用。
- */
- class ShopLogic
- {
- /**
- * 获取商店商品列表
- *
- * @param array $filters 过滤条件
- * @return Collection 商品列表
- */
- public function getShopItems(array $filters = []): Collection
- {
- $query = ShopItem::with([
- 'category',
- 'consumeGroup.consumeItems',
- 'rewardGroup.rewardItems',
- 'promotions' => function ($q) {
- $now = Carbon::now();
- $q->where('is_active', true)
- ->where(function ($q) use ($now) {
- $q->whereNull('start_time')
- ->orWhere('start_time', '<=', $now);
- })
- ->where(function ($q) use ($now) {
- $q->whereNull('end_time')
- ->orWhere('end_time', '>=', $now);
- })
- ->orderBy('sort_order', 'asc');
- }
- ])
- ->where('is_active', true)
- ->where(function ($q) {
- $now = Carbon::now();
- $q->where(function ($q) use ($now) {
- $q->whereNull('start_time')
- ->whereNull('end_time');
- })->orWhere(function ($q) use ($now) {
- $q->where('start_time', '<=', $now)
- ->where('end_time', '>=', $now);
- })->orWhere(function ($q) use ($now) {
- $q->where('start_time', '<=', $now)
- ->whereNull('end_time');
- })->orWhere(function ($q) use ($now) {
- $q->whereNull('start_time')
- ->where('end_time', '>=', $now);
- });
- });
- // 应用过滤条件
- if (isset($filters['category_id'])) {
- $query->where('category_id', $filters['category_id']);
- }
- // 注意:由于商品结构已改为消耗组和奖励组模式,不再支持按item_id过滤
- // if (isset($filters['item_id'])) {
- // $query->where('item_id', $filters['item_id']);
- // }
- if (isset($filters['keyword'])) {
- $keyword = $filters['keyword'];
- $query->where(function ($q) use ($keyword) {
- $q->where('name', 'like', "%{$keyword}%")
- ->orWhere('description', 'like', "%{$keyword}%");
- // 注意:由于商品结构已改为消耗组和奖励组模式,不再支持按关联物品名称搜索
- // ->orWhereHas('item', function ($q) use ($keyword) {
- // $q->where('name', 'like', "%{$keyword}%");
- // });
- });
- }
- // 是否只获取促销商品
- if (isset($filters['only_promotion']) && $filters['only_promotion']) {
- $query->whereHas('promotions', function ($q) {
- $now = Carbon::now();
- $q->where('is_active', true)
- ->where(function ($q) use ($now) {
- $q->whereNull('start_time')
- ->orWhere('start_time', '<=', $now);
- })
- ->where(function ($q) use ($now) {
- $q->whereNull('end_time')
- ->orWhere('end_time', '>=', $now);
- });
- });
- }
- // 按促销活动过滤
- if (isset($filters['promotion_id'])) {
- $query->whereHas('promotions', function ($q) use ($filters) {
- $q->where('id', $filters['promotion_id']);
- });
- }
- // 排序
- $query->orderBy('sort_order', 'asc')
- ->orderBy('id', 'asc');
- // 获取商品列表
- $items = $query->get();
- // 注意:由于商品结构已改为消耗组和奖励组模式,不再有固定价格
- // 折扣价格计算需要根据消耗组和促销活动重新实现
- // foreach ($items as $item) {
- // $item->original_price = $item->price;
- // $item->discounted_price = $item->getDiscountedPrice();
- // $item->has_discount = $item->discounted_price < $item->original_price;
- // $item->discount_percentage = $item->original_price > 0
- // ? round((1 - $item->discounted_price / $item->original_price) * 100)
- // : 0;
- // }
- return $items;
- }
- /**
- * 获取商店分类列表
- *
- * @param bool $onlyActive 是否只获取激活的分类
- * @return Collection 分类列表
- */
- public function getShopCategories(bool $onlyActive = true): Collection
- {
- $query = ShopCategory::query();
- if ($onlyActive) {
- $query->where('is_active', true);
- }
- return $query->orderBy('sort_order', 'asc')->get();
- }
- /**
- * 获取商店分类树
- *
- * @param bool $onlyActive 是否只获取激活的分类
- * @return array 分类树
- */
- public function getShopCategoryTree(bool $onlyActive = true): array
- {
- return ShopCategory::getCategoryTree($onlyActive);
- }
- /**
- * 检查用户购买限制
- *
- * @param int $userId 用户ID
- * @param ShopItem $shopItem 商品
- * @param int $quantity 购买数量
- * @return array [是否可购买, 错误消息]
- */
- public function checkBuyLimit(int $userId, ShopItem $shopItem, int $quantity): array
- {
- // 检查商品是否激活
- if (!$shopItem->is_active) {
- return [false, '该商品已下架'];
- }
- // 检查商品是否在有效期内
- $now = Carbon::now();
- if (($shopItem->start_time && $now < $shopItem->start_time) ||
- ($shopItem->end_time && $now > $shopItem->end_time)) {
- return [false, '该商品不在销售时间内'];
- }
- // 检查购买数量是否有效
- if ($quantity <= 0) {
- return [false, '购买数量必须大于0'];
- }
- // 检查购买限制
- if ($shopItem->max_buy > 0) {
- $boughtCount = $shopItem->getUserBoughtCount($userId);
- if ($boughtCount + $quantity > $shopItem->max_buy) {
- return [false, "超出购买限制,最多还能购买" . ($shopItem->max_buy - $boughtCount) . "个"];
- }
- }
- // 注意:由于商品结构已改为消耗组和奖励组模式,不再检查单一关联物品
- // 需要检查消耗组和奖励组是否存在
- if ($shopItem->consume_group_id && !$shopItem->consumeGroup) {
- return [false, '商品关联的消耗组不存在'];
- }
- if ($shopItem->reward_group_id && !$shopItem->rewardGroup) {
- return [false, '商品关联的奖励组不存在'];
- }
- return [true, ''];
- }
- /**
- * 记录购买日志
- *
- * @param int $userId 用户ID
- * @param ShopItem $shopItem 商品
- * @param int $quantity 购买数量
- * @param int $totalPrice 总价
- * @return ShopPurchaseLog 购买日志
- */
- public function recordPurchase(int $userId, ShopItem $shopItem, int $quantity, int $totalPrice): ShopPurchaseLog
- {
- return $shopItem->recordPurchase($userId, $quantity, $totalPrice);
- }
- /**
- * 获取用户购买记录
- *
- * @param int $userId 用户ID
- * @param array $filters 过滤条件
- * @return Collection 购买记录
- */
- public function getUserPurchaseHistory(int $userId, array $filters = []): Collection
- {
- $query = ShopPurchaseLog::with(['shopItem'])
- ->where('user_id', $userId);
- // 应用过滤条件
- if (isset($filters['shop_item_id'])) {
- $query->where('shop_item_id', $filters['shop_item_id']);
- }
- if (isset($filters['item_id'])) {
- $query->where('item_id', $filters['item_id']);
- }
- if (isset($filters['start_date'])) {
- $query->where('purchase_time', '>=', $filters['start_date']);
- }
- if (isset($filters['end_date'])) {
- $query->where('purchase_time', '<=', $filters['end_date']);
- }
- // 排序
- $query->orderBy('purchase_time', 'desc');
- return $query->get();
- }
- /**
- * 获取促销活动列表
- *
- * @param array $filters 过滤条件
- * @return Collection 促销活动列表
- */
- public function getPromotions(array $filters = []): Collection
- {
- $query = ShopPromotion::with('items');
- // 是否只获取激活的促销活动
- if (isset($filters['only_active']) && $filters['only_active']) {
- $query->where('is_active', true);
- }
- // 是否只获取当前有效的促销活动
- if (isset($filters['only_valid']) && $filters['only_valid']) {
- $now = Carbon::now();
- $query->where('is_active', true)
- ->where(function ($q) use ($now) {
- $q->whereNull('start_time')
- ->orWhere('start_time', '<=', $now);
- })
- ->where(function ($q) use ($now) {
- $q->whereNull('end_time')
- ->orWhere('end_time', '>=', $now);
- });
- }
- // 按分类过滤
- if (isset($filters['category_id'])) {
- $query->whereHas('items', function ($q) use ($filters) {
- $q->where('category_id', $filters['category_id']);
- });
- }
- // 按关键词搜索
- if (isset($filters['keyword'])) {
- $keyword = $filters['keyword'];
- $query->where(function ($q) use ($keyword) {
- $q->where('name', 'like', "%{$keyword}%")
- ->orWhere('description', 'like', "%{$keyword}%");
- });
- }
- // 排序
- $query->orderBy('sort_order', 'asc')
- ->orderBy('id', 'asc');
- return $query->get();
- }
- /**
- * 获取促销活动详情
- *
- * @param int $promotionId 促销活动ID
- * @return ShopPromotion|null 促销活动详情
- */
- public function getPromotionDetail(int $promotionId): ?ShopPromotion
- {
- return ShopPromotion::with('items')->find($promotionId);
- }
- /**
- * 添加商品到促销活动
- *
- * @param int $promotionId 促销活动ID
- * @param int $shopItemId 商品ID
- * @param int|null $customDiscountValue 自定义折扣值
- * @return ShopPromotionItem 促销商品关联
- */
- public function addItemToPromotion(int $promotionId, int $shopItemId, ?int $customDiscountValue = null): ShopPromotionItem
- {
- // 检查促销活动是否存在
- ShopPromotion::findOrFail($promotionId);
- // 检查商品是否存在
- ShopItem::findOrFail($shopItemId);
- // 检查商品是否已经在促销活动中
- $existingItem = ShopPromotionItem::where('promotion_id', $promotionId)
- ->where('shop_item_id', $shopItemId)
- ->first();
- if ($existingItem) {
- // 更新自定义折扣值
- $existingItem->custom_discount_value = $customDiscountValue;
- $existingItem->save();
- return $existingItem;
- }
- // 创建新的关联
- $promotionItem = new ShopPromotionItem([
- 'promotion_id' => $promotionId,
- 'shop_item_id' => $shopItemId,
- 'custom_discount_value' => $customDiscountValue,
- ]);
- $promotionItem->save();
- return $promotionItem;
- }
- /**
- * 从促销活动中移除商品
- *
- * @param int $promotionId 促销活动ID
- * @param int $shopItemId 商品ID
- * @return bool 是否成功
- */
- public function removeItemFromPromotion(int $promotionId, int $shopItemId): bool
- {
- return ShopPromotionItem::where('promotion_id', $promotionId)
- ->where('shop_item_id', $shopItemId)
- ->delete() > 0;
- }
- }
|