call(PlayTypeSeeder::class); DB::transaction(function (): void { $open = [ConfigVersionStatus::Active->value, ConfigVersionStatus::Draft->value]; foreach (PlayConfigVersion::query()->whereIn('status', $open)->orderBy('id')->cursor() as $version) { $this->syncPlayConfigItems($version); } foreach (OddsVersion::query()->whereIn('status', $open)->orderBy('id')->cursor() as $version) { $this->syncOddsItemsForAllPlayTypes($version); } }); } private function syncPlayConfigItems(PlayConfigVersion $version): void { $vid = (int) $version->id; $existing = PlayConfigItem::query() ->where('version_id', $vid) ->pluck('play_code') ->all(); $have = array_fill_keys($existing, true); foreach (PlayType::query()->orderBy('sort_order')->orderBy('play_code')->cursor() as $pt) { if (isset($have[$pt->play_code])) { continue; } PlayConfigItem::query()->create([ 'version_id' => $vid, 'play_code' => $pt->play_code, 'category' => $pt->category, 'dimension' => $pt->dimension, 'bet_mode' => $pt->bet_mode, 'display_name' => $pt->display_name, 'is_enabled' => (bool) $pt->is_enabled, 'min_bet_amount' => self::MIN_BET, 'max_bet_amount' => self::MAX_BET, 'display_order' => (int) $pt->sort_order, 'supports_multi_number' => (bool) $pt->supports_multi_number, 'reserved_rule_json' => $pt->reserved_rule_json, 'rule_text_zh' => null, 'rule_text_en' => null, 'rule_text_ne' => null, 'extra_config_json' => null, ]); } } private function syncOddsItemsForAllPlayTypes(OddsVersion $version): void { $vid = (int) $version->id; $currencies = OddsItem::query() ->where('version_id', $vid) ->distinct() ->pluck('currency_code') ->filter(static fn ($c) => is_string($c) && $c !== '') ->values(); if ($currencies->isEmpty()) { $fallback = Currency::query() ->where('is_bettable', true) ->where('is_enabled', true) ->orderBy('code') ->value('code'); if ($fallback === null || $fallback === '') { return; } $currencies = collect([strtoupper((string) $fallback)]); } foreach ($currencies as $currencyCode) { $currencyCode = strtoupper((string) $currencyCode); foreach (PlayType::query()->orderBy('sort_order')->orderBy('play_code')->cursor() as $pt) { $playCode = $pt->play_code; $anchor = OddsItem::query() ->where('version_id', $vid) ->where('play_code', $playCode) ->where('currency_code', $currencyCode) ->orderByDesc('id') ->first(); $rebate = (float) ($anchor?->rebate_rate ?? 0); $commission = (float) ($anchor?->commission_rate ?? 0); foreach (OddsStandardScopes::PRESET_ODDS_BY_SCOPE as $scope => $oddsValue) { $exists = OddsItem::query() ->where('version_id', $vid) ->where('play_code', $playCode) ->where('currency_code', $currencyCode) ->where('prize_scope', $scope) ->exists(); if ($exists) { continue; } OddsItem::query()->create([ 'version_id' => $vid, 'play_code' => $playCode, 'prize_scope' => $scope, 'odds_value' => $oddsValue, 'rebate_rate' => $rebate, 'commission_rate' => $commission, 'currency_code' => $currencyCode, 'extra_config_json' => null, ]); } } } } }