Skip to content

[feature] update user endpoint #2

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

Merged
merged 1 commit into from
Sep 24, 2023
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
62 changes: 61 additions & 1 deletion internal/users/delivery/http/handler/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package handler
import (
"context"
"net/http"
"strconv"
"time"

"github.com/DoWithLogic/golang-clean-architecture/internal/users/dtos"
Expand Down Expand Up @@ -71,5 +72,64 @@ func (h *handlers) CreateUser(c echo.Context) error {
}

func (h *handlers) UpdateUser(c echo.Context) error {
return nil
var (
ctx, cancel = context.WithTimeout(c.Request().Context(), time.Duration(30*time.Second))
payload dtos.UpdateUserPayload
)
defer cancel()

h.log.Z().Info().Msg("[handlers]UpdateUser")

userID, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
h.log.Z().Err(err).Msg("[handlers]UpdateUser.ParseParam")

return c.JSON(http.StatusBadRequest, dtos.NewResponseError(
http.StatusBadRequest,
dtos.MsgFailed,
dtos.Text(http.StatusBadRequest),
err.Error()),
)
}

if err := c.Bind(&payload); err != nil {
h.log.Z().Err(err).Msg("[handlers]UpdateUser.Bind")

return c.JSON(http.StatusBadRequest, dtos.NewResponseError(
http.StatusBadRequest,
dtos.MsgFailed,
dtos.Text(http.StatusBadRequest),
err.Error()),
)
}

if err := payload.Validate(); err != nil {
h.log.Z().Err(err).Msg("[handlers]UpdateUser.Validate")

return c.JSON(http.StatusBadRequest, dtos.NewResponseError(
http.StatusBadRequest,
dtos.MsgFailed,
dtos.Text(http.StatusBadRequest),
err.Error()),
)
}

updateArgs := &entities.UpdateUsers{
UserID: userID,
Fullname: payload.Fullname,
PhoneNumber: payload.Fullname,
UserType: payload.UserType,
}

err = h.uc.UpdateUser(ctx, updateArgs)
if err != nil {
return c.JSON(http.StatusBadRequest, dtos.NewResponseError(
http.StatusInternalServerError,
dtos.MsgFailed,
dtos.Text(http.StatusInternalServerError),
err.Error()),
)
}

return c.JSON(http.StatusOK, dtos.NewResponse(http.StatusOK, dtos.MsgSuccess, nil))
}
1 change: 1 addition & 0 deletions internal/users/delivery/http/route/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ import (
func RouteUsers(version *echo.Group, ctrl handler.Handlers) {
users := version.Group("users")
users.POST("", ctrl.CreateUser)
users.PATCH("/:id", ctrl.UpdateUser)
}
32 changes: 32 additions & 0 deletions internal/users/dtos/update_users.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package dtos

import (
"errors"

"github.com/DoWithLogic/golang-clean-architecture/internal/users/entities"
"github.com/invopop/validation"
)

type UpdateUserPayload struct {
Fullname string `json:"fullname"`
PhoneNumber string `json:"phone_number"`
UserType string `json:"user_type"`
}

func (cup UpdateUserPayload) Validate() error {
var validationFields []*validation.FieldRules

if cup.UserType != "" && (cup.UserType != entities.UserTypePremium && cup.UserType != entities.UserTypeRegular) {
return errors.New("invalid user_type")
}

if cup.Fullname != "" {
validationFields = append(validationFields, validation.Field(&cup.Fullname, validation.Required, validation.Length(0, 50)))
}

if cup.PhoneNumber != "" {
validationFields = append(validationFields, validation.Field(&cup.PhoneNumber, validation.Required, validation.Length(0, 13)))
}

return validation.ValidateStruct(&cup, validationFields...)
}
3 changes: 1 addition & 2 deletions internal/users/entities/update_users.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,16 @@ type UpdateUsers struct {
Fullname string
PhoneNumber string
UserType string
IsActive bool
UpdatedAt string
UpdatedBy string
}

func NewUpdateUsers(data UpdateUsers) *UpdateUsers {
return &UpdateUsers{
UserID: data.UserID,
Fullname: data.Fullname,
PhoneNumber: data.PhoneNumber,
UserType: UserTypeRegular,
IsActive: true,
UpdatedAt: time.Now().Format("2006-01-02 15:04:05"),
UpdatedBy: "martin",
}
Expand Down
25 changes: 12 additions & 13 deletions internal/users/repository/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type (
Repository interface {
SaveNewUser(context.Context, *entities.Users) (int64, error)
UpdateUserByID(context.Context, *entities.UpdateUsers) error
GetUserByID(context.Context, int64, entities.LockingOpt) (*entities.Users, error)
GetUserByID(context.Context, int64, entities.LockingOpt) (entities.Users, error)
}

repository struct {
Expand Down Expand Up @@ -50,16 +50,15 @@ func (repo *repository) SaveNewUser(ctx context.Context, user *entities.Users) (

func (repo *repository) UpdateUserByID(ctx context.Context, user *entities.UpdateUsers) error {
args := custom.Array{
user.UserID,
user.Fullname,
user.PhoneNumber,
user.UserType,
user.IsActive,
user.Fullname, user.Fullname,
user.PhoneNumber, user.PhoneNumber,
user.UserType, user.UserType,
user.UpdatedAt,
user.UpdatedBy,
user.UserID,
}

err := new(database.SQL).Exec(repo.conn.ExecContext(ctx, repository_query.InsertUsers, args...)).Scan(nil, nil)
err := new(database.SQL).Exec(repo.conn.ExecContext(ctx, repository_query.UpdateUsers, args...)).Scan(nil, nil)
if err != nil {
repo.log.Z().Err(err).Msg("[repository]UpdateUserByID.ExecContext")

Expand All @@ -69,9 +68,9 @@ func (repo *repository) UpdateUserByID(ctx context.Context, user *entities.Updat
return nil
}

func (repo *repository) GetUserByID(ctx context.Context, userID int64, lockOpt entities.LockingOpt) (userData *entities.Users, err error) {
func (repo *repository) GetUserByID(ctx context.Context, userID int64, lockOpt entities.LockingOpt) (userData entities.Users, err error) {
if err := lockOpt.Validate(); err != nil {
return nil, err
return userData, err
}

args := custom.Array{
Expand All @@ -85,22 +84,22 @@ func (repo *repository) GetUserByID(ctx context.Context, userID int64, lockOpt e
&userData.PhoneNumber,
&userData.UserType,
&userData.IsActive,
userData.CreatedAt,
&userData.CreatedAt,
}

}

query := repository_query.GetUserByID

if lockOpt.ForUpdate {
query += "FOR UPDATE;"
query += " FOR UPDATE;"
} else if lockOpt.ForUpdateNoWait {
query += "FOR UPDATE NO WAIT;"
query += " FOR UPDATE NO WAIT;"
}

if err = new(database.SQL).Query(repo.conn.QueryContext(ctx, query, args...)).Scan(row); err != nil {
repo.log.Z().Err(err).Msg("[repository]GetUserByID.QueryContext")
return nil, err
return userData, err
}

return userData, err
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ SELECT
u.is_active,
u.created_at
FROM users u
WHERE u.id = $1
WHERE u.id = ?
11 changes: 5 additions & 6 deletions internal/users/repository/repository_query/users/update.sql
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
UPDATE users SET
fullname = CASE WHEN $2 != '' THEN $2 ELSE fullname END,
phone_number = CASE WHEN $3 != '' THEN $3 ELSE phone_number END,
user_type = CASE WHEN $4 != '' THEN $4 ELSE user_type END,
is_active = CASE WHEN $5 IS NULL THEN $5 ELSE user_type END,
fullname = CASE WHEN ? != '' THEN ? ELSE fullname END,
phone_number = CASE WHEN ? != '' THEN ? ELSE phone_number END,
user_type = CASE WHEN ? != '' THEN ? ELSE user_type END,
updated_at = ?,
created_by = ?
WHERE id = $1
updated_by = ?
WHERE id = ?