Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/MIDAZ-349 #355

Merged
merged 4 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 32 additions & 32 deletions components/ledger/internal/adapters/postgres/asset/asset.mock.go

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

Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (
//go:generate mockgen --destination=asset.mock.go --package=asset . Repository
type Repository interface {
Create(ctx context.Context, asset *mmodel.Asset) (*mmodel.Asset, error)
FindAll(ctx context.Context, organizationID, ledgerID uuid.UUID, limit, page int) ([]*mmodel.Asset, error)
FindAllWithDeleted(ctx context.Context, organizationID, ledgerID uuid.UUID, limit, page int) ([]*mmodel.Asset, error)
ListByIDs(ctx context.Context, organizationID, ledgerID uuid.UUID, ids []uuid.UUID) ([]*mmodel.Asset, error)
Find(ctx context.Context, organizationID, ledgerID, id uuid.UUID) (*mmodel.Asset, error)
FindByNameOrCode(ctx context.Context, organizationID, ledgerID uuid.UUID, name, code string) (bool, error)
Expand Down Expand Up @@ -164,8 +164,8 @@ func (r *AssetPostgreSQLRepository) FindByNameOrCode(ctx context.Context, organi
return false, nil
}

// FindAll retrieves Asset entities from the database.
func (r *AssetPostgreSQLRepository) FindAll(ctx context.Context, organizationID, ledgerID uuid.UUID, limit, page int) ([]*mmodel.Asset, error) {
// FindAllWithDeleted retrieves Asset entities from the database with soft-deleted records.
func (r *AssetPostgreSQLRepository) FindAllWithDeleted(ctx context.Context, organizationID, ledgerID uuid.UUID, limit, page int) ([]*mmodel.Asset, error) {
tracer := pkg.NewTracerFromContext(ctx)

ctx, span := tracer.Start(ctx, "postgres.find_all_assets")
Expand All @@ -184,7 +184,6 @@ func (r *AssetPostgreSQLRepository) FindAll(ctx context.Context, organizationID,
From(r.tableName).
Where(squirrel.Expr("organization_id = ?", organizationID)).
Where(squirrel.Expr("ledger_id = ?", ledgerID)).
Where(squirrel.Eq{"deleted_at": nil}).
OrderBy("created_at DESC").
Limit(pkg.SafeIntToUint64(limit)).
Offset(pkg.SafeIntToUint64((page - 1) * limit)).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package command

import (
"context"
"github.com/LerianStudio/midaz/pkg/constant"
"reflect"
"time"

Expand Down Expand Up @@ -94,7 +95,7 @@ func (uc *UseCase) CreateAsset(ctx context.Context, organizationID, ledgerID uui

inst.Metadata = metadata

aAlias := "@external/" + cii.Code
aAlias := constant.DefaultExternalAccountAliasPrefix + cii.Code
aStatusDescription := "Account external created by asset: " + cii.Code

account, err := uc.AccountRepo.ListAccountsByAlias(ctx, organizationID, ledgerID, []string{aAlias})
Expand Down
35 changes: 35 additions & 0 deletions components/ledger/internal/services/command/delete-asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,41 @@ func (uc *UseCase) DeleteAssetByID(ctx context.Context, organizationID, ledgerID

logger.Infof("Remove asset for id: %s", id)

asset, err := uc.AssetRepo.Find(ctx, organizationID, ledgerID, id)
if err != nil {
mopentelemetry.HandleSpanError(&span, "Failed to get asset on repo by id", err)

logger.Errorf("Error getting asset on repo by id: %v", err)

if errors.Is(err, services.ErrDatabaseItemNotFound) {
return pkg.ValidateBusinessError(constant.ErrAssetIDNotFound, reflect.TypeOf(mmodel.Asset{}).Name(), id)
}

return err
}

aAlias := constant.DefaultExternalAccountAliasPrefix + asset.Code

acc, err := uc.AccountRepo.ListAccountsByAlias(ctx, organizationID, ledgerID, []string{aAlias})
if err != nil {
mopentelemetry.HandleSpanError(&span, "Failed to retrieve asset external account", err)

logger.Errorf("Error retrieving asset external account: %v", err)

return err
}

if len(acc) > 0 {
err := uc.AccountRepo.Delete(ctx, organizationID, ledgerID, nil, uuid.MustParse(acc[0].ID))
if err != nil {
mopentelemetry.HandleSpanError(&span, "Failed to delete asset external account", err)

logger.Errorf("Error deleting asset external account: %v", err)

return err
}
}

if err := uc.AssetRepo.Delete(ctx, organizationID, ledgerID, id); err != nil {
mopentelemetry.HandleSpanError(&span, "Failed to delete asset on repo by id", err)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func (uc *UseCase) GetAllAssets(ctx context.Context, organizationID, ledgerID uu

logger.Infof("Retrieving assets")

assets, err := uc.AssetRepo.FindAll(ctx, organizationID, ledgerID, filter.Limit, filter.Page)
assets, err := uc.AssetRepo.FindAllWithDeleted(ctx, organizationID, ledgerID, filter.Limit, filter.Page)
if err != nil {
mopentelemetry.HandleSpanError(&span, "Failed to get assets on repo", err)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ func TestGetAllAssets(t *testing.T) {
assets := []*mmodel.Asset{{}}
mockAssetRepo.
EXPECT().
FindAll(gomock.Any(), organizationID, ledgerID, page, limit).
FindAllWithDeleted(gomock.Any(), organizationID, ledgerID, page, limit).
Return(assets, nil).
Times(1)
res, err := uc.AssetRepo.FindAll(context.TODO(), organizationID, ledgerID, page, limit)
res, err := uc.AssetRepo.FindAllWithDeleted(context.TODO(), organizationID, ledgerID, page, limit)

assert.NoError(t, err)
assert.Len(t, res, 1)
Expand All @@ -46,10 +46,10 @@ func TestGetAllAssets(t *testing.T) {
errMsg := "errDatabaseItemNotFound"
mockAssetRepo.
EXPECT().
FindAll(gomock.Any(), organizationID, ledgerID, page, limit).
FindAllWithDeleted(gomock.Any(), organizationID, ledgerID, page, limit).
Return(nil, errors.New(errMsg)).
Times(1)
res, err := uc.AssetRepo.FindAll(context.TODO(), organizationID, ledgerID, page, limit)
res, err := uc.AssetRepo.FindAllWithDeleted(context.TODO(), organizationID, ledgerID, page, limit)

assert.EqualError(t, err, errMsg)
assert.Nil(t, res)
Expand Down
5 changes: 5 additions & 0 deletions pkg/constant/account.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package constant

const (
DefaultExternalAccountAliasPrefix = "@external/"
)
4 changes: 2 additions & 2 deletions pkg/mmodel/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
type CreateAccountInput struct {
AssetCode string `json:"assetCode" validate:"required,max=100" example:"BRL"`
Name string `json:"name" validate:"max=256" example:"My Account"`
Alias *string `json:"alias" validate:"max=100,excludes=@external/" example:"@person1"`
Alias *string `json:"alias" validate:"max=100,prohibitedexternalaccountprefix" example:"@person1"`
Type string `json:"type" validate:"required" example:"creditCard"`
ParentAccountID *string `json:"parentAccountId" validate:"omitempty,uuid" example:"00000000-0000-0000-0000-000000000000"`
ProductID *string `json:"productId" validate:"omitempty,uuid" example:"00000000-0000-0000-0000-000000000000"`
Expand All @@ -34,7 +34,7 @@ type UpdateAccountInput struct {
Status Status `json:"status"`
AllowSending *bool `json:"allowSending" example:"true"`
AllowReceiving *bool `json:"allowReceiving" example:"true"`
Alias *string `json:"alias" validate:"max=100,excludes=@external/" example:"@person1"`
Alias *string `json:"alias" validate:"max=100,prohibitedexternalaccountprefix" example:"@person1"`
ProductID *string `json:"productId" validate:"uuid" example:"00000000-0000-0000-0000-000000000000"`
Metadata map[string]any `json:"metadata" validate:"dive,keys,keymax=100,endkeys,nonested,valuemax=2000"`
} // @name UpdateAccountInput
Expand Down
17 changes: 17 additions & 0 deletions pkg/net/http/withBody.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ func newValidator() (*validator.Validate, ut.Translator) {
_ = v.RegisterValidation("nonested", validateMetadataNestedValues)
_ = v.RegisterValidation("valuemax", validateMetadataValueMaxLength)
_ = v.RegisterValidation("singletransactiontype", validateSingleTransactionType)
_ = v.RegisterValidation("prohibitedexternalaccountprefix", validateProhibitedExternalAccountPrefix)

_ = v.RegisterTranslation("required", trans, func(ut ut.Translator) error {
return ut.Add("required", "{0} is a required field", true)
Expand Down Expand Up @@ -271,6 +272,15 @@ func newValidator() (*validator.Validate, ut.Translator) {
return t
})

_ = v.RegisterTranslation("prohibitedexternalaccountprefix", trans, func(ut ut.Translator) error {
prefix := cn.DefaultExternalAccountAliasPrefix
return ut.Add("prohibitedexternalaccountprefix", "{0} cannot contain the text '"+prefix+"'", true)
}, func(ut ut.Translator, fe validator.FieldError) string {
t, _ := ut.T("prohibitedexternalaccountprefix", formatErrorFieldName(fe.Namespace()))

return t
})

return v, trans
}

Expand Down Expand Up @@ -349,6 +359,13 @@ func validateSingleTransactionType(fl validator.FieldLevel) bool {
return true
}

// validateProhibitedExternalAccountPrefix
func validateProhibitedExternalAccountPrefix(fl validator.FieldLevel) bool {
f := fl.Field().Interface().(string)

return !strings.Contains(f, cn.DefaultExternalAccountAliasPrefix)
}

// formatErrorFieldName formats metadata field error names for error messages
func formatErrorFieldName(text string) string {
re, _ := regexp.Compile(`\.(.+)$`)
Expand Down
Loading