|
|
@@ -108,6 +108,7 @@ class AutomaticRewardGrantTest extends TestCase
|
|
|
});
|
|
|
$this->migration()->up();
|
|
|
$this->rulesMigration()->up();
|
|
|
+ (require dirname(__DIR__, 2) . '/database/migrations/2026_11_05_160000_add_backflow_granted_amounts.php')->up();
|
|
|
DB::table('rebate_rules')->insert(['category' => 'self:lottery', 'level' => 1, 'min_effective_amount' => 0, 'percentage' => '0.5', 'turnover_multiple' => 0]);
|
|
|
DB::table('backflow_rules')->insert(['category' => 'self:lottery', 'min_loss_amount' => 100, 'reward_amount' => 35, 'turnover_multiple' => 0]);
|
|
|
$this->request('/admin/rebate');
|
|
|
@@ -536,6 +537,65 @@ class AutomaticRewardGrantTest extends TestCase
|
|
|
$this->assertEquals(120, DB::table('backflow')->where('id', $row->id)->value('need_flow'));
|
|
|
}
|
|
|
|
|
|
+ public function test_backflow_can_be_granted_again_for_the_remainder_until_the_month_is_closed(): void
|
|
|
+ {
|
|
|
+ // now = 2026-10-25 14:30 上海;当月 2026-10。钱包初始 20。
|
|
|
+ DB::table('backflow_rules')->insert([
|
|
|
+ ['category' => 'self:lottery', 'min_loss_amount' => 10, 'reward_amount' => 8, 'turnover_multiple' => 1],
|
|
|
+ ['category' => 'self:lottery', 'min_loss_amount' => 300, 'reward_amount' => 50, 'turnover_multiple' => 1],
|
|
|
+ ]);
|
|
|
+ $id = $this->backflow(['date' => '2026-10', 'recharge_amount' => '50.00', 'withdrawal_amount' => '0']); // 亏 50
|
|
|
+ $this->enable('backflow');
|
|
|
+ $this->assertSame(0, $this->runRewards()['backflow']['granted'], '自动发放不发当月');
|
|
|
+
|
|
|
+ // 第一次手动发放:当月亏 50 → 8,记为部分发放
|
|
|
+ $this->assertTrue(RewardGrantService::grant('backflow', $id, 'operator-one'));
|
|
|
+ $row = DB::table('backflow')->where('id', $id)->first();
|
|
|
+ $this->assertSame([2, '8.00', '8.00'], [(int) $row->status, bcadd($row->amount, 0, 2), bcadd($row->granted_amount, 0, 2)]);
|
|
|
+ $this->assertEquals(28, DB::table('wallets')->where('member_id', '1001')->value('available_balance'));
|
|
|
+ $this->assertSame(['amount' => '8.00', 'granted_amount' => '8.00', 'pending_amount' => '0.00', 'can_grant' => false, 'status_text' => '部分发放'],
|
|
|
+ BackflowService::grantFields((array) $row));
|
|
|
+
|
|
|
+ // 没有差额时当月不能再发
|
|
|
+ try { RewardGrantService::grant('backflow', $id, 'operator-one'); $this->fail('expected exception'); }
|
|
|
+ catch (\RuntimeException $e) { $this->assertSame('暂无可发放金额', $e->getMessage()); }
|
|
|
+
|
|
|
+ // 继续亏到 350:同步后应发 50,已发 8,待发 42
|
|
|
+ $this->fact('1001', 'self:lottery', '2026-10-20 12:00:00', '300', '-300');
|
|
|
+ (new RewardBaseSyncService())->run('2026-10-20', '2026-10-20');
|
|
|
+ $fields = BackflowService::grantFields((array) DB::table('backflow')->where('id', $id)->first());
|
|
|
+ $this->assertSame(['50.00', '8.00', '42.00', true], [$fields['amount'], $fields['granted_amount'], $fields['pending_amount'], $fields['can_grant']]);
|
|
|
+
|
|
|
+ $this->assertTrue(RewardGrantService::grant('backflow', $id, 'operator-two'));
|
|
|
+ $row = DB::table('backflow')->where('id', $id)->first();
|
|
|
+ $this->assertSame([2, '50.00', '50.00'], [(int) $row->status, bcadd($row->granted_amount, 0, 2), bcadd($row->granted_need_flow, 0, 2)]);
|
|
|
+ $this->assertEquals(70, DB::table('wallets')->where('member_id', '1001')->value('available_balance'));
|
|
|
+ $this->assertSame(['8.0000000000', '42.0000000000'], DB::table('balance_logs')->where('change_type', '回水')->orderBy('id')->pluck('amount')
|
|
|
+ ->map(fn ($v) => bcadd($v, 0, 10))->all());
|
|
|
+ $this->assertStringContainsString('本次发放:42.00;累计发放:50.00', DB::table('balance_logs')->where('change_type', '回水')->orderByDesc('id')->value('remark'));
|
|
|
+
|
|
|
+ // 下个月自动发放:无差额,只结清为已发放,不重复入账
|
|
|
+ Carbon::setTestNow(Carbon::parse('2026-11-01 14:30:00', 'Asia/Shanghai'));
|
|
|
+ $this->assertSame(1, $this->runRewards()['backflow']['granted']);
|
|
|
+ $this->assertSame(1, (int) DB::table('backflow')->where('id', $id)->value('status'));
|
|
|
+ $this->assertEquals(70, DB::table('wallets')->where('member_id', '1001')->value('available_balance'));
|
|
|
+ $this->assertSame(2, DB::table('balance_logs')->where('change_type', '回水')->count());
|
|
|
+
|
|
|
+ // 笔笔返仍须等当天结束
|
|
|
+ $rebate = $this->rebate(['date' => Carbon::now('America/New_York')->format('Y-m-d')]);
|
|
|
+ $this->expectExceptionMessage('未到发放时间');
|
|
|
+ RewardGrantService::grant('rebate', $rebate, 'operator-one');
|
|
|
+ }
|
|
|
+
|
|
|
+ public function test_granted_amount_migration_backfills_paid_rows(): void
|
|
|
+ {
|
|
|
+ $paid = DB::table('backflow')->insertGetId(['member_id' => '1001', 'date' => '2026-08', 'status' => 1, 'amount' => '35', 'need_flow' => '70', 'granted_amount' => 0]);
|
|
|
+ $open = DB::table('backflow')->insertGetId(['member_id' => '1001', 'date' => '2026-07', 'status' => 0, 'amount' => '35', 'granted_amount' => 0]);
|
|
|
+ (require dirname(__DIR__, 2) . '/database/migrations/2026_11_05_160000_add_backflow_granted_amounts.php')->up();
|
|
|
+ $this->assertEquals([35, 70], array_values((array) DB::table('backflow')->where('id', $paid)->first(['granted_amount', 'granted_need_flow'])));
|
|
|
+ $this->assertEquals(0, DB::table('backflow')->where('id', $open)->value('granted_amount'));
|
|
|
+ }
|
|
|
+
|
|
|
public function test_sync_cursor_only_revisits_changed_facts_and_backfill_range_creates_missing_rows(): void
|
|
|
{
|
|
|
$this->fact('3001', 'third:1', '2026-10-20 13:00:00', '100', '-100', ['updated_at' => '2026-10-20 13:00:00']);
|