Skip to content

Commit

Permalink
Merge branch 'develop' into feature/MZ-607
Browse files Browse the repository at this point in the history
  • Loading branch information
maxwelbm authored Oct 31, 2024
2 parents 697b036 + ee7909e commit 3be3f6a
Show file tree
Hide file tree
Showing 12 changed files with 263 additions and 33 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
## [1.26.0-beta.10](https://github.com/LerianStudio/midaz/compare/v1.26.0-beta.9...v1.26.0-beta.10) (2024-10-31)


### Features

* add account update endpoint without portfolioId :sparkles: ([3d7ea8f](https://github.com/LerianStudio/midaz/commit/3d7ea8f754faef82d07fdbc519ebe7595fe1ee89))

## [1.26.0-beta.9](https://github.com/LerianStudio/midaz/compare/v1.26.0-beta.8...v1.26.0-beta.9) (2024-10-31)


### Features

* add account creation endpoint with optional portfolioId :sparkles: ([eb51270](https://github.com/LerianStudio/midaz/commit/eb51270a3c36d32975140a0e6df6188080e31fe1))

## [1.26.0-beta.8](https://github.com/LerianStudio/midaz/compare/v1.26.0-beta.7...v1.26.0-beta.8) (2024-10-30)

## [1.26.0-beta.7](https://github.com/LerianStudio/midaz/compare/v1.26.0-beta.6...v1.26.0-beta.7) (2024-10-30)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ func (r *AccountPostgreSQLRepository) ListByAlias(ctx context.Context, organizat
}

// Update an Account entity into Postgresql and returns the Account updated.
func (r *AccountPostgreSQLRepository) Update(ctx context.Context, organizationID, ledgerID, portfolioID, id uuid.UUID, acc *a.Account) (*a.Account, error) {
func (r *AccountPostgreSQLRepository) Update(ctx context.Context, organizationID, ledgerID uuid.UUID, portfolioID *uuid.UUID, id uuid.UUID, acc *a.Account) (*a.Account, error) {
db, err := r.connection.GetDB()
if err != nil {
return nil, err
Expand Down Expand Up @@ -466,15 +466,19 @@ func (r *AccountPostgreSQLRepository) Update(ctx context.Context, organizationID

updates = append(updates, "updated_at = $"+strconv.Itoa(len(args)+1))

args = append(args, record.UpdatedAt, organizationID, ledgerID, portfolioID, id)
args = append(args, record.UpdatedAt, organizationID, ledgerID, id)

query := `UPDATE account SET ` + strings.Join(updates, ", ") +
` WHERE organization_id = $` + strconv.Itoa(len(args)-3) +
` AND ledger_id = $` + strconv.Itoa(len(args)-2) +
` AND portfolio_id = $` + strconv.Itoa(len(args)-1) +
` WHERE organization_id = $` + strconv.Itoa(len(args)-2) +
` AND ledger_id = $` + strconv.Itoa(len(args)-1) +
` AND id = $` + strconv.Itoa(len(args)) +
` AND deleted_at IS NULL`

if portfolioID != nil && *portfolioID != uuid.Nil {
args = append(args, portfolioID)
query += ` AND portfolio_id = $` + strconv.Itoa(len(args))
}

result, err := db.ExecContext(ctx, query, args...)
if err != nil {
var pgErr *pgconn.PgError
Expand Down
14 changes: 9 additions & 5 deletions components/ledger/internal/app/command/create-account.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
)

// CreateAccount creates a new account persists data in the repository.
func (uc *UseCase) CreateAccount(ctx context.Context, organizationID, ledgerID, portfolioID uuid.UUID, cai *a.CreateAccountInput) (*a.Account, error) {
func (uc *UseCase) CreateAccount(ctx context.Context, organizationID, ledgerID uuid.UUID, cai *a.CreateAccountInput) (*a.Account, error) {
logger := mlog.NewLoggerFromContext(ctx)
logger.Infof("Trying to create account: %v", cai)

Expand All @@ -41,8 +41,12 @@ func (uc *UseCase) CreateAccount(ctx context.Context, organizationID, ledgerID,
return nil, common.ValidateBusinessError(cn.ErrAssetCodeNotFound, reflect.TypeOf(a.Account{}).Name())
}

if cai.EntityID == nil {
portfolio, err := uc.PortfolioRepo.Find(ctx, organizationID, ledgerID, portfolioID)
var portfolioUUID uuid.UUID

if common.IsNilOrEmpty(cai.EntityID) && !common.IsNilOrEmpty(cai.PortfolioID) {
portfolioUUID = uuid.MustParse(*cai.PortfolioID)

portfolio, err := uc.PortfolioRepo.Find(ctx, organizationID, ledgerID, portfolioUUID)
if err != nil {
logger.Errorf("Error find portfolio to get Entity ID: %v", err)
return nil, err
Expand All @@ -52,7 +56,7 @@ func (uc *UseCase) CreateAccount(ctx context.Context, organizationID, ledgerID,
}

if !common.IsNilOrEmpty(cai.ParentAccountID) {
acc, err := uc.AccountRepo.Find(ctx, organizationID, ledgerID, &portfolioID, uuid.MustParse(*cai.ParentAccountID))
acc, err := uc.AccountRepo.Find(ctx, organizationID, ledgerID, &portfolioUUID, uuid.MustParse(*cai.ParentAccountID))
if err != nil {
return nil, common.ValidateBusinessError(cn.ErrInvalidParentAccountID, reflect.TypeOf(a.Account{}).Name())
}
Expand All @@ -78,7 +82,7 @@ func (uc *UseCase) CreateAccount(ctx context.Context, organizationID, ledgerID,
ParentAccountID: cai.ParentAccountID,
ProductID: cai.ProductID,
OrganizationID: organizationID.String(),
PortfolioID: mpointers.String(portfolioID.String()),
PortfolioID: cai.PortfolioID,
LedgerID: ledgerID.String(),
EntityID: cai.EntityID,
Balance: balance,
Expand Down
23 changes: 23 additions & 0 deletions components/ledger/internal/app/command/create-account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,29 @@ func TestCreateAccountSuccess(t *testing.T) {
assert.Nil(t, err)
}

// TestCreateWithoutPortfolioAccountSuccess is responsible to test CreateAccountWithoutPortfolio with success
func TestCreateWithoutPortfolioAccountSuccess(t *testing.T) {
account := &a.Account{
ID: common.GenerateUUIDv7().String(),
OrganizationID: common.GenerateUUIDv7().String(),
LedgerID: common.GenerateUUIDv7().String(),
}

uc := UseCase{
AccountRepo: mock.NewMockRepository(gomock.NewController(t)),
}

uc.AccountRepo.(*mock.MockRepository).
EXPECT().
Create(gomock.Any(), account).
Return(account, nil).
Times(1)
res, err := uc.AccountRepo.Create(context.TODO(), account)

assert.Equal(t, account, res)
assert.Nil(t, err)
}

// TestCreateAccountError is responsible to test CreateAccount with error
func TestCreateAccountError(t *testing.T) {
errMSG := "err to create account on database"
Expand Down
2 changes: 1 addition & 1 deletion components/ledger/internal/app/command/update-account.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
)

// UpdateAccount update an account from the repository by given id.
func (uc *UseCase) UpdateAccount(ctx context.Context, organizationID, ledgerID, portfolioID, id uuid.UUID, uai *a.UpdateAccountInput) (*a.Account, error) {
func (uc *UseCase) UpdateAccount(ctx context.Context, organizationID, ledgerID uuid.UUID, portfolioID *uuid.UUID, id uuid.UUID, uai *a.UpdateAccountInput) (*a.Account, error) {
logger := mlog.NewLoggerFromContext(ctx)
logger.Infof("Trying to update account: %v", uai)

Expand Down
33 changes: 29 additions & 4 deletions components/ledger/internal/app/command/update-account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,35 @@ func TestUpdateAccountByIDSuccess(t *testing.T) {

uc.AccountRepo.(*mock.MockRepository).
EXPECT().
Update(gomock.Any(), organizationID, ledgerID, portfolioID, id, account).
Update(gomock.Any(), organizationID, ledgerID, &portfolioID, id, account).
Return(account, nil).
Times(1)
res, err := uc.AccountRepo.Update(context.TODO(), organizationID, ledgerID, portfolioID, id, account)
res, err := uc.AccountRepo.Update(context.TODO(), organizationID, ledgerID, &portfolioID, id, account)

assert.Equal(t, account, res)
assert.Nil(t, err)
}

// TestUpdateAccountByIDWithoutPortfolioSuccess is responsible to test UpdateAccountByIDWithoutPortfolio with success
func TestUpdateAccountByIDWithoutPortfolioSuccess(t *testing.T) {
organizationID := common.GenerateUUIDv7()
ledgerID := common.GenerateUUIDv7()
id := common.GenerateUUIDv7()
account := &a.Account{
ID: id.String(),
UpdatedAt: time.Now(),
}

uc := UseCase{
AccountRepo: mock.NewMockRepository(gomock.NewController(t)),
}

uc.AccountRepo.(*mock.MockRepository).
EXPECT().
Update(gomock.Any(), organizationID, ledgerID, nil, id, account).
Return(account, nil).
Times(1)
res, err := uc.AccountRepo.Update(context.TODO(), organizationID, ledgerID, nil, id, account)

assert.Equal(t, account, res)
assert.Nil(t, err)
Expand All @@ -57,9 +82,9 @@ func TestUpdateAccountByIDError(t *testing.T) {

uc.AccountRepo.(*mock.MockRepository).
EXPECT().
Update(gomock.Any(), organizationID, ledgerID, portfolioID, id, account).
Update(gomock.Any(), organizationID, ledgerID, &portfolioID, id, account).
Return(nil, errors.New(errMSG))
res, err := uc.AccountRepo.Update(context.TODO(), organizationID, ledgerID, portfolioID, id, account)
res, err := uc.AccountRepo.Update(context.TODO(), organizationID, ledgerID, &portfolioID, id, account)

assert.NotEmpty(t, err)
assert.Equal(t, err.Error(), errMSG)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type CreateAccountInput struct {
Type string `json:"type" validate:"required"`
ParentAccountID *string `json:"parentAccountId" validate:"omitempty,uuid"`
ProductID *string `json:"productId" validate:"omitempty,uuid"`
PortfolioID *string `json:"portfolioId" validate:"omitempty,uuid"`
EntityID *string `json:"entityId" validate:"omitempty,max=256"`
Status Status `json:"status"`
Metadata map[string]any `json:"metadata" validate:"dive,keys,keymax=100,endkeys,nonested,valuemax=2000"`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type Repository interface {
FindByAlias(ctx context.Context, organizationID, ledgerID uuid.UUID, alias string) (bool, error)
ListByIDs(ctx context.Context, organizationID, ledgerID uuid.UUID, portfolioID *uuid.UUID, ids []uuid.UUID) ([]*Account, error)
ListByAlias(ctx context.Context, organizationID, ledgerID, portfolioID uuid.UUID, alias []string) ([]*Account, error)
Update(ctx context.Context, organizationID, ledgerID, portfolioID, id uuid.UUID, acc *Account) (*Account, error)
Update(ctx context.Context, organizationID, ledgerID uuid.UUID, portfolioID *uuid.UUID, id uuid.UUID, acc *Account) (*Account, error)
Delete(ctx context.Context, organizationID, ledgerID uuid.UUID, portfolioID *uuid.UUID, id uuid.UUID) error
ListAccountsByIDs(ctx context.Context, organizationID, ledgerID uuid.UUID, ids []uuid.UUID) ([]*Account, error)
ListAccountsByAlias(ctx context.Context, organizationID, ledgerID uuid.UUID, aliases []string) ([]*Account, error)
Expand Down

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

69 changes: 66 additions & 3 deletions components/ledger/internal/ports/http/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,46 @@ func (handler *AccountHandler) CreateAccount(i any, c *fiber.Ctx) error {
ctx := c.UserContext()
logger := mlog.NewLoggerFromContext(ctx)

organizationID := c.Locals("organization_id").(uuid.UUID)
ledgerID := c.Locals("ledger_id").(uuid.UUID)

payload := i.(*a.CreateAccountInput)
logger.Infof("Request to create a Account with details: %#v", payload)

if !common.IsNilOrEmpty(payload.PortfolioID) {
logger.Infof("Initiating create of Account with Portfolio ID: %s", *payload.PortfolioID)
}

account, err := handler.Command.CreateAccount(ctx, organizationID, ledgerID, payload)
if err != nil {
return commonHTTP.WithError(c, err)
}

logger.Infof("Successfully created Account")

return commonHTTP.Created(c, account)
}

// CreateAccountFromPortfolio is a method that creates account information from a given portfolio id.
//
// Will be deprecated in the future. Use CreateAccount instead.
func (handler *AccountHandler) CreateAccountFromPortfolio(i any, c *fiber.Ctx) error {
ctx := c.UserContext()
logger := mlog.NewLoggerFromContext(ctx)

organizationID := c.Locals("organization_id").(uuid.UUID)
ledgerID := c.Locals("ledger_id").(uuid.UUID)
portfolioID := c.Locals("portfolio_id").(uuid.UUID)
portfolioIDStr := portfolioID.String()

logger.Infof("Initiating create of Account with Portfolio ID: %s", portfolioID.String())
logger.Infof("Initiating create of Account with Portfolio ID: %s", portfolioIDStr)

payload := i.(*a.CreateAccountInput)
payload.PortfolioID = &portfolioIDStr

logger.Infof("Request to create a Account with details: %#v", payload)

account, err := handler.Command.CreateAccount(ctx, organizationID, ledgerID, portfolioID, payload)
account, err := handler.Command.CreateAccount(ctx, organizationID, ledgerID, payload)
if err != nil {
return commonHTTP.WithError(c, err)
}
Expand Down Expand Up @@ -206,6 +236,39 @@ func (handler *AccountHandler) UpdateAccount(i any, c *fiber.Ctx) error {
ctx := c.UserContext()
logger := mlog.NewLoggerFromContext(ctx)

organizationID := c.Locals("organization_id").(uuid.UUID)
ledgerID := c.Locals("ledger_id").(uuid.UUID)
id := c.Locals("id").(uuid.UUID)

logger.Infof("Initiating update of Account with ID: %s", id.String())

payload := i.(*a.UpdateAccountInput)
logger.Infof("Request to update an Account with details: %#v", payload)

_, err := handler.Command.UpdateAccount(ctx, organizationID, ledgerID, nil, id, payload)
if err != nil {
logger.Errorf("Failed to update Account with ID: %s, Error: %s", id.String(), err.Error())
return commonHTTP.WithError(c, err)
}

account, err := handler.Query.GetAccountByID(c.Context(), organizationID, ledgerID, nil, id)
if err != nil {
logger.Errorf("Failed to retrieve Account with ID: %s, Error: %s", id, err.Error())
return commonHTTP.WithError(c, err)
}

logger.Infof("Successfully updated Account with ID: %s", id.String())

return commonHTTP.OK(c, account)
}

// UpdateAccountFromPortfolio is a method that updates Account information from a given portfolio id and account id.
//
// Will be deprecated in the future. Use UpdateAccount instead.
func (handler *AccountHandler) UpdateAccountFromPortfolio(i any, c *fiber.Ctx) error {
ctx := c.UserContext()
logger := mlog.NewLoggerFromContext(ctx)

organizationID := c.Locals("organization_id").(uuid.UUID)
ledgerID := c.Locals("ledger_id").(uuid.UUID)
portfolioID := c.Locals("portfolio_id").(uuid.UUID)
Expand All @@ -216,7 +279,7 @@ func (handler *AccountHandler) UpdateAccount(i any, c *fiber.Ctx) error {
payload := i.(*a.UpdateAccountInput)
logger.Infof("Request to update an Account with details: %#v", payload)

_, err := handler.Command.UpdateAccount(ctx, organizationID, ledgerID, portfolioID, id, payload)
_, err := handler.Command.UpdateAccount(ctx, organizationID, ledgerID, &portfolioID, id, payload)
if err != nil {
logger.Errorf("Failed to update Account with ID: %s, Error: %s", id.String(), err.Error())
return commonHTTP.WithError(c, err)
Expand Down
10 changes: 7 additions & 3 deletions components/ledger/internal/ports/http/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,19 @@ func NewRouter(lg mlog.Logger, cc *mcasdoor.CasdoorConnection, ah *AccountHandle
f.Delete("/v1/organizations/:organization_id/ledgers/:ledger_id/products/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("product"), lib.ParseUUIDPathParameters, rh.DeleteProductByID)

// Accounts
f.Post("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios/:portfolio_id/accounts", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("account"), lib.ParseUUIDPathParameters, lib.WithBody(new(a.CreateAccountInput), ah.CreateAccount))
f.Patch("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios/:portfolio_id/accounts/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("account"), lib.ParseUUIDPathParameters, lib.WithBody(new(a.UpdateAccountInput), ah.UpdateAccount))
f.Post("/v1/organizations/:organization_id/ledgers/:ledger_id/accounts", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("account"), lib.ParseUUIDPathParameters, lib.WithBody(new(a.CreateAccountInput), ah.CreateAccount))
f.Patch("/v1/organizations/:organization_id/ledgers/:ledger_id/accounts/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("account"), lib.ParseUUIDPathParameters, lib.WithBody(new(a.UpdateAccountInput), ah.UpdateAccount))
f.Get("/v1/organizations/:organization_id/ledgers/:ledger_id/accounts", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("account"), lib.ParseUUIDPathParameters, ah.GetAllAccounts)
f.Get("/v1/organizations/:organization_id/ledgers/:ledger_id/accounts/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("account"), lib.ParseUUIDPathParameters, ah.GetAccountByID)
f.Delete("/v1/organizations/:organization_id/ledgers/:ledger_id/accounts/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("account"), lib.ParseUUIDPathParameters, ah.DeleteAccountByID)
// Will be deprecated in the future. Use "POST /v1/organizations/:organization_id/ledgers/:ledger_id/accounts" instead.
f.Post("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios/:portfolio_id/accounts", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("account"), lib.ParseUUIDPathParameters, lib.WithBody(new(a.CreateAccountInput), ah.CreateAccountFromPortfolio))
// Will be deprecated in the future. Use "PATCH /v1/organizations/:organization_id/ledgers/:ledger_id/accounts/:id" instead.
f.Patch("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios/:portfolio_id/accounts/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("account"), lib.ParseUUIDPathParameters, lib.WithBody(new(a.UpdateAccountInput), ah.UpdateAccountFromPortfolio))
// Will be deprecated in the future. Use "GET /v1/organizations/:organization_id/ledgers/:ledger_id/accounts" instead.
f.Get("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios/:portfolio_id/accounts", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("account"), lib.ParseUUIDPathParameters, ah.GetAllAccountsByIDFromPortfolio)
// Will be deprecated in the future. Use "GET /v1/organizations/:organization_id/ledgers/:ledger_id/accounts/:id" instead.
f.Get("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios/:portfolio_id/accounts/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("account"), lib.ParseUUIDPathParameters, ah.GetAccountByIDFromPortfolio)
f.Delete("/v1/organizations/:organization_id/ledgers/:ledger_id/accounts/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("account"), lib.ParseUUIDPathParameters, ah.DeleteAccountByID)
// Will be deprecated in the future. Use "DELETE /v1/organizations/:organization_id/ledgers/:ledger_id/accounts/:id" instead.
f.Delete("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios/:portfolio_id/accounts/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("account"), lib.ParseUUIDPathParameters, ah.DeleteAccountByIDFromPortfolio)

Expand Down
Loading

0 comments on commit 3be3f6a

Please sign in to comment.