'boolean', 'limit_type' => PURCHASE_LIMIT_TYPE::class, 'limit_period' => PURCHASE_LIMIT_PERIOD::class, ]; /** * 获取关联的商品 * * @return BelongsTo */ public function shopItem(): BelongsTo { return $this->belongsTo(ShopItem::class, 'shop_item_id'); } /** * 获取用户购买计数记录 * * @return HasMany */ public function userCounters(): HasMany { return $this->hasMany(ShopUserPurchaseCounter::class, 'limit_id'); } /** * 获取用户在此限购规则下的购买计数 * * @param int $userId 用户ID * @return int 购买计数 */ public function getUserPurchaseCount(int $userId): int { $counter = $this->userCounters() ->where('user_id', $userId) ->first(); if (!$counter) { return 0; } // 检查是否需要重置计数 if ($this->limit_period->shouldReset($counter->last_reset_time)) { $counter->resetCount(); return 0; } return $counter->current_count; } /** * 增加用户购买计数 * * @param int $userId 用户ID * @param int $quantity 购买数量 * @return bool */ public function incrementUserPurchaseCount(int $userId, int $quantity = 1): bool { $counter = ShopUserPurchaseCounter::firstOrCreate( [ 'limit_id' => $this->id, 'user_id' => $userId, ], [ 'current_count' => 0, 'last_reset_time' => now(), ] ); // 检查是否需要重置计数 if ($this->limit_period->shouldReset($counter->last_reset_time)) { $counter->resetCount(); } $counter->current_count += $quantity; return $counter->save(); } /** * 检查用户是否可以购买指定数量 * * @param int $userId 用户ID * @param int $quantity 购买数量 * @return array [是否可购买, 错误消息, 剩余可购买数量] */ public function canUserPurchase(int $userId, int $quantity): array { if (!$this->is_active) { return [true, '', $this->max_quantity]; // 限购规则未激活,不限制 } $currentCount = $this->getUserPurchaseCount($userId); $remainingQuantity = $this->max_quantity - $currentCount; if ($quantity > $remainingQuantity) { $periodName = $this->limit_period->getName($this->limit_period->value); $typeName = $this->limit_type->getName($this->limit_type->value); $message = match ($this->limit_type) { PURCHASE_LIMIT_TYPE::SINGLE_PURCHASE => "单次购买数量不能超过{$this->max_quantity}个", PURCHASE_LIMIT_TYPE::PERIODIC_PURCHASE => "{$periodName}内最多购买{$this->max_quantity}个,剩余可购买{$remainingQuantity}个", }; return [false, $message, $remainingQuantity]; } return [true, '', $remainingQuantity]; } /** * 获取限购类型文本 * * @return string */ public function getLimitTypeTextAttribute(): string { return $this->limit_type->getName($this->limit_type->value); } /** * 获取限购周期文本 * * @return string */ public function getLimitPeriodTextAttribute(): string { return $this->limit_period->getName($this->limit_period->value); } }