feat: 拆分开奖与结算审核流程,新增手动结果录入、重开和派彩审批接口

This commit is contained in:
2026-05-16 18:01:06 +08:00
parent 83046b402d
commit 4f143c7cb1
38 changed files with 1992 additions and 170 deletions

View File

@@ -110,6 +110,100 @@ test('ticket preview returns computed summary for open draw', function (): void
->assertJsonCount(2, 'data.lines');
});
test('module 6 box family expands combinations and computes amount semantics', function (): void {
$player = ticketPlayerWithWallet(500_000);
ticketOpenDraw();
$payload = [
'draw_id' => '20260511-001',
'currency_code' => 'NPR',
'client_trace_id' => 'trace-module6-box',
'lines' => [
['number' => '1234', 'play_code' => 'box', 'amount' => 10_000],
['number' => '1123', 'play_code' => 'box', 'amount' => 10_000],
['number' => '1122', 'play_code' => 'box', 'amount' => 10_000],
['number' => '1112', 'play_code' => 'box', 'amount' => 10_000],
['number' => '1111', 'play_code' => 'box', 'amount' => 10_000],
['number' => '1122', 'play_code' => 'ibox', 'amount' => 100],
['number' => '1234', 'play_code' => 'mbox', 'amount' => 10_001],
],
];
$resp = $this->withHeader('Authorization', 'Bearer dev:'.$player->id)
->postJson('/api/v1/ticket/preview', $payload)
->assertOk();
$lines = collect($resp->json('data.lines'))->keyBy('client_line_no');
expect($lines[1]['combination_count'])->toBe(24)
->and($lines[2]['combination_count'])->toBe(12)
->and($lines[3]['combination_count'])->toBe(6)
->and($lines[4]['combination_count'])->toBe(4)
->and($lines[5]['combination_count'])->toBe(1)
->and($lines[6]['combination_count'])->toBe(6)
->and($lines[6]['total_bet_amount'])->toBe(600)
->and($lines[7]['combination_count'])->toBe(24)
->and($lines[7]['total_bet_amount'])->toBe(9_984)
->and($lines[7]['actual_deduct_amount'])->toBe(9_984)
->and($lines[7]['rule_snapshot_json']['rounding_refund_amount'] ?? null)->toBe(17);
});
test('module 6 roll expands each R position and charges per expanded combination', function (): void {
$player = ticketPlayerWithWallet(500_000);
ticketOpenDraw();
$resp = $this->withHeader('Authorization', 'Bearer dev:'.$player->id)
->postJson('/api/v1/ticket/preview', [
'draw_id' => '20260511-001',
'currency_code' => 'NPR',
'client_trace_id' => 'trace-module6-roll',
'lines' => [
['number' => 'R234', 'play_code' => 'roll', 'amount' => 100],
['number' => 'RR34', 'play_code' => 'roll', 'amount' => 100],
],
])
->assertOk();
$lines = collect($resp->json('data.lines'))->keyBy('client_line_no');
expect($lines[1]['combination_count'])->toBe(10)
->and($lines[1]['total_bet_amount'])->toBe(1_000)
->and($lines[2]['combination_count'])->toBe(100)
->and($lines[2]['total_bet_amount'])->toBe(10_000);
});
test('module 6 reserved and phase two plays are not available for betting or public entry', function (): void {
$player = ticketPlayerWithWallet();
ticketOpenDraw();
$this->withHeader('Authorization', 'Bearer dev:'.$player->id)
->postJson('/api/v1/ticket/preview', [
'draw_id' => '20260511-001',
'currency_code' => 'NPR',
'client_trace_id' => 'trace-module6-half-box',
'lines' => [
['number' => '1234', 'play_code' => 'half_box', 'amount' => 10_000],
],
])
->assertStatus(400)
->assertJsonPath('code', ErrorCode::PlayModeClosed->value);
$this->withHeader('Authorization', 'Bearer dev:'.$player->id)
->postJson('/api/v1/ticket/preview', [
'draw_id' => '20260511-001',
'currency_code' => 'NPR',
'client_trace_id' => 'trace-module6-5d',
'lines' => [
['number' => '12345', 'play_code' => '5d', 'amount' => 10_000],
],
])
->assertStatus(400)
->assertJsonPath('code', ErrorCode::PlayModeClosed->value);
$plays = collect($this->getJson('/api/v1/play/effective?currency=NPR')->assertOk()->json('data.plays'));
expect($plays->firstWhere('play_code', 'half_box')['config']['is_enabled'])->toBeFalse()
->and($plays->contains('play_code', '5d'))->toBeFalse()
->and($plays->contains('play_code', '6d'))->toBeFalse();
});
test('ticket place deducts wallet and persists order items combinations and logs', function (): void {
$player = ticketPlayerWithWallet();
ticketOpenDraw();