where('is_default', true)->first(); $extra = json_decode((string) ($site->extra_json ?? '{}'), true); if (! is_array($extra)) { $extra = []; } $extra['credit_line_mode'] = true; DB::table('admin_sites')->where('id', $site->id)->update([ 'extra_json' => json_encode($extra), 'updated_at' => now(), ]); $siteCode = (string) $site->code; $player = Player::query()->create([ 'site_code' => $siteCode, 'agent_node_id' => (int) DB::table('agent_nodes')->where('depth', 0)->value('id'), 'site_player_id' => 'rev-p1', 'username' => 'rev1', 'nickname' => null, 'default_currency' => 'NPR', 'status' => 0, ]); $drawId = (int) \App\Models\Draw::query()->create([ 'draw_no' => 'REV-DRAW-1', 'business_date' => now()->toDateString(), 'sequence_no' => 1, 'status' => \App\Lottery\DrawStatus::Open->value, 'current_result_version' => 0, 'settle_version' => 0, 'is_reopened' => false, ])->id; $orderId = (int) DB::table('ticket_orders')->insertGetId([ 'order_no' => 'ORD-REV-1', 'player_id' => $player->id, 'draw_id' => $drawId, 'currency_code' => 'NPR', 'total_bet_amount' => 100, 'total_rebate_amount' => 0, 'total_actual_deduct' => 100, 'total_estimated_payout' => 0, 'status' => 'placed', 'created_at' => now(), 'updated_at' => now(), ]); $itemId = (int) DB::table('ticket_items')->insertGetId([ 'ticket_no' => 'T-REV-1', 'order_id' => $orderId, 'player_id' => $player->id, 'draw_id' => $drawId, 'original_number' => '1234', 'normalized_number' => '1234', 'play_code' => 'direct', 'dimension' => '4d', 'digit_slot' => null, 'bet_mode' => 'single', 'unit_bet_amount' => 100, 'total_bet_amount' => 100, 'rebate_rate_snapshot' => 0, 'commission_rate_snapshot' => 0, 'actual_deduct_amount' => 100, 'odds_snapshot_json' => '{}', 'rule_snapshot_json' => '{}', 'combination_count' => 1, 'estimated_max_payout' => 0, 'risk_locked_amount' => 0, 'status' => 'settled', 'win_amount' => 0, 'jackpot_win_amount' => 0, 'agent_node_id' => $player->agent_node_id, 'share_snapshot' => '{}', 'agent_settled_at' => now(), 'settled_at' => now(), 'created_at' => now(), 'updated_at' => now(), ]); $ledgerId = (int) DB::table('share_ledger')->insertGetId([ 'ticket_item_id' => $itemId, 'player_id' => $player->id, 'agent_node_id' => $player->agent_node_id, 'agent_path' => '[]', 'share_snapshot' => '{}', 'game_win_loss' => -1000, 'basic_rebate' => 50, 'shared_net_win_loss' => -950, 'allocations_json' => '[]', 'settled_at' => now(), 'created_at' => now(), 'updated_at' => now(), ]); $rebateId = (int) DB::table('rebate_records')->insertGetId([ 'player_id' => $player->id, 'ticket_item_id' => $itemId, 'game_type' => '*', 'valid_bet_amount' => 1000, 'rebate_rate' => 0.005, 'rebate_amount' => 50, 'rebate_type' => 'basic', 'owner_agent_id' => $player->agent_node_id, 'status' => 'accrued', 'created_at' => now(), 'updated_at' => now(), ]); $item = TicketItem::query()->findOrFail($itemId); app(GameSettlementReversalService::class)->reverseTicketItem($item); $sum = (int) DB::table('share_ledger')->where('ticket_item_id', $itemId)->sum('shared_net_win_loss'); expect($sum)->toBe(0); expect((string) DB::table('rebate_records')->where('id', $rebateId)->value('status'))->toBe('reversed'); expect(DB::table('share_ledger')->where('reversal_of_id', $ledgerId)->exists())->toBeTrue(); });