This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
)
|
||||
|
||||
type PurchaseRoute string
|
||||
|
||||
const (
|
||||
PurchaseRouteNewPurchase PurchaseRoute = "new_purchase"
|
||||
PurchaseRoutePurchaseToRenewal PurchaseRoute = "purchase_to_renewal"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrSingleModePlanMismatch = errors.New("single subscribe mode plan mismatch")
|
||||
)
|
||||
|
||||
type PurchaseRouteDecision struct {
|
||||
SingleMode bool
|
||||
Route PurchaseRoute
|
||||
ResolvedSubscribeID int64
|
||||
Anchor *user.Subscribe
|
||||
}
|
||||
|
||||
type FindSingleModeAnchorFunc func(ctx context.Context, userID int64) (*user.Subscribe, error)
|
||||
|
||||
func ResolvePurchaseRoute(
|
||||
ctx context.Context,
|
||||
singleMode bool,
|
||||
userID int64,
|
||||
requestedSubscribeID int64,
|
||||
findAnchor FindSingleModeAnchorFunc,
|
||||
) (*PurchaseRouteDecision, error) {
|
||||
decision := &PurchaseRouteDecision{
|
||||
SingleMode: singleMode,
|
||||
Route: PurchaseRouteNewPurchase,
|
||||
ResolvedSubscribeID: requestedSubscribeID,
|
||||
}
|
||||
|
||||
if !singleMode || userID == 0 || findAnchor == nil {
|
||||
return decision, nil
|
||||
}
|
||||
|
||||
anchorSub, err := findAnchor(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if anchorSub == nil {
|
||||
return decision, nil
|
||||
}
|
||||
|
||||
if requestedSubscribeID != anchorSub.SubscribeId {
|
||||
return nil, ErrSingleModePlanMismatch
|
||||
}
|
||||
|
||||
decision.Route = PurchaseRoutePurchaseToRenewal
|
||||
decision.ResolvedSubscribeID = anchorSub.SubscribeId
|
||||
decision.Anchor = anchorSub
|
||||
return decision, nil
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestResolvePurchaseRoute(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
t.Run("single mode disabled", func(t *testing.T) {
|
||||
called := false
|
||||
decision, err := ResolvePurchaseRoute(ctx, false, 1, 100, func(ctx context.Context, userID int64) (*user.Subscribe, error) {
|
||||
called = true
|
||||
return nil, nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, decision)
|
||||
require.Equal(t, PurchaseRouteNewPurchase, decision.Route)
|
||||
require.Equal(t, int64(100), decision.ResolvedSubscribeID)
|
||||
require.False(t, called)
|
||||
})
|
||||
|
||||
t.Run("single mode but empty user", func(t *testing.T) {
|
||||
decision, err := ResolvePurchaseRoute(ctx, true, 0, 100, nil)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, decision)
|
||||
require.Equal(t, PurchaseRouteNewPurchase, decision.Route)
|
||||
require.Equal(t, int64(100), decision.ResolvedSubscribeID)
|
||||
})
|
||||
|
||||
t.Run("single mode no anchor", func(t *testing.T) {
|
||||
decision, err := ResolvePurchaseRoute(ctx, true, 1, 100, func(ctx context.Context, userID int64) (*user.Subscribe, error) {
|
||||
return nil, nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, decision)
|
||||
require.Equal(t, PurchaseRouteNewPurchase, decision.Route)
|
||||
require.Equal(t, int64(100), decision.ResolvedSubscribeID)
|
||||
})
|
||||
|
||||
t.Run("single mode routed to renewal", func(t *testing.T) {
|
||||
decision, err := ResolvePurchaseRoute(ctx, true, 1, 100, func(ctx context.Context, userID int64) (*user.Subscribe, error) {
|
||||
return &user.Subscribe{
|
||||
Id: 11,
|
||||
SubscribeId: 100,
|
||||
OrderId: 7,
|
||||
Token: "token",
|
||||
}, nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, decision)
|
||||
require.Equal(t, PurchaseRoutePurchaseToRenewal, decision.Route)
|
||||
require.Equal(t, int64(100), decision.ResolvedSubscribeID)
|
||||
require.NotNil(t, decision.Anchor)
|
||||
require.Equal(t, int64(11), decision.Anchor.Id)
|
||||
})
|
||||
|
||||
t.Run("single mode plan mismatch", func(t *testing.T) {
|
||||
decision, err := ResolvePurchaseRoute(ctx, true, 1, 100, func(ctx context.Context, userID int64) (*user.Subscribe, error) {
|
||||
return &user.Subscribe{
|
||||
Id: 11,
|
||||
SubscribeId: 200,
|
||||
}, nil
|
||||
})
|
||||
require.ErrorIs(t, err, ErrSingleModePlanMismatch)
|
||||
require.Nil(t, decision)
|
||||
})
|
||||
|
||||
t.Run("single mode anchor query error", func(t *testing.T) {
|
||||
queryErr := errors.New("query failed")
|
||||
decision, err := ResolvePurchaseRoute(ctx, true, 1, 100, func(ctx context.Context, userID int64) (*user.Subscribe, error) {
|
||||
return nil, queryErr
|
||||
})
|
||||
require.ErrorIs(t, err, queryErr)
|
||||
require.Nil(t, decision)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user