feat: 添加新的错误码以支持投注功能,更新数据库填充器以增强玩法和赔率配置,扩展 API 路由以支持风险池管理

This commit is contained in:
2026-05-11 11:52:23 +08:00
parent 067c2b39f5
commit 058f596f34
29 changed files with 2300 additions and 122 deletions

View File

@@ -16,80 +16,117 @@ use Illuminate\Support\Facades\DB;
/**
* 阶段 4:写入首套 **active** 玩法配置 / 赔率 / 风控封顶版本(依赖 {@see PlayTypeSeeder}{@see CurrencySeeder})。
*
* 幂等:仅当三套版本均已有 active 行时跳过;否则只补缺失的一类(避免「仅有 play active 时整段被跳过」导致 /play/effective 不可用)。
*/
class OperationalConfigV1Seeder extends Seeder
{
public function run(): void
{
if (PlayConfigVersion::query()->where('status', ConfigVersionStatus::Active->value)->exists()) {
$hasPlay = PlayConfigVersion::query()
->where('status', ConfigVersionStatus::Active->value)
->exists();
$hasOdds = OddsVersion::query()
->where('status', ConfigVersionStatus::Active->value)
->exists();
$hasRisk = RiskCapVersion::query()
->where('status', ConfigVersionStatus::Active->value)
->exists();
if ($hasPlay && $hasOdds && $hasRisk) {
return;
}
DB::transaction(function (): void {
$playVersion = PlayConfigVersion::query()->create([
'version_no' => 1,
'status' => ConfigVersionStatus::Active->value,
'effective_at' => now(),
'updated_by' => null,
'reason' => 'seed:v1',
]);
foreach (PlayType::query()->orderBy('sort_order')->orderBy('play_code')->get() as $pt) {
PlayConfigItem::query()->create([
'version_id' => $playVersion->id,
'play_code' => $pt->play_code,
'is_enabled' => (bool) $pt->is_enabled,
'min_bet_amount' => 100,
'max_bet_amount' => 500_000_000,
'display_order' => (int) $pt->sort_order,
'rule_text_zh' => null,
'rule_text_en' => null,
'rule_text_ne' => null,
'extra_config_json' => null,
]);
DB::transaction(function () use ($hasPlay, $hasOdds, $hasRisk): void {
if (! $hasPlay) {
$this->seedActivePlayConfigVersion();
}
$oddsVersion = OddsVersion::query()->create([
'version_no' => 1,
'status' => ConfigVersionStatus::Active->value,
'effective_at' => now(),
'updated_by' => null,
'reason' => 'seed:v1',
]);
/** 对齐界面文档 §5.5:头/二/三/特别/安慰odds_value = 乘数×10000NPR 基准展示口径) */
foreach (PlayType::query()->orderBy('sort_order')->orderBy('play_code')->get() as $pt) {
foreach (OddsStandardScopes::PRESET_ODDS_BY_SCOPE as $scope => $oddsValue) {
OddsItem::query()->create([
'version_id' => $oddsVersion->id,
'play_code' => $pt->play_code,
'prize_scope' => $scope,
'odds_value' => $oddsValue,
'rebate_rate' => 0,
'commission_rate' => 0,
'currency_code' => 'NPR',
'extra_config_json' => null,
]);
}
if (! $hasOdds) {
$this->seedActiveOddsVersion();
}
$riskVersion = RiskCapVersion::query()->create([
'version_no' => 1,
'status' => ConfigVersionStatus::Active->value,
'effective_at' => now(),
'updated_by' => null,
'reason' => 'seed:v1',
]);
foreach (['0000', '1234', '9999'] as $num) {
RiskCapItem::query()->create([
'version_id' => $riskVersion->id,
'draw_id' => null,
'normalized_number' => $num,
'cap_amount' => 50_000_000_000,
'cap_type' => 'per_number',
]);
if (! $hasRisk) {
$this->seedActiveRiskCapVersion();
}
});
}
private function seedActivePlayConfigVersion(): void
{
$versionNo = (int) (PlayConfigVersion::query()->max('version_no') ?? 0) + 1;
$playVersion = PlayConfigVersion::query()->create([
'version_no' => $versionNo,
'status' => ConfigVersionStatus::Active->value,
'effective_at' => now(),
'updated_by' => null,
'reason' => 'seed:v1',
]);
foreach (PlayType::query()->orderBy('sort_order')->orderBy('play_code')->get() as $pt) {
PlayConfigItem::query()->create([
'version_id' => $playVersion->id,
'play_code' => $pt->play_code,
'is_enabled' => (bool) $pt->is_enabled,
'min_bet_amount' => 100,
'max_bet_amount' => 500_000_000,
'display_order' => (int) $pt->sort_order,
'rule_text_zh' => null,
'rule_text_en' => null,
'rule_text_ne' => null,
'extra_config_json' => null,
]);
}
}
private function seedActiveOddsVersion(): void
{
$versionNo = (int) (OddsVersion::query()->max('version_no') ?? 0) + 1;
$oddsVersion = OddsVersion::query()->create([
'version_no' => $versionNo,
'status' => ConfigVersionStatus::Active->value,
'effective_at' => now(),
'updated_by' => null,
'reason' => 'seed:v1',
]);
/** 对齐界面文档 §5.5:头/二/三/特别/安慰odds_value = 乘数×10000NPR 基准展示口径) */
foreach (PlayType::query()->orderBy('sort_order')->orderBy('play_code')->get() as $pt) {
foreach (OddsStandardScopes::PRESET_ODDS_BY_SCOPE as $scope => $oddsValue) {
OddsItem::query()->create([
'version_id' => $oddsVersion->id,
'play_code' => $pt->play_code,
'prize_scope' => $scope,
'odds_value' => $oddsValue,
'rebate_rate' => 0,
'commission_rate' => 0,
'currency_code' => 'NPR',
'extra_config_json' => null,
]);
}
}
}
private function seedActiveRiskCapVersion(): void
{
$versionNo = (int) (RiskCapVersion::query()->max('version_no') ?? 0) + 1;
$riskVersion = RiskCapVersion::query()->create([
'version_no' => $versionNo,
'status' => ConfigVersionStatus::Active->value,
'effective_at' => now(),
'updated_by' => null,
'reason' => 'seed:v1',
]);
foreach (['0000', '1234', '9999'] as $num) {
RiskCapItem::query()->create([
'version_id' => $riskVersion->id,
'draw_id' => null,
'normalized_number' => $num,
'cap_amount' => 50_000_000_000,
'cap_type' => 'per_number',
]);
}
}
}