Skip to content

Commit 1d73627

Browse files
committed
Require buy-in before cash-out
1 parent f71e6f4 commit 1d73627

5 files changed

Lines changed: 57 additions & 1 deletion

File tree

PokerBank.Domain/PokerGame.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ private Result<GameEntry> AddEntry(Guid playerId, Money amount, GameEntryType ty
7979
return Result.Fail<GameEntry>(PokerGameErrors.InvalidAmount());
8080
}
8181

82+
if (type == GameEntryType.CashOut && !HasBuyIn(playerId))
83+
{
84+
return Result.Fail<GameEntry>(PokerGameErrors.PlayerHasNoBuyIns());
85+
}
86+
8287
if (type == GameEntryType.CashOut && TotalCashOuts + amount > TotalBuyIns)
8388
{
8489
return Result.Fail<GameEntry>(PokerGameErrors.CashOutsExceedBuyIns());
@@ -92,6 +97,11 @@ private Result<GameEntry> AddEntry(Guid playerId, Money amount, GameEntryType ty
9297

9398
private bool IsClosed() => Status == GameStatus.Closed;
9499

100+
private bool HasBuyIn(Guid playerId)
101+
{
102+
return _entries.Any(entry => entry.PlayerId == playerId && entry.Type == GameEntryType.BuyIn);
103+
}
104+
95105
private Money SumEntries(GameEntryType type)
96106
{
97107
return _entries

PokerBank.Domain/PokerGameErrorCode.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ public enum PokerGameErrorCode
66
InvalidAmount = 2,
77
GameClosed = 3,
88
CashOutsExceedBuyIns = 4,
9-
BuyInsMustEqualCashOuts = 5
9+
BuyInsMustEqualCashOuts = 5,
10+
PlayerHasNoBuyIns = 6
1011
}

PokerBank.Domain/PokerGameErrors.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ public static class PokerGameErrors
1818
PokerGameErrorCode.CashOutsExceedBuyIns,
1919
"Cash-outs cannot exceed total buy-ins.");
2020

21+
public static PokerGameError PlayerHasNoBuyIns() => new(
22+
PokerGameErrorCode.PlayerHasNoBuyIns,
23+
"Player must have a buy-in before cashing out.");
24+
2125
public static PokerGameError BuyInsMustEqualCashOuts() => new(
2226
PokerGameErrorCode.BuyInsMustEqualCashOuts,
2327
"Cannot close a game until total buy-ins equal total cash-outs.");

PokerBank.Tests/Domain/PokerGameTests.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,23 @@ public void AddCashOut_Fails_WhenTotalCashOutsWouldExceedTotalBuyIns()
100100
Assert.DoesNotContain(game.Entries, entry => entry.Type == GameEntryType.CashOut);
101101
}
102102

103+
[Fact]
104+
public void AddCashOut_Fails_WhenPlayerHasNoBuyIns()
105+
{
106+
var game = PokerGame.Create();
107+
var playerWithBuyIn = Guid.NewGuid();
108+
var playerWithoutBuyIn = Guid.NewGuid();
109+
110+
Assert.True(game.AddBuyIn(playerWithBuyIn, new Money(100m)).IsSuccess);
111+
112+
var result = game.AddCashOut(playerWithoutBuyIn, new Money(50m));
113+
114+
Assert.True(result.IsFailed);
115+
var error = Assert.Single(result.Errors.OfType<PokerGameError>());
116+
Assert.Equal(PokerGameErrorCode.PlayerHasNoBuyIns, error.Code);
117+
Assert.DoesNotContain(game.Entries, entry => entry.Type == GameEntryType.CashOut);
118+
}
119+
103120
[Fact]
104121
public void ClosedGame_CannotBeModified()
105122
{

PokerBank.Tests/Features/Games/GamesApiTests.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,28 @@ public async Task AddCashOut_ReturnsNotFound_WhenPlayerDoesNotExist()
386386
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
387387
}
388388

389+
[Fact]
390+
public async Task AddCashOut_ReturnsConflict_WhenPlayerHasNotBoughtIn()
391+
{
392+
using var client = factory.CreateHttpsClient();
393+
394+
var game = await CreateGame(client);
395+
var playerWithBuyIn = await CreatePlayer(client, "Lorenzo");
396+
var playerWithoutBuyIn = await CreatePlayer(client, "Maya");
397+
await AddBuyIn(client, game.Id, playerWithBuyIn.Id, 100m);
398+
399+
var response = await client.PostAsJsonAsync(
400+
$"/games/{game.Id}/cash-outs",
401+
new { PlayerId = playerWithoutBuyIn.Id, Amount = 50m });
402+
403+
Assert.Equal(HttpStatusCode.Conflict, response.StatusCode);
404+
405+
var error = await response.Content.ReadFromJsonAsync<ErrorResponse>();
406+
407+
Assert.NotNull(error);
408+
Assert.Equal("Player must have a buy-in before cashing out.", error.Error);
409+
}
410+
389411
[Theory]
390412
[InlineData(0)]
391413
[InlineData(-10)]
@@ -636,6 +658,8 @@ private sealed record GameDetailsResponse(
636658

637659
private sealed record PlayerResponse(Guid Id, string Name, bool IsActive);
638660

661+
private sealed record ErrorResponse(string Error);
662+
639663
private sealed record GameEntryDetailsResponse(
640664
Guid Id,
641665
Guid PlayerId,

0 commit comments

Comments
 (0)