feat: 添加结算功能,更新 TicketItem 模型以支持最新结算详情,增强 DrawTickService 以自动处理结算,更新 TicketWalletService 以支持派彩入账,扩展 API 路由以管理结算批次和奖池

This commit is contained in:
2026-05-11 15:34:34 +08:00
parent 6a55fa9592
commit 19003f5041
50 changed files with 3604 additions and 3 deletions

View File

@@ -0,0 +1,50 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/** 单注对 Jackpot 的蓄水 {@see jackpot_contributions} */
class JackpotContribution extends Model
{
protected $fillable = [
'jackpot_pool_id',
'draw_id',
'player_id',
'ticket_item_id',
'contribution_amount',
'currency_code',
];
protected function casts(): array
{
return [
'jackpot_pool_id' => 'integer',
'draw_id' => 'integer',
'player_id' => 'integer',
'ticket_item_id' => 'integer',
'contribution_amount' => 'integer',
];
}
public function pool(): BelongsTo
{
return $this->belongsTo(JackpotPool::class, 'jackpot_pool_id');
}
public function draw(): BelongsTo
{
return $this->belongsTo(Draw::class);
}
public function player(): BelongsTo
{
return $this->belongsTo(Player::class);
}
public function ticketItem(): BelongsTo
{
return $this->belongsTo(TicketItem::class, 'ticket_item_id');
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/** Jackpot 爆池派发记录 {@see jackpot_payout_logs} */
class JackpotPayoutLog extends Model
{
public const UPDATED_AT = null;
protected $fillable = [
'draw_id',
'jackpot_pool_id',
'trigger_type',
'total_payout_amount',
'winner_count',
'trigger_snapshot_json',
];
protected function casts(): array
{
return [
'draw_id' => 'integer',
'jackpot_pool_id' => 'integer',
'total_payout_amount' => 'integer',
'winner_count' => 'integer',
'trigger_snapshot_json' => 'json',
];
}
public function draw(): BelongsTo
{
return $this->belongsTo(Draw::class);
}
public function pool(): BelongsTo
{
return $this->belongsTo(JackpotPool::class, 'jackpot_pool_id');
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
/** Jackpot 奖池配置与当前水位 {@see jackpot_pools} */
class JackpotPool extends Model
{
protected $fillable = [
'currency_code',
'current_amount',
'contribution_rate',
'trigger_threshold',
'payout_rate',
'force_trigger_draw_gap',
'min_bet_amount',
'status',
'last_trigger_draw_id',
];
protected function casts(): array
{
return [
'current_amount' => 'integer',
'contribution_rate' => 'decimal:4',
'trigger_threshold' => 'integer',
'payout_rate' => 'decimal:4',
'force_trigger_draw_gap' => 'integer',
'min_bet_amount' => 'integer',
'status' => 'integer',
'last_trigger_draw_id' => 'integer',
];
}
public function lastTriggerDraw(): BelongsTo
{
return $this->belongsTo(Draw::class, 'last_trigger_draw_id');
}
public function contributions(): HasMany
{
return $this->hasMany(JackpotContribution::class, 'jackpot_pool_id');
}
}

View File

@@ -0,0 +1,60 @@
<?php
namespace App\Models;
use App\Lottery\SettlementBatchStatus;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
/** 单期单次结算批次 {@see settlement_batches} */
class SettlementBatch extends Model
{
protected $fillable = [
'draw_id',
'result_batch_id',
'settle_version',
'status',
'total_ticket_count',
'total_win_count',
'total_payout_amount',
'total_jackpot_payout_amount',
'started_at',
'finished_at',
];
protected function casts(): array
{
return [
'draw_id' => 'integer',
'result_batch_id' => 'integer',
'settle_version' => 'integer',
'total_ticket_count' => 'integer',
'total_win_count' => 'integer',
'total_payout_amount' => 'integer',
'total_jackpot_payout_amount' => 'integer',
'started_at' => 'datetime',
'finished_at' => 'datetime',
];
}
public function draw(): BelongsTo
{
return $this->belongsTo(Draw::class);
}
public function resultBatch(): BelongsTo
{
return $this->belongsTo(DrawResultBatch::class, 'result_batch_id');
}
public function details(): HasMany
{
return $this->hasMany(TicketSettlementDetail::class, 'settlement_batch_id');
}
public function statusEnum(): ?SettlementBatchStatus
{
return SettlementBatchStatus::tryFrom((string) $this->status);
}
}

View File

@@ -5,6 +5,7 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
/** 注项明细 {@see ticket_items} */
class TicketItem extends Model
@@ -81,4 +82,9 @@ class TicketItem extends Model
{
return $this->hasMany(TicketCombination::class, 'ticket_item_id');
}
public function latestSettlementDetail(): HasOne
{
return $this->hasOne(TicketSettlementDetail::class, 'ticket_item_id')->latestOfMany('id');
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/** 注单项结算明细 {@see ticket_settlement_details} */
class TicketSettlementDetail extends Model
{
protected $fillable = [
'settlement_batch_id',
'ticket_item_id',
'matched_prize_tier',
'win_amount',
'jackpot_allocation_amount',
'match_detail_json',
];
protected function casts(): array
{
return [
'settlement_batch_id' => 'integer',
'ticket_item_id' => 'integer',
'win_amount' => 'integer',
'jackpot_allocation_amount' => 'integer',
'match_detail_json' => 'json',
];
}
public function batch(): BelongsTo
{
return $this->belongsTo(SettlementBatch::class, 'settlement_batch_id');
}
public function ticketItem(): BelongsTo
{
return $this->belongsTo(TicketItem::class, 'ticket_item_id');
}
}