create([ 'username' => 'wallet_admin', 'name' => 'Wallet', 'email' => null, 'password' => Hash::make('secret-strong'), 'status' => 0, ]); return $admin->createToken('test', ['*'], now()->addDay())->plainTextToken; } test('admin wallet transfer orders list requires authentication', function (): void { $this->getJson('/api/v1/admin/wallet/transfer-orders') ->assertUnauthorized() ->assertJsonPath('code', ErrorCode::AdminUnauthenticated->value); }); test('admin lists transfer orders with player info', function (): void { $token = makeAdminToken(); $player = Player::query()->create([ 'site_code' => 'main', 'site_player_id' => 'p99', 'username' => 'u99', 'nickname' => null, 'default_currency' => 'NPR', 'status' => 0, ]); TransferOrder::query()->create([ 'transfer_no' => 'TI_test_order_1', 'player_id' => $player->id, 'direction' => 'in', 'currency_code' => 'NPR', 'amount' => 1000, 'idempotent_key' => 'adm-test-1', 'status' => 'success', 'external_request_payload' => null, 'external_response_payload' => null, 'external_ref_no' => 'ref1', 'fail_reason' => null, 'finished_at' => now(), ]); $this->withHeader('Authorization', 'Bearer '.$token) ->getJson('/api/v1/admin/wallet/transfer-orders?per_page=10') ->assertOk() ->assertJsonPath('code', ErrorCode::Success->value) ->assertJsonPath('data.total', 1) ->assertJsonPath('data.items.0.transfer_no', 'TI_test_order_1') ->assertJsonPath('data.items.0.site_player_id', 'p99') ->assertJsonPath('data.items.0.status', 'success'); }); test('admin filters abnormal transfer orders', function (): void { $token = makeAdminToken(); $player = Player::query()->create([ 'site_code' => 'main', 'site_player_id' => 'pa', 'username' => null, 'nickname' => null, 'default_currency' => 'NPR', 'status' => 0, ]); foreach ( [ ['TI_ok', 'success'], ['TI_bad', 'failed'], ['TI_wait', 'pending_reconcile'], ] as [$no, $st] ) { TransferOrder::query()->create([ 'transfer_no' => $no, 'player_id' => $player->id, 'direction' => 'in', 'currency_code' => 'NPR', 'amount' => 100, 'idempotent_key' => 'k-'.$no, 'status' => $st, 'external_request_payload' => null, 'external_response_payload' => null, 'external_ref_no' => null, 'fail_reason' => null, 'finished_at' => $st === 'success' ? now() : null, ]); } $resp = $this->withHeader('Authorization', 'Bearer '.$token) ->getJson('/api/v1/admin/wallet/transfer-orders?abnormal=1'); $resp->assertOk()->assertJsonPath('data.total', 2); }); test('admin lists wallet transactions and filters abnormal', function (): void { $token = makeAdminToken(); $player = Player::query()->create([ 'site_code' => 'main', 'site_player_id' => 'pb', 'username' => null, 'nickname' => null, 'default_currency' => 'NPR', 'status' => 0, ]); $wallet = PlayerWallet::query()->create([ 'player_id' => $player->id, 'wallet_type' => 'lottery', 'currency_code' => 'NPR', 'balance' => 5000, 'frozen_balance' => 0, 'status' => 0, 'version' => 1, ]); WalletTxn::query()->create([ 'txn_no' => 'WX_posted_1', 'player_id' => $player->id, 'wallet_id' => $wallet->id, 'biz_type' => 'transfer_in', 'biz_no' => 'TI_x', 'direction' => 1, 'amount' => 100, 'balance_before' => 0, 'balance_after' => 100, 'status' => 'posted', 'external_ref_no' => null, 'idempotent_key' => 'ik1', 'remark' => null, ]); WalletTxn::query()->create([ 'txn_no' => 'WX_pending_1', 'player_id' => $player->id, 'wallet_id' => $wallet->id, 'biz_type' => 'transfer_out', 'biz_no' => 'TO_x', 'direction' => 2, 'amount' => 50, 'balance_before' => 100, 'balance_after' => 50, 'status' => 'pending_reconcile', 'external_ref_no' => null, 'idempotent_key' => 'ik2', 'remark' => null, ]); $this->withHeader('Authorization', 'Bearer '.$token) ->getJson('/api/v1/admin/wallet/transactions') ->assertOk() ->assertJsonPath('data.total', 2); $this->withHeader('Authorization', 'Bearer '.$token) ->getJson('/api/v1/admin/wallet/transactions?abnormal=1') ->assertOk() ->assertJsonPath('data.total', 1) ->assertJsonPath('data.items.0.status', 'pending_reconcile'); }); test('admin shows player wallets', function (): void { $token = makeAdminToken(); $player = Player::query()->create([ 'site_code' => 'main', 'site_player_id' => 'pc', 'username' => null, 'nickname' => null, 'default_currency' => 'NPR', 'status' => 0, ]); PlayerWallet::query()->create([ 'player_id' => $player->id, 'wallet_type' => 'lottery', 'currency_code' => 'NPR', 'balance' => 77700, 'frozen_balance' => 0, 'status' => 0, 'version' => 0, ]); $this->withHeader('Authorization', 'Bearer '.$token) ->getJson('/api/v1/admin/players/'.$player->id.'/wallets') ->assertOk() ->assertJsonPath('data.player.site_player_id', 'pc') ->assertJsonPath('data.wallets.0.balance', 77700) ->assertJsonPath('data.wallets.0.available_balance', 77700); });