feat: 更新玩法配置管理,简化字段并增强功能

- 将玩法相关的显示名称字段统一为 `display_name`,移除多语言字段。
- 在 `PlayTypePatchController` 中新增即时切换玩法开关的功能,并推送大厅更新。
- 优化多个控制器和服务中的权限检查与数据处理逻辑,提升代码可读性与维护性。
This commit is contained in:
2026-05-25 14:34:24 +08:00
parent 270d2e9af1
commit e27a00f260
74 changed files with 4469 additions and 280 deletions

View File

@@ -297,7 +297,6 @@ return new class extends Migration
$actionIds = DB::table('admin_action_catalog')->pluck('id', 'code');
$menuActions = [
['menu_code' => 'dashboard', 'action_code' => 'view', 'permission_code' => 'dashboard.view', 'name' => '仪表盘查看'],
['menu_code' => 'draw.results', 'action_code' => 'view', 'permission_code' => 'draw.results.view', 'name' => '开奖结果查看'],
['menu_code' => 'draw.review', 'action_code' => 'review', 'permission_code' => 'draw.review.review', 'name' => '开奖审核'],
['menu_code' => 'draw.review', 'action_code' => 'publish', 'permission_code' => 'draw.review.publish', 'name' => '开奖发布'],
@@ -340,7 +339,7 @@ return new class extends Migration
private function seedApiResources(Carbon $now): void
{
$resources = [
['code' => 'admin.dashboard', 'module_code' => 'dashboard', 'name' => '后台仪表盘', 'http_method' => 'GET', 'uri_pattern' => '/api/v1/admin/dashboard', 'route_name' => 'api.v1.admin.dashboard', 'auth_mode' => 'login_only', 'is_audit_required' => false, 'permission_codes' => ['dashboard.view']],
['code' => 'admin.dashboard', 'module_code' => 'dashboard', 'name' => '后台仪表盘', 'http_method' => 'GET', 'uri_pattern' => '/api/v1/admin/dashboard', 'route_name' => 'api.v1.admin.dashboard', 'auth_mode' => 'login_only', 'is_audit_required' => false, 'permission_codes' => []],
['code' => 'admin.draws.index', 'module_code' => 'draw', 'name' => '期开奖列表', 'http_method' => 'GET', 'uri_pattern' => '/api/v1/admin/draws', 'route_name' => 'api.v1.admin.draws.index', 'auth_mode' => 'permission_required', 'is_audit_required' => false, 'permission_codes' => ['draw.results.view']],
['code' => 'admin.draws.show', 'module_code' => 'draw', 'name' => '期开奖详情', 'http_method' => 'GET', 'uri_pattern' => '/api/v1/admin/draws/{draw}', 'route_name' => 'api.v1.admin.draws.show', 'auth_mode' => 'permission_required', 'is_audit_required' => false, 'permission_codes' => ['draw.results.view']],
['code' => 'admin.draws.publish', 'module_code' => 'draw', 'name' => '开奖发布', 'http_method' => 'POST', 'uri_pattern' => '/api/v1/admin/draws/{draw}/result-batches/{batch}/publish', 'route_name' => 'api.v1.admin.draws.result-batches.publish', 'auth_mode' => 'permission_required', 'is_audit_required' => true, 'permission_codes' => ['draw.review.publish']],
@@ -454,7 +453,7 @@ return new class extends Migration
foreach ($legacyRoles as $role) {
$roleId = (int) $role->id;
$grantedPermissions = ['dashboard.view' => true];
$grantedPermissions = [];
foreach ($legacyRolePermissions->get((int) $role->id, collect()) as $pivot) {
$permissionId = (int) $pivot->permission_id;
$legacySlug = $legacyPermissionById[$permissionId] ?? null;

View File

@@ -0,0 +1,54 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
foreach (['play_types', 'play_config_items'] as $table) {
Schema::table($table, function (Blueprint $blueprint): void {
$blueprint->string('display_name', 64)->nullable()->after('bet_mode');
});
DB::table($table)->update([
'display_name' => DB::raw(
"COALESCE(
NULLIF(TRIM(display_name_zh), ''),
NULLIF(TRIM(display_name_en), ''),
NULLIF(TRIM(display_name_ne), ''),
play_code
)",
),
]);
Schema::table($table, function (Blueprint $blueprint): void {
$blueprint->dropColumn(['display_name_zh', 'display_name_en', 'display_name_ne']);
});
}
}
public function down(): void
{
foreach (['play_types', 'play_config_items'] as $table) {
Schema::table($table, function (Blueprint $blueprint): void {
$blueprint->string('display_name_zh', 64)->nullable()->after('bet_mode');
$blueprint->string('display_name_en', 64)->nullable()->after('display_name_zh');
$blueprint->string('display_name_ne', 64)->nullable()->after('display_name_en');
});
DB::table($table)->update([
'display_name_zh' => DB::raw('display_name'),
'display_name_en' => DB::raw('display_name'),
'display_name_ne' => DB::raw('display_name'),
]);
Schema::table($table, function (Blueprint $blueprint): void {
$blueprint->dropColumn('display_name');
});
}
}
};

View File

@@ -0,0 +1,62 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
public function up(): void
{
$now = Carbon::now();
$actionIds = DB::table('admin_action_catalog')->pluck('id', 'code');
$menuIds = DB::table('admin_menus')->pluck('id', 'code');
$walletMenuId = $menuIds['service.wallet'] ?? null;
$updateActionId = $actionIds['update'] ?? null;
if ($walletMenuId !== null && $updateActionId !== null) {
$exists = DB::table('admin_menu_actions')
->where('permission_code', 'service.wallet.adjust')
->exists();
if (! $exists) {
DB::table('admin_menu_actions')->insert([
'menu_id' => $walletMenuId,
'action_id' => $updateActionId,
'permission_code' => 'service.wallet.adjust',
'name' => '钱包补单/冲正',
'status' => 1,
'created_at' => $now,
'updated_at' => $now,
]);
}
}
$oddsMenuId = $menuIds['config.odds'] ?? null;
$viewActionId = $actionIds['view'] ?? null;
if ($oddsMenuId !== null && $viewActionId !== null) {
$exists = DB::table('admin_menu_actions')
->where('permission_code', 'config.odds.view')
->exists();
if (! $exists) {
DB::table('admin_menu_actions')->insert([
'menu_id' => $oddsMenuId,
'action_id' => $viewActionId,
'permission_code' => 'config.odds.view',
'name' => '赔率配置查看',
'status' => 1,
'created_at' => $now,
'updated_at' => $now,
]);
}
}
}
public function down(): void
{
DB::table('admin_menu_actions')
->whereIn('permission_code', ['service.wallet.adjust', 'config.odds.view'])
->delete();
}
};

View File

@@ -0,0 +1,48 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
/** @var list<string> */
private const STALE_PERMISSION_CODES = [
'dashboard.view',
'service.reports.view',
'service.reports.export',
];
public function up(): void
{
$menuActionIds = DB::table('admin_menu_actions')
->whereIn('permission_code', self::STALE_PERMISSION_CODES)
->pluck('id');
if ($menuActionIds->isNotEmpty()) {
DB::table('admin_menu_actions')
->whereIn('id', $menuActionIds->all())
->delete();
}
$staleReportMenuId = DB::table('admin_menus')
->where('code', 'service.reports')
->value('id');
if ($staleReportMenuId !== null) {
$hasActions = DB::table('admin_menu_actions')
->where('menu_id', (int) $staleReportMenuId)
->exists();
if (! $hasActions) {
DB::table('admin_menus')
->where('id', (int) $staleReportMenuId)
->delete();
}
}
}
public function down(): void
{
// 数据清理迁移,不回滚以免再现僵尸 permission_code。
}
};

