| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- <?php
- namespace Tests\Integration;
- use App\Http\Controllers\admin\Balance;
- use Illuminate\Config\Repository;
- use Illuminate\Database\Capsule\Manager;
- use Illuminate\Foundation\Application;
- use Illuminate\Http\Request;
- use Illuminate\Support\Facades\DB;
- use Illuminate\Support\Facades\Facade;
- use PHPUnit\Framework\TestCase;
- class AdminBonusLogTest extends TestCase
- {
- private Application $app;
- protected function setUp(): void
- {
- Facade::clearResolvedInstances();
- $this->app = new Application(dirname(__DIR__, 2));
- $this->app->instance('config', new Repository(['app' => ['locale' => 'zh']]));
- $this->app->instance('log', new \Psr\Log\NullLogger());
- $translator = new \Illuminate\Translation\Translator(new \Illuminate\Translation\ArrayLoader(), 'zh');
- $this->app->instance('translator', $translator);
- $this->app->instance('validator', new \Illuminate\Validation\Factory($translator, $this->app));
- $this->app->instance(\Illuminate\Contracts\Routing\ResponseFactory::class, new \Tests\Support\JsonResponseFactory());
- Facade::setFacadeApplication($this->app);
- $db = new Manager($this->app);
- $db->addConnection(['driver' => 'sqlite', 'database' => ':memory:', 'prefix' => 'bot_']);
- $db->setAsGlobal(); $db->bootEloquent(); $this->app->instance('db', $db->getDatabaseManager());
- $this->app->bind('db.schema', fn () => $db->schema());
- foreach ([
- 'users' => 'id INTEGER PRIMARY KEY,member_id TEXT,account TEXT,username TEXT,first_name TEXT,admin_note TEXT,status INTEGER,phone TEXT,visitor_id TEXT,register_ip TEXT,"from" INTEGER',
- 'balance_logs' => 'id INTEGER PRIMARY KEY,member_id TEXT,type INTEGER,change_type TEXT,amount TEXT,before_balance TEXT,after_balance TEXT,related_id INTEGER,remark TEXT,frozen_status INTEGER,created_at TEXT,updated_at TEXT',
- 'promotion_activities' => 'id INTEGER PRIMARY KEY,type INTEGER',
- 'promotion_rewards' => 'id INTEGER PRIMARY KEY,activity_id INTEGER,credited_log_id INTEGER',
- 'recharge_bonus_rewards' => 'id INTEGER PRIMARY KEY,credited_log_id INTEGER',
- ] as $table => $columns) DB::statement('CREATE TABLE bot_' . $table . ' (' . $columns . ')');
- DB::table('users')->insert(['id' => 1, 'member_id' => 'm1', 'account' => 'alice', 'from' => 1]);
- foreach ([[1,2,'余额宝利息','2'],[2,1,'余额宝利息','3'],[3,1,'优惠活动','666'],[4,1,'优惠活动','500'],[5,1,'流水解冻','2'],[6,2,'流水解冻','-2'],[7,1,'充值','100'],[8,1,'即充即送','5']] as [$id,$type,$name,$amount]) {
- DB::table('balance_logs')->insert(['id'=>$id,'member_id'=>'m1','type'=>$type,'change_type'=>$name,'amount'=>$amount,'created_at'=>'2026-11-05 12:00:00']);
- }
- DB::table('promotion_activities')->insert([['id'=>9,'type'=>9],['id'=>7,'type'=>7]]);
- DB::table('promotion_rewards')->insert([['id'=>1,'activity_id'=>9,'credited_log_id'=>3],['id'=>2,'activity_id'=>7,'credited_log_id'=>4]]);
- Request::macro('validate', function (array $rules) { return app('validator')->make($this->all(), $rules)->validate(); });
- }
- protected function tearDown(): void
- {
- DB::disconnect(); Facade::clearResolvedInstances(); parent::tearDown();
- }
- private function records(array $filters = []): array
- {
- $this->app->instance('request', Request::create('/admin/balance/log', 'GET', $filters));
- $body = (new Balance())->log()->getData(true);
- $this->assertSame(0, $body['code'], $body['msg']);
- return $body['data'];
- }
- public function test_bonus_includes_available_and_legacy_rewards_without_counting_transfers(): void
- {
- $data=$this->records(['is_fancai'=>1,'type'=>2,'limit'=>2]);
- $this->assertSame(5,$data['total']);
- $this->assertSame('1176.00',$data['total_amount']);
- $this->assertCount(2,$data['data']);
- $this->assertSame([8,4],array_column($data['data'],'id'));
- $this->assertSame('净亏邀请',$data['data'][1]['change_type']);
- $this->assertArrayNotHasKey('activity_types', $data);
- foreach (['reward_source', 'activity_type', 'activity_id'] as $field) $this->assertArrayNotHasKey($field, $data['data'][1]);
- $this->assertSame('1176.00',$this->records(['is_fancai'=>1,'page'=>2,'limit'=>2])['total_amount']);
- }
- public function test_activity_and_member_filters_apply_to_counts_and_sum(): void
- {
- $data=$this->records(['is_fancai'=>1,'change_type'=>'转盘','account'=>'lic']);
- $this->assertSame(1,$data['total']);$this->assertSame('666.00',$data['total_amount']);
- $this->assertSame('转盘',$data['data'][0]['change_type']);
- $this->assertSame(0,$this->records(['is_fancai'=>1,'account'=>'bob'])['total']);
- $this->assertSame(2,$this->records(['is_fancai'=>1,'change_type'=>'余额宝利息'])['total']);
- }
- public function test_regular_balance_type_filter_remains_effective(): void
- {
- $this->assertSame(2,$this->records(['type'=>2])['total']);
- $this->assertSame(8,$this->records()['total']);
- $ordinary = $this->records(['change_type'=>'优惠活动']);
- $this->assertSame(2, $ordinary['total']);
- $this->assertSame(['优惠活动'], array_values(array_unique(array_column($ordinary['data'], 'change_type'))));
- }
- private function log(int $id, string $type, string $amount = '10'): void
- {
- DB::table('balance_logs')->insert(['id'=>$id, 'member_id'=>'m1', 'type'=>1, 'change_type'=>$type,
- 'amount'=>$amount, 'before_balance'=>'100.00', 'after_balance'=>bcadd('100', $amount, 2),
- 'related_id'=>1, 'created_at'=>'2026-11-05 12:00:00']);
- }
- public function test_each_dropdown_value_filters_exactly_the_type_returned_in_rows(): void
- {
- DB::table('promotion_activities')->insert([['id'=>8,'type'=>8],['id'=>10,'type'=>10]]);
- foreach ([80=>8, 100=>10] as $log => $activity) {
- $this->log($log, '优惠活动');
- DB::table('promotion_rewards')->insert(['activity_id'=>$activity,'credited_log_id'=>$log]);
- }
- $this->log(101, '优惠活动', '6');
- DB::table('recharge_bonus_rewards')->insert(['credited_log_id'=>101]);
- $this->log(102, '优惠活动', '4'); // Same related_id as a promotion reward; it is not that reward's log.
- $this->log(103, '老用户回归');
- $this->log(104, '注册赠送');
- $this->log(105, '充值返现');
- // Unclaimed/coupon rewards and zero-valued channel rewards have no credited log.
- DB::table('promotion_rewards')->insert(['activity_id'=>9,'credited_log_id'=>null]);
- DB::table('recharge_bonus_rewards')->insert(['credited_log_id'=>null]);
- $options = $this->records(['is_fancai'=>1])['change_types'];
- $this->assertContains('转盘', $options);
- $this->assertContains('净亏邀请', $options);
- $this->assertContains('首充奖励', $options);
- $this->assertContains('邀请升级奖励', $options);
- foreach ($options as $type) {
- $filtered = $this->records(['is_fancai'=>1, 'change_type'=>$type, 'limit'=>100]);
- $this->assertGreaterThan(0, $filtered['total'], $type);
- $this->assertSame([$type], array_values(array_unique(array_column($filtered['data'], 'change_type'))));
- }
- $generic = $this->records(['is_fancai'=>1, 'change_type'=>'优惠活动']);
- $this->assertSame([102], array_column($generic['data'], 'id'));
- $this->assertSame('4.00', $generic['total_amount']);
- $channel = $this->records(['is_fancai'=>1, 'change_type'=>'充值渠道赠送']);
- $this->assertSame([101], array_column($channel['data'], 'id'));
- $this->assertSame('6.00', $channel['total_amount']);
- $this->assertSame('优惠活动', DB::table('balance_logs')->where('id', 3)->value('change_type'));
- }
- public function test_source_filter_pagination_totals_and_money_fields_remain_consistent(): void
- {
- $this->log(200, '优惠活动', '20');
- DB::table('promotion_rewards')->insert(['activity_id'=>9,'credited_log_id'=>200]);
- foreach ([1=>200, 2=>3] as $page=>$id) {
- $data = $this->records(['is_fancai'=>1, 'change_type'=>'转盘', 'limit'=>1, 'page'=>$page]);
- $this->assertSame(2, $data['total']);
- $this->assertSame('686.00', $data['total_amount']);
- $this->assertSame([$id], array_column($data['data'], 'id'));
- }
- $row = $this->records(['is_fancai'=>1, 'change_type'=>'转盘', 'limit'=>1])['data'][0];
- $this->assertSame('100.00', $row['before_balance']);
- $this->assertSame('20', $row['amount']);
- $this->assertSame('120.00', $row['after_balance']);
- }
- public function test_legacy_schema_keeps_generic_rewards_readable_and_specific_filters_empty(): void
- {
- DB::statement('DROP TABLE bot_promotion_rewards');
- DB::statement('DROP TABLE bot_promotion_activities');
- DB::statement('DROP TABLE bot_recharge_bonus_rewards');
- $generic = $this->records(['is_fancai'=>1, 'change_type'=>'优惠活动']);
- $this->assertSame(2, $generic['total']);
- $this->assertSame('1166.00', $generic['total_amount']);
- foreach (['转盘', '净亏邀请', '充值渠道赠送'] as $type) {
- $this->assertSame(0, $this->records(['is_fancai'=>1, 'change_type'=>$type])['total']);
- }
- }
- }
|