feat: 添加新的错误码以支持配置版本管理,更新彩票配置以启用手动审核,增强 API 路由以支持玩法和赔率版本化管理

This commit is contained in:
2026-05-11 10:08:48 +08:00
parent aeaf124096
commit 067c2b39f5
41 changed files with 2578 additions and 1 deletions

42
app/Models/OddsItem.php Normal file
View File

@@ -0,0 +1,42 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* {@see odds_items}
*
* `odds_value`:整数,**赔率乘数 × 10000**(例如 19500 表示 1.9500 倍)。
*/
class OddsItem extends Model
{
protected $fillable = [
'version_id',
'play_code',
'prize_scope',
'odds_value',
'rebate_rate',
'commission_rate',
'currency_code',
'extra_config_json',
];
protected function casts(): array
{
return [
'version_id' => 'integer',
'odds_value' => 'integer',
'rebate_rate' => 'decimal:4',
'commission_rate' => 'decimal:4',
'extra_config_json' => 'json',
];
}
/** @return BelongsTo<OddsVersion, OddsItem> */
public function version(): BelongsTo
{
return $this->belongsTo(OddsVersion::class, 'version_id');
}
}

View File

@@ -0,0 +1,55 @@
<?php
namespace App\Models;
use App\Lottery\ConfigVersionStatus;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
/** {@see odds_versions} */
class OddsVersion extends Model
{
protected $fillable = [
'version_no',
'status',
'effective_at',
'updated_by',
'reason',
];
protected function casts(): array
{
return [
'version_no' => 'integer',
'effective_at' => 'datetime',
'updated_by' => 'integer',
];
}
protected static function booted(): void
{
static::saving(function (OddsVersion $m): void {
if ($m->status === null || $m->status === '') {
$m->status = ConfigVersionStatus::Draft->value;
}
});
}
/** @return BelongsTo<AdminUser, OddsVersion> */
public function updatedByAdmin(): BelongsTo
{
return $this->belongsTo(AdminUser::class, 'updated_by');
}
/** @return HasMany<OddsItem, OddsVersion> */
public function items(): HasMany
{
return $this->hasMany(OddsItem::class, 'version_id');
}
public function isDraft(): bool
{
return $this->status === ConfigVersionStatus::Draft->value;
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/** {@see play_config_items} — 与 {@see PlayType::play_code} 对齐。 */
class PlayConfigItem extends Model
{
protected $fillable = [
'version_id',
'play_code',
'is_enabled',
'min_bet_amount',
'max_bet_amount',
'display_order',
'rule_text_zh',
'rule_text_en',
'rule_text_ne',
'extra_config_json',
];
protected function casts(): array
{
return [
'version_id' => 'integer',
'is_enabled' => 'boolean',
'min_bet_amount' => 'integer',
'max_bet_amount' => 'integer',
'display_order' => 'integer',
'extra_config_json' => 'json',
];
}
/** @return BelongsTo<PlayConfigVersion, PlayConfigItem> */
public function version(): BelongsTo
{
return $this->belongsTo(PlayConfigVersion::class, 'version_id');
}
/** @return BelongsTo<PlayType, PlayConfigItem> */
public function playType(): BelongsTo
{
return $this->belongsTo(PlayType::class, 'play_code', 'play_code');
}
}

View File

@@ -0,0 +1,55 @@
<?php
namespace App\Models;
use App\Lottery\ConfigVersionStatus;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
/** {@see play_config_versions} */
class PlayConfigVersion extends Model
{
protected $fillable = [
'version_no',
'status',
'effective_at',
'updated_by',
'reason',
];
protected function casts(): array
{
return [
'version_no' => 'integer',
'effective_at' => 'datetime',
'updated_by' => 'integer',
];
}
protected static function booted(): void
{
static::saving(function (PlayConfigVersion $m): void {
if ($m->status === null || $m->status === '') {
$m->status = ConfigVersionStatus::Draft->value;
}
});
}
/** @return BelongsTo<AdminUser, PlayConfigVersion> */
public function updatedByAdmin(): BelongsTo
{
return $this->belongsTo(AdminUser::class, 'updated_by');
}
/** @return HasMany<PlayConfigItem, PlayConfigVersion> */
public function items(): HasMany
{
return $this->hasMany(PlayConfigItem::class, 'version_id');
}
public function isDraft(): bool
{
return $this->status === ConfigVersionStatus::Draft->value;
}
}

34
app/Models/PlayType.php Normal file
View File

@@ -0,0 +1,34 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
/** 玩法主数据目录 {@see play_types}(与版本化配置 items 通过 play_code 关联)。 */
class PlayType extends Model
{
protected $fillable = [
'play_code',
'category',
'dimension',
'bet_mode',
'display_name_zh',
'display_name_en',
'display_name_ne',
'is_enabled',
'sort_order',
'supports_multi_number',
'reserved_rule_json',
];
protected function casts(): array
{
return [
'dimension' => 'integer',
'is_enabled' => 'boolean',
'sort_order' => 'integer',
'supports_multi_number' => 'boolean',
'reserved_rule_json' => 'json',
];
}
}

View File

@@ -0,0 +1,43 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* {@see risk_cap_items}
*
* `cap_amount`:与钱包一致的最小货币单位(整数)。
*/
class RiskCapItem extends Model
{
protected $fillable = [
'version_id',
'draw_id',
'normalized_number',
'cap_amount',
'cap_type',
];
protected function casts(): array
{
return [
'version_id' => 'integer',
'draw_id' => 'integer',
'cap_amount' => 'integer',
];
}
/** @return BelongsTo<RiskCapVersion, RiskCapItem> */
public function version(): BelongsTo
{
return $this->belongsTo(RiskCapVersion::class, 'version_id');
}
/** @return BelongsTo<Draw, RiskCapItem> */
public function draw(): BelongsTo
{
return $this->belongsTo(Draw::class, 'draw_id');
}
}

View File

@@ -0,0 +1,55 @@
<?php
namespace App\Models;
use App\Lottery\ConfigVersionStatus;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
/** {@see risk_cap_versions} */
class RiskCapVersion extends Model
{
protected $fillable = [
'version_no',
'status',
'effective_at',
'updated_by',
'reason',
];
protected function casts(): array
{
return [
'version_no' => 'integer',
'effective_at' => 'datetime',
'updated_by' => 'integer',
];
}
protected static function booted(): void
{
static::saving(function (RiskCapVersion $m): void {
if ($m->status === null || $m->status === '') {
$m->status = ConfigVersionStatus::Draft->value;
}
});
}
/** @return BelongsTo<AdminUser, RiskCapVersion> */
public function updatedByAdmin(): BelongsTo
{
return $this->belongsTo(AdminUser::class, 'updated_by');
}
/** @return HasMany<RiskCapItem, RiskCapVersion> */
public function items(): HasMany
{
return $this->hasMany(RiskCapItem::class, 'version_id');
}
public function isDraft(): bool
{
return $this->status === ConfigVersionStatus::Draft->value;
}
}