View File

@@ -0,0 +1,94 @@
<?php
use App\Support\AdminAuthorizationRegistry;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
public function up(): void
{
$now = Carbon::now();
$menuActionId = DB::table('admin_menu_actions')
->where('permission_code', 'dashboard.view')
->value('id');
if ($menuActionId === null) {
return;
}
$resource = collect(AdminAuthorizationRegistry::resources())
->firstWhere('code', 'admin.dashboard.analytics');
if ($resource === null) {
return;
}
$resourceId = DB::table('admin_api_resources')
->where('code', 'admin.dashboard.analytics')
->value('id');
$payload = [
'module_code' => $resource['module_code'],
'name' => $resource['name'],
'http_method' => $resource['http_method'],
'uri_pattern' => $resource['uri_pattern'],
'route_name' => $resource['route_name'],
'auth_mode' => $resource['auth_mode'],
'is_audit_required' => $resource['is_audit_required'],
'status' => 1,
'meta_json' => null,
'updated_at' => $now,
];
if ($resourceId === null) {
$resourceId = DB::table('admin_api_resources')->insertGetId($payload + [
'code' => 'admin.dashboard.analytics',
'created_at' => $now,
]);
} else {
DB::table('admin_api_resources')
->where('id', (int) $resourceId)
->update($payload);
}
DB::table('admin_api_resource_bindings')
->where('api_resource_id', (int) $resourceId)
->delete();
foreach ($resource['permission_codes'] as $permissionCode) {
$actionId = DB::table('admin_menu_actions')
->where('permission_code', $permissionCode)
->value('id');
if ($actionId === null) {
continue;
}
DB::table('admin_api_resource_bindings')->insert([
'api_resource_id' => (int) $resourceId,
'menu_action_id' => (int) $actionId,
'created_at' => $now,
'updated_at' => $now,
]);
}
}
public function down(): void
{
$resourceId = DB::table('admin_api_resources')
->where('code', 'admin.dashboard.analytics')
->value('id');
if ($resourceId === null) {
return;
}
DB::table('admin_api_resource_bindings')
->where('api_resource_id', (int) $resourceId)
->delete();
DB::table('admin_api_resources')
->where('id', (int) $resourceId)
->delete();
}
};

