Skip to content

Commit

Permalink
feat: payment_options.name field is unique
Browse files Browse the repository at this point in the history
  • Loading branch information
x1m3 committed Jan 3, 2025
1 parent 2ca6552 commit b8e25ec
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 11 deletions.
2 changes: 2 additions & 0 deletions api/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1897,6 +1897,8 @@ paths:
$ref: '#/components/responses/400'
'401':
$ref: '#/components/responses/401'
'409':
$ref: '#/components/responses/409'
'500':
$ref: '#/components/responses/500'

Expand Down
9 changes: 9 additions & 0 deletions internal/api/api.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions internal/api/payment.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ func (s *Server) CreatePaymentOption(ctx context.Context, request CreatePaymentO
if errors.Is(err, repositories.ErrIdentityNotFound) {
return CreatePaymentOption400JSONResponse{N400JSONResponse{Message: "invalid issuer did"}}, nil
}
if errors.Is(err, repositories.ErrPaymentOptionAlreadyExists) {
return CreatePaymentOption409JSONResponse{N409JSONResponse{Message: "payment option name already exists"}}, nil
}
return CreatePaymentOption500JSONResponse{N500JSONResponse{Message: fmt.Sprintf("can't create payment-option: <%s>", err.Error())}}, nil
}
return CreatePaymentOption201JSONResponse{Id: id.String()}, nil
Expand Down
35 changes: 30 additions & 5 deletions internal/api/payment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,14 @@ func TestServer_CreatePaymentOption(t *testing.T) {

require.NoError(t, json.Unmarshal([]byte(paymentOptionConfigurationTesting), &config))

_, err = server.Services.payments.CreatePaymentOption(
ctx,
issuerDID,
"duplicated name",
"Payment Option explanation",
&domain.PaymentOptionConfig{})
require.NoError(t, err)

type expected struct {
httpCode int
msg string
Expand All @@ -103,7 +111,7 @@ func TestServer_CreatePaymentOption(t *testing.T) {
body: CreatePaymentOptionJSONRequestBody{
PaymentOptions: config,
Description: "Payment Option explanation",
Name: "1 POL Payment",
Name: "3 POL Payment",
},
expected: expected{
httpCode: http.StatusUnauthorized,
Expand All @@ -117,7 +125,7 @@ func TestServer_CreatePaymentOption(t *testing.T) {
body: CreatePaymentOptionJSONRequestBody{
PaymentOptions: config,
Description: "Payment Option explanation",
Name: "1 POL Payment",
Name: "4 POL Payment",
},
expected: expected{
httpCode: http.StatusCreated,
Expand All @@ -130,13 +138,27 @@ func TestServer_CreatePaymentOption(t *testing.T) {
body: CreatePaymentOptionJSONRequestBody{
PaymentOptions: config,
Description: "Payment Option explanation",
Name: "1 POL Payment",
Name: "5 POL Payment",
},
expected: expected{
httpCode: http.StatusBadRequest,
msg: "invalid issuer did",
},
},
{
name: "Duplicated name",
auth: authOk,
issuerDID: *issuerDID,
body: CreatePaymentOptionJSONRequestBody{
PaymentOptions: config,
Description: "Payment Option explanation",
Name: "duplicated name",
},
expected: expected{
httpCode: http.StatusConflict,
msg: "payment option name already exists",
},
},
} {
t.Run(tc.name, func(t *testing.T) {
rr := httptest.NewRecorder()
Expand All @@ -157,7 +179,10 @@ func TestServer_CreatePaymentOption(t *testing.T) {
var response CreatePaymentOption400JSONResponse
require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &response))
assert.Equal(t, tc.expected.msg, response.Message)

case http.StatusConflict:
var response CreatePaymentOption409JSONResponse
require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &response))
assert.Equal(t, tc.expected.msg, response.Message)
}
})
}
Expand Down Expand Up @@ -422,7 +447,7 @@ func TestServer_DeletePaymentOption(t *testing.T) {
otherDID, err := w3c.ParseDID("did:polygonid:polygon:amoy:2qRYvPBNBTkPaHk1mKBkcLTequfAdsHzXv549ktnL5")
require.NoError(t, err)

optionID, err := server.Services.payments.CreatePaymentOption(ctx, issuerDID, "1 POL Payment", "Payment Option explanation", &config)
optionID, err := server.Services.payments.CreatePaymentOption(ctx, issuerDID, "10 POL Payment", "Payment Option explanation", &config)
require.NoError(t, err)
type expected struct {
httpCode int
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
-- +goose Up
-- +goose StatementBegin

-- Update the name column with unique names
WITH duplicates AS (SELECT id, name, ROW_NUMBER() OVER (PARTITION BY name ORDER BY id) AS row_num
FROM payment_options)
UPDATE payment_options
SET name =payment_options.name || '_' || duplicates.row_num - 1
FROM duplicates
WHERE payment_options.id = duplicates.id
AND duplicates.row_num > 1;

ALTER TABLE payment_options
ADD CONSTRAINT payment_options_name_unique UNIQUE (name);
-- +goose StatementEnd

-- +goose Down
-- +goose StatementBegin
ALTER TABLE payment_options
DROP CONSTRAINT payment_options_name_unique;
-- +goose StatementEnd
7 changes: 7 additions & 0 deletions internal/repositories/payment.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ import (
// ErrPaymentOptionDoesNotExists error
var ErrPaymentOptionDoesNotExists = errors.New("payment option not found")

// ErrPaymentOptionAlreadyExists error
var ErrPaymentOptionAlreadyExists = errors.New("payment option already exists")

// ErrPaymentRequestDoesNotExists error
var ErrPaymentRequestDoesNotExists = errors.New("payment request not found")

Expand Down Expand Up @@ -289,6 +292,10 @@ VALUES ($1, $2, $3, $4, $5, $6, $7);
if strings.Contains(err.Error(), "violates foreign key constraint") {
return uuid.Nil, ErrIdentityNotFound
}
if strings.Contains(err.Error(), "violates unique constraint") {
return uuid.Nil, ErrPaymentOptionAlreadyExists
}
return uuid.Nil, err
}
return opt.ID, nil
}
Expand Down
13 changes: 7 additions & 6 deletions internal/repositories/payment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,16 @@ func TestPayment_GetPaymentOptionByID(t *testing.T) {

fixture.CreateIdentity(t, &domain.Identity{Identifier: issuerID.String()})
repo := NewPayment(*storage)
id, err := repo.SavePaymentOption(ctx, domain.NewPaymentOption(*issuerID, "name", "description", &paymentOptionConfig))
paymentOption := domain.NewPaymentOption(*issuerID, "payment option name "+uuid.NewString(), "description", &paymentOptionConfig)
id, err := repo.SavePaymentOption(ctx, paymentOption)
assert.NoError(t, err)
assert.NotEqual(t, uuid.Nil, id)

t.Run("Get payment option", func(t *testing.T) {
opt, err := repo.GetPaymentOptionByID(ctx, issuerID, id)
assert.NoError(t, err)
assert.Equal(t, id, opt.ID)
assert.Equal(t, "name", opt.Name)
assert.Equal(t, paymentOption.Name, opt.Name)
assert.Equal(t, "description", opt.Description)
assert.Equal(t, paymentOptionConfig, opt.Config)
})
Expand All @@ -166,7 +167,7 @@ func TestPayment_DeletePaymentOption(t *testing.T) {

fixture.CreateIdentity(t, &domain.Identity{Identifier: issuerID.String()})
repo := NewPayment(*storage)
id, err := repo.SavePaymentOption(ctx, domain.NewPaymentOption(*issuerID, "name", "description", &domain.PaymentOptionConfig{}))
id, err := repo.SavePaymentOption(ctx, domain.NewPaymentOption(*issuerID, "name"+uuid.NewString(), "description", &domain.PaymentOptionConfig{}))
assert.NoError(t, err)
assert.NotEqual(t, uuid.Nil, id)

Expand All @@ -190,7 +191,7 @@ func TestPayment_SavePaymentRequest(t *testing.T) {
fixture.CreateIdentity(t, &domain.Identity{Identifier: issuerID.String()})
repo := NewPayment(*storage)

payymentOptionID, err := repo.SavePaymentOption(ctx, domain.NewPaymentOption(*issuerID, "name", "description", &domain.PaymentOptionConfig{}))
payymentOptionID, err := repo.SavePaymentOption(ctx, domain.NewPaymentOption(*issuerID, "name"+uuid.NewString(), "description", &domain.PaymentOptionConfig{}))
require.NoError(t, err)

t.Run("Save payment to not existing payment option id", func(t *testing.T) {
Expand Down Expand Up @@ -266,7 +267,7 @@ func TestPayment_GetPaymentRequestByID(t *testing.T) {
require.NoError(t, err)

fixture.CreateIdentity(t, &domain.Identity{Identifier: issuerID.String()})
paymentOptionID, err := repo.SavePaymentOption(ctx, domain.NewPaymentOption(*issuerID, "name", "description", &domain.PaymentOptionConfig{}))
paymentOptionID, err := repo.SavePaymentOption(ctx, domain.NewPaymentOption(*issuerID, "name"+uuid.NewString(), "description", &domain.PaymentOptionConfig{}))
require.NoError(t, err)
expected := fixture.CreatePaymentRequest(t, *issuerID, *issuerID, paymentOptionID, 10)

Expand Down Expand Up @@ -298,7 +299,7 @@ func TestPayment_GetPaymentRequestItem(t *testing.T) {
fixture.CreateIdentity(t, &domain.Identity{Identifier: issuerID.String()})
repo := NewPayment(*storage)

payymentOptionID, err := repo.SavePaymentOption(ctx, domain.NewPaymentOption(*issuerID, "name", "description", &domain.PaymentOptionConfig{}))
payymentOptionID, err := repo.SavePaymentOption(ctx, domain.NewPaymentOption(*issuerID, "name"+uuid.NewString(), "description", &domain.PaymentOptionConfig{}))
require.NoError(t, err)
expected := fixture.CreatePaymentRequest(t, *issuerID, *issuerID, payymentOptionID, 10)

Expand Down

0 comments on commit b8e25ec

Please sign in to comment.