| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 |
- <?php
- namespace App\Module\Shop\Models;
- use Illuminate\Database\Eloquent\Relations\BelongsTo;
- use Illuminate\Database\Eloquent\Relations\BelongsToMany;
- use Illuminate\Database\Eloquent\Relations\HasMany;
- use Illuminate\Support\Facades\DB;
- use UCore\ModelCore;
- use App\Module\Shop\Models\ShopCategory;
- use App\Module\Shop\Models\ShopPromotion;
- use App\Module\Shop\Models\ShopPromotionItem;
- use App\Module\Shop\Models\ShopPurchaseLog;
- /**
- * 商店物品模型
- *
- * field start
- * @property int $id 商品ID,主键
- * @property string $name 商品名称
- * @property string $description 商品描述
- * @property int $category_id 分类ID,外键关联kku_shop_categories表
- * @property string $category_name 分类名称(字符串格式,区别于现有分类机制)
- * @property int $consume_group_id 消耗组ID,外键关联kku_game_consume_groups表
- * @property int $reward_group_id 奖励组ID,外键关联kku_game_reward_groups表
- * @property int $max_single_buy 单次最大购买数量(0表示无限制)
- * @property bool $is_active 是否激活(0:否, 1:是)
- * @property int $sort_order 排序权重
- * @property string $image 商品图片
- * @property string $start_time 上架时间
- * @property string $end_time 下架时间
- * @property \Carbon\Carbon $created_at 创建时间
- * @property \Carbon\Carbon $updated_at 更新时间
- * field end
- */
- class ShopItem extends ModelCore
- {
- /**
- * 与模型关联的表名
- *
- * @var string
- */
- protected $table = 'shop_items';
- /**
- * 可批量赋值的属性
- *
- * @var array
- */
- protected $fillable = [
- 'name',
- 'description',
- 'category_id',
- 'category_name',
- 'consume_group_id',
- 'reward_group_id',
- 'max_single_buy',
- 'is_active',
- 'sort_order',
- 'image',
- 'start_time',
- 'end_time',
- ];
- /**
- * 应该被转换为日期的属性
- *
- * @var array
- */
- protected $dates = [
- 'start_time',
- 'end_time',
- 'created_at',
- 'updated_at',
- ];
- /**
- * 应该被转换为原生类型的属性
- *
- * @var array
- */
- protected $casts = [
- 'is_active' => 'boolean',
- ];
- /**
- * 获取关联的分类
- *
- * @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;
- }
- }
|