fix: 增强配置发布校验与关闭玩法清理提示

1. 发布赔率、玩法配置和风控封顶草稿前校验空配置、重复项、金额范围和合法性
2. 限制赔率返水与佣金比例在 0 到 1 之间
3. 投注预览和下单遇到已关闭玩法时返回需清理注项明细
This commit is contained in:
2026-05-16 09:54:47 +08:00
parent 87637f2e4a
commit f7f6c58b02
8 changed files with 299 additions and 6 deletions

View File

@@ -10,6 +10,7 @@ use App\Models\PlayConfigItem;
use App\Models\PlayConfigVersion;
use Illuminate\Support\Facades\DB;
use App\Lottery\ConfigVersionStatus;
use Illuminate\Validation\ValidationException;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
/** 后台:玩法配置版本({@see play_config_versions} / {@see play_config_items} */
@@ -113,6 +114,7 @@ final class PlayConfigStreamService
public function publish(PlayConfigVersion $draft, AdminUser $admin, ?Request $request = null): void
{
$this->validatePublishableDraft($draft);
$before = $this->snapshotVersion($draft);
DB::transaction(function () use ($draft, $admin): void {
@@ -178,4 +180,51 @@ final class PlayConfigStreamService
'items_count' => $v->items()->count(),
];
}
private function validatePublishableDraft(PlayConfigVersion $draft): void
{
$items = $draft->items()->orderBy('play_code')->get();
$allowedPlayCodes = array_fill_keys(
PlayType::query()->pluck('play_code')->all(),
true,
);
$errors = [];
$seenPlayCodes = [];
if ($items->isEmpty()) {
$errors['items'][] = '草稿至少需要一条玩法配置';
}
foreach ($items as $index => $row) {
$playCode = (string) $row->play_code;
$minBet = (int) $row->min_bet_amount;
$maxBet = (int) $row->max_bet_amount;
if (! isset($allowedPlayCodes[$playCode])) {
$errors["items.$index.play_code"][] = '玩法不存在';
}
if (isset($seenPlayCodes[$playCode])) {
$errors["items.$index.play_code"][] = '玩法重复';
}
$seenPlayCodes[$playCode] = true;
if ($minBet < 0) {
$errors["items.$index.min_bet_amount"][] = '最小下注额不能小于 0';
}
if ($maxBet < 0) {
$errors["items.$index.max_bet_amount"][] = '最大下注额不能小于 0';
}
if ($maxBet < $minBet) {
$errors["items.$index.max_bet_amount"][] = '最大下注额不能小于最小下注额';
}
}
if ($errors !== []) {
throw ValidationException::withMessages($errors);
}
}
}