'boolean', 'display_attributes' => \App\Module\Shop\Casts\ShopDisplayAttributesCast::class, ]; /** * 获取关联的分类 * * @return BelongsTo */ public function category(): BelongsTo { return $this->belongsTo(ShopCategory::class, 'category_id'); } /** * 获取关联的消耗组 * * @return BelongsTo */ public function consumeGroup(): BelongsTo { return $this->belongsTo(\App\Module\Game\Models\GameConsumeGroup::class, 'consume_group_id'); } /** * 获取关联的奖励组 * * @return BelongsTo */ public function rewardGroup(): BelongsTo { return $this->belongsTo(\App\Module\Game\Models\GameRewardGroup::class, 'reward_group_id'); } /** * 获取用户已购买数量 * * @param int $userId 用户ID * @return int 已购买数量 */ public function getUserBoughtCount(int $userId): int { return ShopPurchaseLog::where('user_id', $userId) ->where('shop_item_id', $this->id) ->sum('quantity'); } /** * 获取该商品关联的促销活动 * * @return BelongsToMany */ public function promotions(): BelongsToMany { return $this->belongsToMany( ShopPromotion::class, 'shop_promotion_items', 'shop_item_id', 'promotion_id' )->withPivot('custom_discount_value') ->withTimestamps(); } /** * 获取商品的促销关联记录 * * @return HasMany */ public function promotionItems(): HasMany { return $this->hasMany(ShopPromotionItem::class, 'shop_item_id'); } /** * 获取当前有效的促销活动 * * @return ShopPromotion|null */ public function getActivePromotion(): ?ShopPromotion { $now = now(); return $this->promotions() ->where('is_active', true) ->where(function ($query) use ($now) { $query->whereNull('start_time') ->orWhere('start_time', '<=', $now); }) ->where(function ($query) use ($now) { $query->whereNull('end_time') ->orWhere('end_time', '>=', $now); }) ->orderBy('sort_order') ->first(); } /** * 获取折扣后的价格 * 注意:由于商品不再有固定价格,此方法需要根据消耗组重新实现 * * @return int */ public function getDiscountedPrice(): int { // TODO: 根据消耗组重新实现价格计算逻辑 $promotion = $this->getActivePromotion(); if (!$promotion) { return 0; // 暂时返回0,需要根据消耗组计算 } $promotionItem = $this->promotionItems() ->where('promotion_id', $promotion->id) ->first(); $customDiscountValue = $promotionItem ? $promotionItem->custom_discount_value : null; return $promotion->calculateDiscountedPrice(0, $customDiscountValue); // 暂时传入0 } /** * 记录购买记录 * 注意:由于商品结构变更,此方法需要根据新的消耗组和奖励组重新实现 * * @param int $userId 用户ID * @param int $quantity 购买数量 * @param int $totalPrice 总价 * @return ShopPurchaseLog 购买记录 */ public function recordPurchase(int $userId, int $quantity, int $totalPrice): ShopPurchaseLog { $log = new ShopPurchaseLog([ 'user_id' => $userId, 'shop_item_id' => $this->id, 'item_id' => null, // 不再关联单一物品 'quantity' => $quantity, 'price' => 0, // 不再有固定价格 'total_price' => $totalPrice, 'currency_id' => null, // 不再有单一货币类型 'purchase_time' => now(), 'ip_address' => request()->ip(), 'device_info' => request()->userAgent(), ]); $log->save(); return $log; } /** * 获取关联的限购配置 * * @return HasMany */ public function purchaseLimits(): HasMany { return $this->hasMany(ShopPurchaseLimit::class, 'shop_item_id'); } /** * 获取激活的限购配置 * * @return HasMany */ public function activePurchaseLimits(): HasMany { return $this->purchaseLimits()->where('is_active', true)->orderBy('sort_order'); } /** * 检查用户是否可以购买指定数量(包含所有限购规则) * * @param int $userId 用户ID * @param int $quantity 购买数量 * @return array [是否可购买, 错误消息, 剩余可购买数量] */ public function canUserPurchaseWithLimits(int $userId, int $quantity): array { // 检查单次购买限制 if ($this->max_single_buy > 0 && $quantity > $this->max_single_buy) { return [false, "单次购买数量不能超过{$this->max_single_buy}个", $this->max_single_buy]; } // 检查所有激活的限购配置 $activeLimits = $this->activePurchaseLimits; $minRemainingQuantity = PHP_INT_MAX; foreach ($activeLimits as $limit) { list($canPurchase, $errorMessage, $remainingQuantity) = $limit->canUserPurchase($userId, $quantity); if (!$canPurchase) { return [false, $errorMessage, $remainingQuantity]; } $minRemainingQuantity = min($minRemainingQuantity, $remainingQuantity); } $finalRemainingQuantity = $minRemainingQuantity === PHP_INT_MAX ? $quantity : $minRemainingQuantity; return [true, '', $finalRemainingQuantity]; } /** * 更新所有相关的限购计数 * * @param int $userId 用户ID * @param int $quantity 购买数量 * @return bool */ public function updatePurchaseLimitCounters(int $userId, int $quantity): bool { $activeLimits = $this->activePurchaseLimits; foreach ($activeLimits as $limit) { $limit->incrementUserPurchaseCount($userId, $quantity); } return true; } }