View File

@@ -0,0 +1,51 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
return new class extends Migration
{
public function up(): void
{
Schema::table('settlement_batches', function (Blueprint $table): void {
if (! Schema::hasColumn('settlement_batches', 'review_status')) {
$table->string('review_status', 32)->default('pending')->after('total_jackpot_payout_amount');
}
if (! Schema::hasColumn('settlement_batches', 'reviewed_by')) {
$table->foreignId('reviewed_by')->nullable()->after('review_status')->constrained('admin_users')->nullOnDelete();
}
if (! Schema::hasColumn('settlement_batches', 'reviewed_at')) {
$table->timestamp('reviewed_at')->nullable()->after('reviewed_by');
}
if (! Schema::hasColumn('settlement_batches', 'review_remark')) {
$table->string('review_remark', 255)->nullable()->after('reviewed_at');
}
if (! Schema::hasColumn('settlement_batches', 'paid_at')) {
$table->timestamp('paid_at')->nullable()->after('review_remark');
}
});
}
public function down(): void
{
Schema::table('settlement_batches', function (Blueprint $table): void {
if (Schema::hasColumn('settlement_batches', 'paid_at')) {
$table->dropColumn('paid_at');
}
if (Schema::hasColumn('settlement_batches', 'review_remark')) {
$table->dropColumn('review_remark');
}
if (Schema::hasColumn('settlement_batches', 'reviewed_at')) {
$table->dropColumn('reviewed_at');
}
if (Schema::hasColumn('settlement_batches', 'reviewed_by')) {
$table->dropForeign(['reviewed_by']);
$table->dropColumn('reviewed_by');
}
if (Schema::hasColumn('settlement_batches', 'review_status')) {
$table->dropColumn('review_status');
}
});
}
};

View File

