6
0
Fork 0
jiqu-library-server/app/Services/DrawActivityService.php

98 lines
2.7 KiB
PHP

<?php
namespace App\Services;
use App\Enums\DrawLogStatus;
use App\Enums\DrawPrizeType;
use App\Exceptions\BizException;
use App\Models\DrawActivity;
use App\Models\DrawActivityPrize;
use App\Models\DrawLog;
use App\Models\User;
use Illuminate\Support\Facades\DB;
class DrawActivityService
{
/**
* 活动抽奖
*
* @param \App\Models\DrawActivity $drawActivity
* @param \App\Models\User $user
* @return \App\Models\DrawLog
*/
public function draw(DrawActivity $drawActivity, User $user): DrawLog
{
if (! $drawActivity->isPublished()) {
throw new BizException('抽奖活动未发布');
}
if ($drawActivity->isUnstart()) {
throw new BizException('抽奖活动未开始');
}
if ($drawActivity->isClosed()) {
throw new BizException('抽奖活动已结束');
}
(new DrawTicketService())->change($user, $drawActivity, -1, '活动抽奖');
$prize = $this->getDrawActivityPrize($drawActivity);
// 如果限制了奖品数量,则需扣除奖品库存
if ($prize->limited) {
$prize->update([
'stock' => DB::raw('stock-1'),
'winnings' => DB::raw('winnings+1'),
]);
} else {
$prize->increment('winnings', 1);
}
$drawLog = DrawLog::create([
'user_id' => $user->id,
'draw_activity_id' => $drawActivity->id,
'draw_activity_prize_id' => $prize->id,
'status' => match ($prize->type) {
DrawPrizeType::None => DrawLogStatus::Completed,
default => DrawLogStatus::Pending,
},
]);
return $drawLog->setRelation('prize', $prize);
}
/**
* @param \App\Models\DrawActivity $drawActivity
* @return \App\Models\DrawActivityPrize
*/
protected function getDrawActivityPrize(DrawActivity $drawActivity): DrawActivityPrize
{
$drawActivityPrizes = $drawActivity->prizes()->get();
// 过滤权重为0或库存不足的奖品
$prizes = $drawActivityPrizes->filter(function ($item) {
if ($item->weight === 0 || ($item->limited && $item->stock === 0)) {
return false;
}
return true;
});
$max = $prizes->sum('weight');
if ($max > 0) {
$rand = mt_rand($min = 1, $max);
foreach ($prizes as $prize) {
if ($rand <= $prize->weight + $min) {
return $prize;
}
$min += $prize->weight;
}
}
throw new BizException('抽奖活动异常');
}
}