Skip to content

Commit 9b6cb70

Browse files
committed
feat: Implement abandoned checkout reactivation and repository methods
1 parent 40d91f6 commit 9b6cb70

5 files changed

Lines changed: 73 additions & 0 deletions

File tree

internal/application/usecase/checkout_usecase.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,26 @@ func (uc *CheckoutUseCase) GetOrCreateCheckoutBySessionIDWithCurrency(sessionID
780780
return checkout, nil
781781
}
782782

783+
// If no active checkout found, try to get an abandoned checkout and reactivate it
784+
abandonedCheckout, err := uc.checkoutRepo.GetAbandonedBySessionID(sessionID)
785+
if err == nil {
786+
// Reactivate the abandoned checkout
787+
abandonedCheckout.Reactivate()
788+
789+
// If currency is specified, change currency if different
790+
if currency != "" && abandonedCheckout.Currency != currency {
791+
return uc.ChangeCurrency(abandonedCheckout, currency)
792+
}
793+
794+
// Update the checkout in repository
795+
err = uc.checkoutRepo.Update(abandonedCheckout)
796+
if err != nil {
797+
return nil, fmt.Errorf("failed to reactivate abandoned checkout: %w", err)
798+
}
799+
800+
return abandonedCheckout, nil
801+
}
802+
783803
// If not found, create a new one
784804
var checkoutCurrency string
785805
if currency != "" {

internal/domain/entity/checkout.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,12 @@ func (c *Checkout) MarkAsExpired() {
367367
c.LastActivityAt = time.Now()
368368
}
369369

370+
// Reactivate marks an abandoned checkout as active again
371+
func (c *Checkout) Reactivate() {
372+
c.Status = CheckoutStatusActive
373+
c.LastActivityAt = time.Now()
374+
}
375+
370376
// IsExpired checks if the checkout has expired
371377
func (c *Checkout) IsExpired() bool {
372378
return time.Now().After(c.ExpiresAt)

internal/domain/entity/checkout_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,37 @@ func TestCheckoutStatus(t *testing.T) {
323323
assert.Equal(t, CheckoutStatus("abandoned"), CheckoutStatusAbandoned)
324324
assert.Equal(t, CheckoutStatus("expired"), CheckoutStatusExpired)
325325
})
326+
327+
t.Run("MarkAsAbandoned", func(t *testing.T) {
328+
checkout, err := NewCheckout("session123", "USD")
329+
require.NoError(t, err)
330+
331+
originalTime := checkout.LastActivityAt
332+
time.Sleep(1 * time.Millisecond) // Ensure time difference
333+
334+
checkout.MarkAsAbandoned()
335+
336+
assert.Equal(t, CheckoutStatusAbandoned, checkout.Status)
337+
assert.True(t, checkout.LastActivityAt.After(originalTime))
338+
})
339+
340+
t.Run("Reactivate", func(t *testing.T) {
341+
checkout, err := NewCheckout("session123", "USD")
342+
require.NoError(t, err)
343+
344+
// First mark as abandoned
345+
checkout.MarkAsAbandoned()
346+
assert.Equal(t, CheckoutStatusAbandoned, checkout.Status)
347+
348+
originalTime := checkout.LastActivityAt
349+
time.Sleep(1 * time.Millisecond) // Ensure time difference
350+
351+
// Then reactivate
352+
checkout.Reactivate()
353+
354+
assert.Equal(t, CheckoutStatusActive, checkout.Status)
355+
assert.True(t, checkout.LastActivityAt.After(originalTime))
356+
})
326357
}
327358

328359
func TestCheckoutDTOConversions(t *testing.T) {

internal/domain/repository/checkout_repository.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ type CheckoutRepository interface {
1616
// GetBySessionID retrieves an active checkout by session ID
1717
GetBySessionID(sessionID string) (*entity.Checkout, error)
1818

19+
// GetAbandonedBySessionID retrieves an abandoned checkout by session ID
20+
GetAbandonedBySessionID(sessionID string) (*entity.Checkout, error)
21+
1922
// Update updates a checkout
2023
Update(checkout *entity.Checkout) error
2124

internal/infrastructure/repository/gorm/checkout_repository.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,19 @@ func (c *CheckoutRepository) GetBySessionID(sessionID string) (*entity.Checkout,
8888
return &checkout, nil
8989
}
9090

91+
// GetAbandonedBySessionID implements repository.CheckoutRepository.
92+
func (c *CheckoutRepository) GetAbandonedBySessionID(sessionID string) (*entity.Checkout, error) {
93+
var checkout entity.Checkout
94+
err := c.db.Preload("Items").Preload("Items.Product").Preload("Items.ProductVariant").
95+
Preload("User").
96+
Where("session_id = ? AND status = ?", sessionID, entity.CheckoutStatusAbandoned).
97+
First(&checkout).Error
98+
if err != nil {
99+
return nil, err
100+
}
101+
return &checkout, nil
102+
}
103+
91104
// GetByUserID implements repository.CheckoutRepository.
92105
func (c *CheckoutRepository) GetByUserID(userID uint) (*entity.Checkout, error) {
93106
var checkout entity.Checkout

0 commit comments

Comments
 (0)