@@ -0,0 +1,216 @@
<?php
use App\Support\AdminPermissionBridge;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
/** @var list<array{menu_code: string, action_code: string, permission_code: string, name: string}> */
private const NEW_MENU_ACTIONS = [
['menu_code' => 'dashboard', 'action_code' => 'view', 'permission_code' => 'dashboard.view', 'name' => '仪表盘查看'],
['menu_code' => 'service.report', 'action_code' => 'export', 'permission_code' => 'service.report.export', 'name' => '报表导出'],
['menu_code' => 'risk.monitor', 'action_code' => 'manage', 'permission_code' => 'risk.monitor.manage', 'name' => '风控监控管理'],
];
public function up(): void
{
$now = Carbon::now();
$menuIds = DB::table('admin_menus')->pluck('id', 'code');
$actionIds = DB::table('admin_action_catalog')->pluck('id', 'code');
$menuActionIds = [];
foreach (self::NEW_MENU_ACTIONS as $row) {
$menuId = $menuIds[$row['menu_code']] ?? null;
$actionId = $actionIds[$row['action_code']] ?? null;
if ($menuId === null || $actionId === null) {
continue;
}
$exists = DB::table('admin_menu_actions')
->where('permission_code', $row['permission_code'])
->exists();
if ($exists) {
$menuActionIds[$row['permission_code']] = (int) DB::table('admin_menu_actions')
->where('permission_code', $row['permission_code'])
->value('id');
continue;
}
$menuActionIds[$row['permission_code']] = (int) DB::table('admin_menu_actions')->insertGetId([
'menu_id' => (int) $menuId,
'action_id' => (int) $actionId,
'permission_code' => $row['permission_code'],
'name' => $row['name'],
'status' => 1,
'created_at' => $now,
'updated_at' => $now,
]);
}
$this->grantMenuActionsToAllRoles($menuActionIds, $now);
$this->grantReportExportToReportViewRoles($menuActionIds['service.report.export'] ?? null, $now);
$this->grantTicketsViewToLegacyRoles($menuActionIds, $now);
}
public function down(): void
{
$codes = array_column(self::NEW_MENU_ACTIONS, 'permission_code');
$ids = DB::table('admin_menu_actions')->whereIn('permission_code', $codes)->pluck('id');
foreach ($ids as $id) {
DB::table('admin_role_menu_actions')->where('menu_action_id', (int) $id)->delete();
DB::table('admin_user_menu_actions')->where('menu_action_id', (int) $id)->delete();
DB::table('admin_api_resource_bindings')->where('menu_action_id', (int) $id)->delete();
DB::table('admin_menu_actions')->where('id', (int) $id)->delete();
}
}
/**
* @param array<string, int> $menuActionIds
*/
private function grantMenuActionsToAllRoles(array $menuActionIds, Carbon $now): void
{
$dashboardId = $menuActionIds['dashboard.view'] ?? null;
if ($dashboardId === null) {
return;
}
$roleIds = DB::table('admin_roles')->pluck('id');
foreach ($roleIds as $roleId) {
DB::table('admin_role_menu_actions')->updateOrInsert([
'role_id' => (int) $roleId,
'menu_action_id' => $dashboardId,
]);
}
}
private function grantReportExportToReportViewRoles(?int $exportMenuActionId, Carbon $now): void
{
if ($exportMenuActionId === null) {
return;
}
$viewMenuActionId = DB::table('admin_menu_actions')
->where('permission_code', 'service.report.view')
->value('id');
if ($viewMenuActionId === null) {
return;
}
$roleIds = DB::table('admin_role_menu_actions')
->where('menu_action_id', (int) $viewMenuActionId)
->distinct()
->pluck('role_id');
foreach ($roleIds as $roleId) {
DB::table('admin_role_menu_actions')->updateOrInsert([
'role_id' => (int) $roleId,
'menu_action_id' => $exportMenuActionId,
]);
}
}
/**
* 原注单入口依赖多种 prd.*;迁移为独立的 prd.tickets.view。
*
* @param array<string, int> $menuActionIds
*/
private function grantTicketsViewToLegacyRoles(array $menuActionIds, Carbon $now): void
{
$ticketsViewId = DB::table('admin_menu_actions')
->where('permission_code', 'service.tickets.view')
->value('id');
if ($ticketsViewId === null) {
return;
}
$legacySlugs = [
'prd.users.view_cs',
'prd.users.manage',
'prd.users.view_finance',
'prd.draw_result.view',
'prd.draw_result.manage',
'prd.payout.view',
'prd.payout.review',
'prd.payout.manage',
];
$roleIds = $this->roleIdsWithAnyLegacySlug($legacySlugs);
foreach ($roleIds as $roleId) {
DB::table('admin_role_menu_actions')->updateOrInsert([
'role_id' => (int) $roleId,
'menu_action_id' => (int) $ticketsViewId,
]);
}
$riskViewId = DB::table('admin_menu_actions')
->where('permission_code', 'risk.monitor.view')
->value('id');
$riskManageId = $menuActionIds['risk.monitor.manage'] ?? null;
if ($riskManageId === null) {
return;
}
$riskRoleIds = $this->roleIdsWithAnyLegacySlug([
'prd.draw_result.manage',
'prd.draw_result.view',
'prd.risk.manage',
'prd.risk.view',
]);
foreach ($riskRoleIds as $roleId) {
if ($riskViewId !== null) {
DB::table('admin_role_menu_actions')->updateOrInsert([
'role_id' => (int) $roleId,
'menu_action_id' => (int) $riskViewId,
]);
}
DB::table('admin_role_menu_actions')->updateOrInsert([
'role_id' => (int) $roleId,
'menu_action_id' => (int) $riskManageId,
]);
}
}
/**
* 通过角色已授权的 menu_action 反推曾拥有指定 prd.* 的角色legacy 表已废弃)。
*
* @param list<string> $legacySlugs
* @return list<int>
*/
private function roleIdsWithAnyLegacySlug(array $legacySlugs): array
{
$codes = [];
foreach ($legacySlugs as $slug) {
$codes = array_merge($codes, AdminPermissionBridge::menuActionCodesForLegacy($slug));
}
$codes = array_values(array_unique($codes));
if ($codes === []) {
return [];
}
$menuActionIds = DB::table('admin_menu_actions')
->whereIn('permission_code', $codes)
->where('status', 1)
->pluck('id');
if ($menuActionIds->isEmpty()) {
return [];
}
return DB::table('admin_role_menu_actions')
->whereIn('menu_action_id', $menuActionIds->map(fn ($id) => (int) $id)->all())
->distinct()
->pluck('role_id')
->map(fn ($id) => (int) $id)
->all();
}
};

