改为独立座驾模块
This commit is contained in:
@@ -8,9 +8,9 @@
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\ShopItem;
|
||||
use App\Models\Ride;
|
||||
use App\Models\User;
|
||||
use App\Models\UserPurchase;
|
||||
use App\Models\UserRidePurchase;
|
||||
use App\Support\ChatContentSanitizer;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Support\Carbon;
|
||||
@@ -18,23 +18,18 @@ use Illuminate\Support\Facades\DB;
|
||||
|
||||
/**
|
||||
* 聊天室座驾服务
|
||||
* 负责复用商店商品和用户购买记录完成座驾购买、续期、替换与进房展示。
|
||||
* 负责通过 rides 与 user_ride_purchases 完成座驾购买、续期、替换与进房展示。
|
||||
*/
|
||||
class RideService
|
||||
{
|
||||
/**
|
||||
* 获取全部上架座驾商品。
|
||||
*
|
||||
* @return Collection<int, ShopItem>
|
||||
* @return Collection<int, Ride>
|
||||
*/
|
||||
public function activeItems(): Collection
|
||||
{
|
||||
return ShopItem::query()
|
||||
->where('type', ShopItem::TYPE_RIDE)
|
||||
->where('is_active', true)
|
||||
->orderBy('sort_order')
|
||||
->orderBy('id')
|
||||
->get();
|
||||
return Ride::active();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -42,7 +37,7 @@ class RideService
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function formatItem(ShopItem $item): array
|
||||
public function formatItem(Ride $item): array
|
||||
{
|
||||
return [
|
||||
'id' => $item->id,
|
||||
@@ -60,13 +55,12 @@ class RideService
|
||||
/**
|
||||
* 获取用户当前有效座驾,若已过期则自动标记为 expired。
|
||||
*/
|
||||
public function currentRide(User $user): ?UserPurchase
|
||||
public function currentRide(User $user): ?UserRidePurchase
|
||||
{
|
||||
$purchase = UserPurchase::query()
|
||||
->with('shopItem')
|
||||
$purchase = UserRidePurchase::query()
|
||||
->with('ride')
|
||||
->where('user_id', $user->id)
|
||||
->where('status', 'active')
|
||||
->whereHas('shopItem', fn ($query) => $query->where('type', ShopItem::TYPE_RIDE))
|
||||
->orderByDesc('expires_at')
|
||||
->first();
|
||||
|
||||
@@ -92,7 +86,7 @@ class RideService
|
||||
public function formatCurrentRide(User $user): ?array
|
||||
{
|
||||
$purchase = $this->currentRide($user);
|
||||
if (! $purchase || ! $purchase->shopItem) {
|
||||
if (! $purchase || ! $purchase->ride) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -106,14 +100,13 @@ class RideService
|
||||
*/
|
||||
public function purchaseRecords(User $user, int $limit = 20): array
|
||||
{
|
||||
return UserPurchase::query()
|
||||
->with('shopItem')
|
||||
return UserRidePurchase::query()
|
||||
->with('ride')
|
||||
->where('user_id', $user->id)
|
||||
->whereHas('shopItem', fn ($query) => $query->where('type', ShopItem::TYPE_RIDE))
|
||||
->latest()
|
||||
->limit($limit)
|
||||
->get()
|
||||
->map(fn (UserPurchase $purchase) => $this->formatPurchase($purchase))
|
||||
->map(fn (UserRidePurchase $purchase) => $this->formatPurchase($purchase))
|
||||
->values()
|
||||
->all();
|
||||
}
|
||||
@@ -123,9 +116,9 @@ class RideService
|
||||
*
|
||||
* @return array{ok:bool, message:string, current_ride?:array<string, mixed>}
|
||||
*/
|
||||
public function buy(User $user, ShopItem $item): array
|
||||
public function buy(User $user, Ride $item): array
|
||||
{
|
||||
if (! $item->isRide() || ! $item->is_active) {
|
||||
if (! $item->is_active) {
|
||||
return ['ok' => false, 'message' => '该座驾暂未上架。'];
|
||||
}
|
||||
|
||||
@@ -142,35 +135,33 @@ class RideService
|
||||
$now = Carbon::now();
|
||||
|
||||
// 先清理已过期的 active 座驾,避免旧状态影响替换判断。
|
||||
UserPurchase::query()
|
||||
UserRidePurchase::query()
|
||||
->where('user_id', $user->id)
|
||||
->where('status', 'active')
|
||||
->whereNotNull('expires_at')
|
||||
->where('expires_at', '<=', $now)
|
||||
->whereHas('shopItem', fn ($query) => $query->where('type', ShopItem::TYPE_RIDE))
|
||||
->update(['status' => 'expired']);
|
||||
|
||||
$activeRide = UserPurchase::query()
|
||||
->with('shopItem')
|
||||
$activeRide = UserRidePurchase::query()
|
||||
->with('ride')
|
||||
->where('user_id', $user->id)
|
||||
->where('status', 'active')
|
||||
->whereHas('shopItem', fn ($query) => $query->where('type', ShopItem::TYPE_RIDE))
|
||||
->orderByDesc('expires_at')
|
||||
->first();
|
||||
|
||||
// 座驾购买必须先扣金币,后续续期或替换都在同一个事务内完成。
|
||||
$user->decrement('jjb', $item->price);
|
||||
|
||||
if ($activeRide && (int) $activeRide->shop_item_id === (int) $item->id) {
|
||||
if ($activeRide && (int) $activeRide->ride_id === (int) $item->id) {
|
||||
$baseTime = $activeRide->expires_at && $activeRide->expires_at->greaterThan($now)
|
||||
? $activeRide->expires_at
|
||||
: $now;
|
||||
|
||||
// 同款续购先取消旧 active,再创建新 active,既保留购买记录,又保持当前座驾唯一。
|
||||
$activeRide->update(['status' => 'cancelled']);
|
||||
UserPurchase::create([
|
||||
UserRidePurchase::create([
|
||||
'user_id' => $user->id,
|
||||
'shop_item_id' => $item->id,
|
||||
'ride_id' => $item->id,
|
||||
'status' => 'active',
|
||||
'price_paid' => $item->price,
|
||||
'expires_at' => $baseTime->copy()->addDays($days),
|
||||
@@ -184,9 +175,9 @@ class RideService
|
||||
$activeRide->update(['status' => 'cancelled']);
|
||||
}
|
||||
|
||||
UserPurchase::create([
|
||||
UserRidePurchase::create([
|
||||
'user_id' => $user->id,
|
||||
'shop_item_id' => $item->id,
|
||||
'ride_id' => $item->id,
|
||||
'status' => 'active',
|
||||
'price_paid' => $item->price,
|
||||
'expires_at' => $now->copy()->addDays($days),
|
||||
@@ -208,7 +199,7 @@ class RideService
|
||||
public function buildPresencePayload(User $user): ?array
|
||||
{
|
||||
$purchase = $this->currentRide($user);
|
||||
$item = $purchase?->shopItem;
|
||||
$item = $purchase?->ride;
|
||||
$rideKey = $item?->rideKey();
|
||||
|
||||
if (! $purchase || ! $item || ! $rideKey) {
|
||||
@@ -234,9 +225,9 @@ class RideService
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function formatPurchase(UserPurchase $purchase): array
|
||||
private function formatPurchase(UserRidePurchase $purchase): array
|
||||
{
|
||||
$item = $purchase->shopItem;
|
||||
$item = $purchase->ride;
|
||||
|
||||
return [
|
||||
'id' => $purchase->id,
|
||||
|
||||
Reference in New Issue
Block a user