Files
lotteryLaravel/app/Services/Ticket/RiskPoolRealtimePublisher.php
kang 2ea3e810a0
Some checks failed
lotterLaravel CI / test (push) Has been cancelled
lotterLaravel E2E / e2e-api (push) Has been cancelled
feat(risk): 支持按开注商隔离风险池并新增经营报表
2026-07-10 10:23:30 +08:00

90 lines
2.6 KiB
PHP

<?php
namespace App\Services\Ticket;
use App\Models\BetProvider;
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 $providerCode,
string $normalizedNumber,
int $soldOutStatusBefore,
int $lockedAmountBefore,
int $totalCapBefore,
RiskPool $poolAfter,
): void {
if (strtoupper(trim($providerCode)) !== BetProvider::DEFAULT_CODE) {
return;
}
$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, string $providerCode): void
{
if (strtoupper(trim($providerCode)) !== BetProvider::DEFAULT_CODE) {
return;
}
$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;
}
}