feat(enakgame): filter play history by game and status
GET /customer/enakgame/sessions takes optional game_id and status, so a game reloaded mid-play finds the session it was running (status=STARTED) instead of starting a new one and charging EnakCoin again. An invalid game_id or status is refused. integration-enakgame.md §4.4 now describes recovery after a reload: keep the session_id in sessionStorage, continue a STARTED session before expires_at, and call complete again for a COMPLETED one to get the full answer, prize included. The mobile guide and RFC §11 mention the filters. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
b5d2cd491a
commit
52e8fe11c6
@@ -287,7 +287,7 @@ func TestGameSessionRepository_ReadsAndMoves(t *testing.T) {
|
||||
assert.True(t, got.Flagged)
|
||||
assert.NotNil(t, got.CompletionFailedAt)
|
||||
|
||||
sessions, total, err := f.sessions.ListCustomerSessions(ctx, f.customer, 0, 1)
|
||||
sessions, total, err := f.sessions.ListCustomerSessions(ctx, CustomerSessionFilter{CustomerID: f.customer, Limit: 1})
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 2, total)
|
||||
assert.Len(t, sessions, 1)
|
||||
|
||||
@@ -50,7 +50,7 @@ type GameSessionRepository interface {
|
||||
GetSessionBySpendTransaction(ctx context.Context, spendTransactionID uuid.UUID) (*entities.GameSession, error)
|
||||
// ListCustomerSessions returns a page of a customer's sessions, newest first, and
|
||||
// the total.
|
||||
ListCustomerSessions(ctx context.Context, customerID uuid.UUID, offset, limit int) ([]entities.GameSession, int64, error)
|
||||
ListCustomerSessions(ctx context.Context, filter CustomerSessionFilter) ([]entities.GameSession, int64, error)
|
||||
|
||||
CompleteSession(ctx context.Context, id uuid.UUID, completion GameSessionCompletion) (bool, error)
|
||||
RefundSession(ctx context.Context, id, refundTransactionID uuid.UUID, reason string, endedAt time.Time) (bool, error)
|
||||
@@ -116,8 +116,26 @@ func (r *gameSessionRepository) GetSessionBySpendTransaction(ctx context.Context
|
||||
return r.first(DBFromContext(ctx, r.db).WithContext(ctx).Where("spend_transaction_id = ?", spendTransactionID))
|
||||
}
|
||||
|
||||
func (r *gameSessionRepository) ListCustomerSessions(ctx context.Context, customerID uuid.UUID, offset, limit int) ([]entities.GameSession, int64, error) {
|
||||
q := DBFromContext(ctx, r.db).WithContext(ctx).Model(&entities.GameSession{}).Where("customer_id = ?", customerID)
|
||||
// CustomerSessionFilter selects a customer's sessions.
|
||||
type CustomerSessionFilter struct {
|
||||
CustomerID uuid.UUID
|
||||
// Nil for every game.
|
||||
GameID *uuid.UUID
|
||||
// Empty for every status.
|
||||
Status string
|
||||
Offset int
|
||||
Limit int
|
||||
}
|
||||
|
||||
func (r *gameSessionRepository) ListCustomerSessions(ctx context.Context, filter CustomerSessionFilter) ([]entities.GameSession, int64, error) {
|
||||
q := DBFromContext(ctx, r.db).WithContext(ctx).Model(&entities.GameSession{}).Where("customer_id = ?", filter.CustomerID)
|
||||
if filter.GameID != nil {
|
||||
q = q.Where("game_id = ?", *filter.GameID)
|
||||
}
|
||||
if filter.Status != "" {
|
||||
q = q.Where("status = ?", filter.Status)
|
||||
}
|
||||
offset, limit := filter.Offset, filter.Limit
|
||||
var total int64
|
||||
if err := q.Count(&total).Error; err != nil {
|
||||
return nil, 0, fmt.Errorf("failed to count game sessions: %w", err)
|
||||
|
||||
Reference in New Issue
Block a user