feat: 添加新的错误码以支持配置版本管理,更新彩票配置以启用手动审核,增强 API 路由以支持玩法和赔率版本化管理
This commit is contained in:
151
app/Support/AdminConfigPresenter.php
Normal file
151
app/Support/AdminConfigPresenter.php
Normal file
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
namespace App\Support;
|
||||
|
||||
use App\Models\OddsItem;
|
||||
use App\Models\OddsVersion;
|
||||
use App\Models\PlayConfigItem;
|
||||
use App\Models\PlayConfigVersion;
|
||||
use App\Models\PlayType;
|
||||
use App\Models\RiskCapItem;
|
||||
use App\Models\RiskCapVersion;
|
||||
|
||||
/** 后台 API:阶段 4 运营配置序列化(与其它 Admin*Controller 手写数组风格一致)。 */
|
||||
final class AdminConfigPresenter
|
||||
{
|
||||
/** @return array<string, mixed> */
|
||||
public static function playType(PlayType $t): array
|
||||
{
|
||||
return [
|
||||
'id' => (int) $t->id,
|
||||
'play_code' => $t->play_code,
|
||||
'category' => $t->category,
|
||||
'dimension' => $t->dimension,
|
||||
'bet_mode' => $t->bet_mode,
|
||||
'display_name_zh' => $t->display_name_zh,
|
||||
'display_name_en' => $t->display_name_en,
|
||||
'display_name_ne' => $t->display_name_ne,
|
||||
'is_enabled' => (bool) $t->is_enabled,
|
||||
'sort_order' => (int) $t->sort_order,
|
||||
'supports_multi_number' => (bool) $t->supports_multi_number,
|
||||
'reserved_rule_json' => $t->reserved_rule_json,
|
||||
'updated_at' => $t->updated_at?->toIso8601String(),
|
||||
];
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
public static function playConfigVersionSummary(PlayConfigVersion $v): array
|
||||
{
|
||||
return [
|
||||
'id' => (int) $v->id,
|
||||
'version_no' => (int) $v->version_no,
|
||||
'status' => $v->status,
|
||||
'effective_at' => $v->effective_at?->toIso8601String(),
|
||||
'updated_by' => $v->updated_by,
|
||||
'reason' => $v->reason,
|
||||
'created_at' => $v->created_at?->toIso8601String(),
|
||||
'updated_at' => $v->updated_at?->toIso8601String(),
|
||||
];
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
public static function playConfigVersionDetail(PlayConfigVersion $v): array
|
||||
{
|
||||
$base = self::playConfigVersionSummary($v);
|
||||
$base['items'] = $v->items->map(fn (PlayConfigItem $r) => self::playConfigItem($r))->values()->all();
|
||||
|
||||
return $base;
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
public static function playConfigItem(PlayConfigItem $r): array
|
||||
{
|
||||
return [
|
||||
'id' => (int) $r->id,
|
||||
'play_code' => $r->play_code,
|
||||
'is_enabled' => (bool) $r->is_enabled,
|
||||
'min_bet_amount' => (int) $r->min_bet_amount,
|
||||
'max_bet_amount' => (int) $r->max_bet_amount,
|
||||
'display_order' => (int) $r->display_order,
|
||||
'rule_text_zh' => $r->rule_text_zh,
|
||||
'rule_text_en' => $r->rule_text_en,
|
||||
'rule_text_ne' => $r->rule_text_ne,
|
||||
'extra_config_json' => $r->extra_config_json,
|
||||
];
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
public static function oddsVersionSummary(OddsVersion $v): array
|
||||
{
|
||||
return [
|
||||
'id' => (int) $v->id,
|
||||
'version_no' => (int) $v->version_no,
|
||||
'status' => $v->status,
|
||||
'effective_at' => $v->effective_at?->toIso8601String(),
|
||||
'updated_by' => $v->updated_by,
|
||||
'reason' => $v->reason,
|
||||
'created_at' => $v->created_at?->toIso8601String(),
|
||||
'updated_at' => $v->updated_at?->toIso8601String(),
|
||||
];
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
public static function oddsVersionDetail(OddsVersion $v): array
|
||||
{
|
||||
$base = self::oddsVersionSummary($v);
|
||||
$base['items'] = $v->items->map(fn (OddsItem $r) => self::oddsItem($r))->values()->all();
|
||||
|
||||
return $base;
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
public static function oddsItem(OddsItem $r): array
|
||||
{
|
||||
return [
|
||||
'id' => (int) $r->id,
|
||||
'play_code' => $r->play_code,
|
||||
'prize_scope' => $r->prize_scope,
|
||||
'odds_value' => (int) $r->odds_value,
|
||||
'rebate_rate' => (string) $r->rebate_rate,
|
||||
'commission_rate' => (string) $r->commission_rate,
|
||||
'currency_code' => $r->currency_code,
|
||||
'extra_config_json' => $r->extra_config_json,
|
||||
];
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
public static function riskCapVersionSummary(RiskCapVersion $v): array
|
||||
{
|
||||
return [
|
||||
'id' => (int) $v->id,
|
||||
'version_no' => (int) $v->version_no,
|
||||
'status' => $v->status,
|
||||
'effective_at' => $v->effective_at?->toIso8601String(),
|
||||
'updated_by' => $v->updated_by,
|
||||
'reason' => $v->reason,
|
||||
'created_at' => $v->created_at?->toIso8601String(),
|
||||
'updated_at' => $v->updated_at?->toIso8601String(),
|
||||
];
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
public static function riskCapVersionDetail(RiskCapVersion $v): array
|
||||
{
|
||||
$base = self::riskCapVersionSummary($v);
|
||||
$base['items'] = $v->items->map(fn (RiskCapItem $r) => self::riskCapItem($r))->values()->all();
|
||||
|
||||
return $base;
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
public static function riskCapItem(RiskCapItem $r): array
|
||||
{
|
||||
return [
|
||||
'id' => (int) $r->id,
|
||||
'draw_id' => $r->draw_id,
|
||||
'normalized_number' => $r->normalized_number,
|
||||
'cap_amount' => (int) $r->cap_amount,
|
||||
'cap_type' => $r->cap_type,
|
||||
];
|
||||
}
|
||||
}
|
||||
103
app/Support/OddsStandardScopes.php
Normal file
103
app/Support/OddsStandardScopes.php
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace App\Support;
|
||||
|
||||
use App\Models\Currency;
|
||||
use App\Models\OddsItem;
|
||||
use App\Models\OddsVersion;
|
||||
use App\Models\PlayType;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
/**
|
||||
* 界面文档 §5.5:每个玩法需具备的五档 prize_scope;odds_value = 乘数×10000。
|
||||
*/
|
||||
final class OddsStandardScopes
|
||||
{
|
||||
/** @var array<string, int> */
|
||||
public const PRESET_ODDS_BY_SCOPE = [
|
||||
'first' => 250_000,
|
||||
'second' => 110_000,
|
||||
'third' => 55_000,
|
||||
'starter' => 22_000,
|
||||
'consolation' => 6_500,
|
||||
];
|
||||
|
||||
/** @var list<string> */
|
||||
public const SCOPE_KEYS = ['first', 'second', 'third', 'starter', 'consolation'];
|
||||
|
||||
/**
|
||||
* 为指定赔率版本补全缺失的标准五档行(幂等)。
|
||||
*
|
||||
* 仅对「该版本里已出现过的 (play_code, currency_code)」补全,避免给从未配置过的玩法凭空加行。
|
||||
* 若版本下无任何 odds_items,则用当前全部玩法 × 首个可下注币种补全。
|
||||
*/
|
||||
public static function syncMissingForVersion(OddsVersion $version): void
|
||||
{
|
||||
DB::transaction(function () use ($version): void {
|
||||
$vid = (int) $version->id;
|
||||
|
||||
$pairs = OddsItem::query()
|
||||
->where('version_id', $vid)
|
||||
->select(['play_code', 'currency_code'])
|
||||
->distinct()
|
||||
->get();
|
||||
|
||||
if ($pairs->isEmpty()) {
|
||||
$currencyCode = Currency::query()
|
||||
->where('is_bettable', true)
|
||||
->where('is_enabled', true)
|
||||
->orderBy('code')
|
||||
->value('code');
|
||||
if ($currencyCode === null || $currencyCode === '') {
|
||||
return;
|
||||
}
|
||||
$pairs = PlayType::query()
|
||||
->orderBy('sort_order')
|
||||
->orderBy('play_code')
|
||||
->get(['play_code'])
|
||||
->map(fn (PlayType $pt) => (object) [
|
||||
'play_code' => $pt->play_code,
|
||||
'currency_code' => $currencyCode,
|
||||
]);
|
||||
}
|
||||
|
||||
foreach ($pairs as $pair) {
|
||||
$playCode = (string) $pair->play_code;
|
||||
$currencyCode = strtoupper((string) $pair->currency_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 (self::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,
|
||||
]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user