Files
lotteryLaravel/app/Services/Ticket/RiskPoolRealtimePublisher.php
kang 618201f980 feat: 重构注单控制器以复用共享筛选逻辑
新增 TicketItemListFilters trait,用于封装注单列表的通用筛选逻辑。
更新 AdminPlayerTicketItemsIndexController、AdminTicketItemIndexController 与 TicketItemsIndexController,统一使用新的注单编号搜索与订单日期范围筛选方法,提升代码复用性与可读性。
增强 AdminRiskPoolManualStatusController:支持发布手动停售状态变更通知。
优化 RiskPoolService 与 TicketWalletService:钱包资金变动后实时通知余额更新。
更新测试用例,确保重构后功能行为保持一致。
2026-05-26 17:14:19 +08:00

80 lines
2.4 KiB
PHP

<?php
namespace App\Services\Ticket;
use App\Models\Draw;
use App\Models\RiskPool;
use App\Services\Draw\LotteryHallRealtimeBroadcaster;
/**
* 风险池占用变化后推送 `risk.warning` / `risk.sold_out`(频道 `lottery-hall`)。
*/
final class RiskPoolRealtimePublisher
{
private const WARNING_RATIO = 0.8;
/** @var array<int, string> */
private array $drawNoById = [];
public function __construct(
private readonly LotteryHallRealtimeBroadcaster $hallRealtime,
) {}
public function publishAfterLock(
int $drawId,
string $normalizedNumber,
int $soldOutStatusBefore,
int $lockedAmountBefore,
int $totalCapBefore,
RiskPool $poolAfter,
): void {
$drawNo = $this->resolveDrawNo($drawId);
$normalizedNumber = strtoupper(trim($normalizedNumber));
$totalCap = (int) $poolAfter->total_cap_amount;
if ($totalCap < 1) {
$totalCap = max(1, $totalCapBefore);
}
$soldOutAfter = (int) $poolAfter->sold_out_status;
if ($soldOutAfter === 1 && $soldOutStatusBefore !== 1) {
$this->hallRealtime->notifyRiskSoldOut($drawId, $drawNo, $normalizedNumber);
}
$lockedAfter = (int) $poolAfter->locked_amount;
$usageBefore = $totalCapBefore > 0 ? $lockedAmountBefore / $totalCapBefore : 0.0;
$usageAfter = $totalCap > 0 ? $lockedAfter / $totalCap : 1.0;
if ($usageAfter >= self::WARNING_RATIO && $usageBefore < self::WARNING_RATIO) {
$this->hallRealtime->notifyRiskWarning(
$drawId,
$drawNo,
$normalizedNumber,
$usageAfter,
);
}
}
public function publishManualSoldOut(Draw $draw, string $normalizedNumber): void
{
$this->hallRealtime->notifyRiskSoldOut(
(int) $draw->id,
(string) $draw->draw_no,
strtoupper(trim($normalizedNumber)),
);
}
private function resolveDrawNo(int $drawId): string
{
if (isset($this->drawNoById[$drawId])) {
return $this->drawNoById[$drawId];
}
$drawNo = Draw::query()->whereKey($drawId)->value('draw_no');
$resolved = is_string($drawNo) && $drawNo !== '' ? $drawNo : (string) $drawId;
$this->drawNoById[$drawId] = $resolved;
return $resolved;
}
}