WorldCupSettlementService.php 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. <?php
  2. namespace App\Services\WorldCup;
  3. use App\Services\WorldCup\Repositories\SqlWorldCupSettlementRepository;
  4. use App\Services\WorldCup\Repositories\WorldCupSettlementRepositoryInterface;
  5. class WorldCupSettlementService
  6. {
  7. private $repository;
  8. public function __construct(WorldCupSettlementRepositoryInterface $repository = null)
  9. {
  10. $this->repository = $repository ?: new SqlWorldCupSettlementRepository();
  11. }
  12. public function settleMatch(int $matchId, string $result, string $actor): array
  13. {
  14. if (!in_array($result, ['home', 'draw', 'away'], true)) {
  15. return $this->fail('Invalid match result');
  16. }
  17. $match = $this->repository->findMatch($matchId);
  18. if (!$match) {
  19. return $this->fail('Match not found');
  20. }
  21. if (($match['status'] ?? '') === 'finished') {
  22. return $this->fail('Match already settled');
  23. }
  24. if ($result === 'draw' && ($match['stage'] ?? '') !== 'group') {
  25. return $this->fail('Draw is only available for group stage');
  26. }
  27. $bets = $this->repository->pendingBetsForMatch($matchId);
  28. $summary = $this->settleBets($bets, $result);
  29. $this->repository->markMatchFinished($matchId, $result);
  30. $this->repository->writeAudit($actor, 'settle_match', [
  31. 'match_id' => $matchId,
  32. 'result' => $result,
  33. 'summary' => $summary,
  34. ]);
  35. return $this->success($summary);
  36. }
  37. public function settleWinner(string $selection, string $actor): array
  38. {
  39. $selection = trim($selection);
  40. if ($selection === '') {
  41. return $this->fail('Winner selection is required');
  42. }
  43. $summary = $this->settleBets($this->repository->pendingWinnerBets(), $selection);
  44. $this->repository->writeAudit($actor, 'settle_winner', [
  45. 'selection' => $selection,
  46. 'summary' => $summary,
  47. ]);
  48. return $this->success($summary);
  49. }
  50. private function settleBets(array $bets, string $winningSelection): array
  51. {
  52. $summary = [
  53. 'won_count' => 0,
  54. 'lost_count' => 0,
  55. 'paid_amount' => 0,
  56. ];
  57. foreach ($bets as $bet) {
  58. $status = (string)$bet['selection'] === $winningSelection ? 'won' : 'lost';
  59. if ($status === 'won') {
  60. $paidAmount = $this->repository->payBet($bet);
  61. $summary['won_count']++;
  62. $summary['paid_amount'] += $paidAmount;
  63. } else {
  64. $summary['lost_count']++;
  65. }
  66. $this->repository->markBetSettled((int)$bet['bet_id'], $status);
  67. }
  68. return $summary;
  69. }
  70. private function success(array $data): array
  71. {
  72. return [
  73. 'success' => true,
  74. 'message' => '',
  75. 'data' => $data,
  76. ];
  77. }
  78. private function fail(string $message): array
  79. {
  80. return [
  81. 'success' => false,
  82. 'message' => $message,
  83. 'data' => [],
  84. ];
  85. }
  86. }