View File

@@ -0,0 +1,112 @@
<?php
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Migrations\Migration;
return new class extends Migration
{
public function up(): void
{
$now = Carbon::now();
if (! DB::table('admin_action_catalog')->where('code', 'manual_burst')->exists()) {
DB::table('admin_action_catalog')->insert([
'code' => 'manual_burst',
'name' => '手动爆池',
'sort_order' => 85,
'status' => 1,
'created_at' => $now,
'updated_at' => $now,
]);
}
$jackpotMenuId = (int) DB::table('admin_menus')->where('code', 'config.jackpot')->value('id');
$manualBurstActionId = (int) DB::table('admin_action_catalog')->where('code', 'manual_burst')->value('id');
if ($jackpotMenuId <= 0 || $manualBurstActionId <= 0) {
return;
}
DB::table('admin_menu_actions')->updateOrInsert(
['permission_code' => 'jackpot.pool.manual_burst'],
[
'menu_id' => $jackpotMenuId,
'action_id' => $manualBurstActionId,
'name' => 'Jackpot 手动爆池',
'status' => 1,
'created_at' => $now,
'updated_at' => $now,
],
);
if (Schema::hasTable('admin_permissions')) {
DB::table('admin_permissions')->updateOrInsert(
['slug' => 'prd.jackpot.manual_burst'],
[
'name' => 'Jackpot 手动爆池·仅超管',
'created_at' => $now,
'updated_at' => $now,
],
);
}
$menuActionId = (int) DB::table('admin_menu_actions')
->where('permission_code', 'jackpot.pool.manual_burst')
->value('id');
$superRoleId = (int) DB::table('admin_roles')->where('slug', 'super_admin')->value('id');
if ($superRoleId > 0 && $menuActionId > 0) {
if (Schema::hasTable('admin_role_legacy_permissions')) {
DB::table('admin_role_legacy_permissions')->updateOrInsert(
[
'role_id' => $superRoleId,
'permission_slug' => 'prd.jackpot.manual_burst',
],
[
'created_at' => $now,
'updated_at' => $now,
],
);
}
DB::table('admin_role_menu_actions')->updateOrInsert(
[
'role_id' => $superRoleId,
'menu_action_id' => $menuActionId,
],
[],
);
}
$resourceId = DB::table('admin_api_resources')
->where('code', 'admin.jackpot.pools.manual-burst')
->value('id');
if ($resourceId !== null && $menuActionId > 0) {
DB::table('admin_api_resource_bindings')
->where('api_resource_id', (int) $resourceId)
->delete();
DB::table('admin_api_resource_bindings')->insert([
'api_resource_id' => (int) $resourceId,
'menu_action_id' => $menuActionId,
'created_at' => $now,
'updated_at' => $now,
]);
if ($superRoleId > 0 && Schema::hasTable('admin_role_api_resources')) {
DB::table('admin_role_api_resources')->updateOrInsert([
'role_id' => $superRoleId,
'api_resource_id' => (int) $resourceId,
], []);
}
}
}
public function down(): void
{
// 避免误删线上已调整的授权绑定。
}
};

