fix(core): harden settlement and wallet integration

This commit is contained in:
wchino
2026-07-22 01:40:37 +08:00
parent 150c3e7ebd
commit 35f6e46958
54 changed files with 2564 additions and 359 deletions

View File

@@ -10,11 +10,11 @@ use App\Lottery\DrawStatus;
use App\Models\JackpotPool;
use App\Models\TicketOrder;
use App\Models\SettlementBatch;
use App\Support\PlayerFundingMode;
use Illuminate\Support\Facades\DB;
use App\Lottery\SettlementBatchStatus;
use App\Services\AgentSettlement\GameSettlementReversalService;
use App\Services\Ticket\TicketWalletService;
use App\Support\PlayerFundingMode;
use App\Services\AgentSettlement\GameSettlementReversalService;
final class SettlementBatchWorkflowService
{
@@ -67,7 +67,7 @@ final class SettlementBatchWorkflowService
if ($itemIds !== []) {
$items = TicketItem::query()->whereIn('id', $itemIds)->get();
foreach ($items as $item) {
$this->gameSettlementReversal->reverseTicketItem($item);
$this->gameSettlementReversal->reverseTicketItem($item, (int) $locked->settle_version);
}
TicketItem::query()
@@ -118,15 +118,22 @@ final class SettlementBatchWorkflowService
throw new \RuntimeException('draw_has_unsettled_tickets');
}
if ($batchItemIds !== []) {
$orphanPendingPayout = TicketItem::query()
->where('draw_id', $locked->draw_id)
->where('status', 'pending_payout')
->whereNotIn('id', $batchItemIds)
->exists();
if ($orphanPendingPayout) {
throw new \RuntimeException('draw_has_unsettled_tickets');
}
$orphanPendingPayout = TicketItem::query()
->where('draw_id', $locked->draw_id)
->where('status', 'pending_payout')
->whereNotIn('id', $batchItemIds)
->whereNotExists(function ($query): void {
$query->selectRaw('1')
->from('ticket_settlement_details as other_details')
->join('settlement_batches as other_batches', 'other_batches.id', '=', 'other_details.settlement_batch_id')
->whereColumn('other_details.ticket_item_id', 'ticket_items.id')
->whereColumn('other_batches.draw_id', 'ticket_items.draw_id')
->where('other_batches.status', SettlementBatchStatus::Approved->value)
->where('other_batches.review_status', 'approved');
})
->exists();
if ($orphanPendingPayout) {
throw new \RuntimeException('draw_has_unsettled_tickets');
}
$details = $locked->details()->with(['ticketItem.order'])->get();
@@ -193,10 +200,34 @@ final class SettlementBatchWorkflowService
'paid_at' => now(),
])->save();
Draw::query()->whereKey($locked->draw_id)->update([
'status' => DrawStatus::Settled->value,
'settle_version' => (int) $locked->settle_version,
]);
$hasIncompleteProviderBatch = SettlementBatch::query()
->where('draw_id', $locked->draw_id)
->whereIn('status', [
SettlementBatchStatus::Running->value,
SettlementBatchStatus::PendingReview->value,
SettlementBatchStatus::Approved->value,
])
->exists();
$hasPendingTicket = TicketItem::query()
->where('draw_id', $locked->draw_id)
->whereIn('status', [
'pending_confirm',
'partial_pending_confirm',
'pending_draw',
'pending_payout',
])
->exists();
if (! $hasIncompleteProviderBatch && ! $hasPendingTicket) {
$settleVersion = (int) SettlementBatch::query()
->where('draw_id', $locked->draw_id)
->where('status', SettlementBatchStatus::Paid->value)
->max('settle_version');
Draw::query()->whereKey($locked->draw_id)->update([
'status' => DrawStatus::Settled->value,
'settle_version' => $settleVersion,
]);
}
return $locked->refresh();
});