View File

@@ -39,17 +39,22 @@ final class AdminRbacAndUserSeeder extends Seeder
['name' => '风控运营员'],
);
$this->syncRolePermissions($risk, [
'prd.dashboard.view',
'prd.play_switch.manage',
'prd.odds.manage',
'prd.risk_cap.manage',
'prd.rebate.manage',
'prd.jackpot.manage',
'prd.draw_result.manage',
'prd.risk.view',
'prd.risk.manage',
'prd.payout.review',
'prd.tickets.view',
'prd.wallet_reconcile.view',
'prd.audit.view',
'prd.player_freeze.manage',
'prd.report.view',
'prd.report.export',
]);
$finance = AdminRole::query()->updateOrCreate(
@@ -57,16 +62,19 @@ final class AdminRbacAndUserSeeder extends Seeder
['name' => '财务/对账员'],
);
$this->syncRolePermissions($finance, [
'prd.dashboard.view',
'prd.users.view_finance',
'prd.risk_cap.view',
'prd.rebate.view',
'prd.jackpot.view',
'prd.draw_result.view',
'prd.payout.view',
'prd.tickets.view',
'prd.wallet_reconcile.manage',
'prd.wallet_adjust.manage',
'prd.audit.view',
'prd.report.view',
'prd.report.export',
]);
$cs = AdminRole::query()->updateOrCreate(
@@ -74,7 +82,9 @@ final class AdminRbacAndUserSeeder extends Seeder
['name' => '客服人员'],
);
$this->syncRolePermissions($cs, [
'prd.dashboard.view',
'prd.users.view_cs',
'prd.tickets.view',
'prd.draw_result.view',
'prd.wallet_reconcile.view_cs',
'prd.report.view',

View File

@@ -11,6 +11,8 @@ use App\Lottery\DrawStatus;
use App\Models\TicketOrder;
use App\Models\TransferOrder;
use App\Models\DrawResultBatch;
use App\Models\SettlementBatch;
use App\Lottery\SettlementBatchStatus;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use App\Lottery\DrawResultBatchStatus;
@@ -54,7 +56,8 @@ final class DashboardHallFixtureSeeder extends Seeder
DB::transaction(function () use ($draw, $player): void {
$this->seedRiskPools($draw);
$this->seedTicketOrders($draw, $player);
$this->seedPendingReviewBatch($draw);
$resultBatch = $this->seedPendingReviewBatch($draw);
$this->seedSettlementBatches($draw, $resultBatch);
$this->seedAbnormalTransfers($player);
});
@@ -269,12 +272,12 @@ final class DashboardHallFixtureSeeder extends Seeder
);
}
private function seedPendingReviewBatch(Draw $draw): void
private function seedPendingReviewBatch(Draw $draw): DrawResultBatch
{
$max = (int) DrawResultBatch::query()->where('draw_id', $draw->id)->max('result_version');
$next = max(1, $max + 1);
DrawResultBatch::query()->firstOrCreate(
return DrawResultBatch::query()->firstOrCreate(
[
'draw_id' => $draw->id,
'result_version' => $next,
@@ -291,6 +294,35 @@ final class DashboardHallFixtureSeeder extends Seeder
);
}
private function seedSettlementBatches(Draw $draw, DrawResultBatch $resultBatch): void
{
$now = Carbon::now()->utc();
$rows = [
[1, SettlementBatchStatus::PendingReview, 3, 1, 15_000, 5_000, $now->copy()->subHours(2), null],
[2, SettlementBatchStatus::Approved, 3, 2, 20_000, 5_000, $now->copy()->subHour(), $now->copy()->subMinutes(30)],
[3, SettlementBatchStatus::Completed, 3, 2, 20_000, 5_000, $now->copy()->subMinutes(45), $now->copy()->subMinutes(10)],
];
foreach ($rows as [$version, $status, $tickets, $wins, $payout, $jackpot, $started, $finished]) {
SettlementBatch::query()->firstOrCreate(
[
'draw_id' => $draw->id,
'settle_version' => $version,
],
[
'result_batch_id' => (int) $resultBatch->id,
'status' => $status->value,
'total_ticket_count' => $tickets,
'total_win_count' => $wins,
'total_payout_amount' => $payout,
'total_jackpot_payout_amount' => $jackpot,
'started_at' => $started,
'finished_at' => $finished,
],
);
}
}
private function seedAbnormalTransfers(Player $player): void
{
$rows = [

View File

@@ -82,6 +82,20 @@ final class LotterySettingsSeeder extends Seeder
'是否在 draw tick 中自动对 `settling` 期号跑结算false 时仅能通过后台 POST settlement/run 触发',
);
LotterySettings::put(
'settlement.auto_approve_on_tick',
true,
'settlement',
'冷静期结束后自动结算批次是否由 tick 自动审核通过false 时需人工审核',
);
LotterySettings::put(
'settlement.auto_payout_on_tick',
true,
'settlement',
'结算批次审核通过后是否由 tick 自动派彩入账false 时需人工执行 payout',
);
LotterySettings::put(
'settlement.apply_rebate_to_payout',
false,

View File

@@ -69,9 +69,7 @@ final class OperationalConfigV1Seeder extends Seeder
'category' => $pt->category,
'dimension' => $pt->dimension,
'bet_mode' => $pt->bet_mode,
'display_name_zh' => $pt->display_name_zh,
'display_name_en' => $pt->display_name_en,
'display_name_ne' => $pt->display_name_ne,
'display_name' => $pt->display_name,
'is_enabled' => (bool) $pt->is_enabled,
'min_bet_amount' => 100,
'max_bet_amount' => 500_000_000,

View File

@@ -64,9 +64,7 @@ final class PlayOperationalAlignmentSeeder extends Seeder
'category' => $pt->category,
'dimension' => $pt->dimension,
'bet_mode' => $pt->bet_mode,
'display_name_zh' => $pt->display_name_zh,
'display_name_en' => $pt->display_name_en,
'display_name_ne' => $pt->display_name_ne,
'display_name' => $pt->display_name,
'is_enabled' => (bool) $pt->is_enabled,
'min_bet_amount' => self::MIN_BET,
'max_bet_amount' => self::MAX_BET,

View File

@@ -79,9 +79,7 @@ final class PlayTypeSeeder extends Seeder
'category' => $category,
'dimension' => $dimension,
'bet_mode' => $betMode,
'display_name_zh' => $name,
'display_name_en' => $name,
'display_name_ne' => $name,
'display_name' => $name,
'is_enabled' => $isEnabled,
'sort_order' => $sortOrder,
'supports_multi_number' => $supportsMultiNumber,