Skip to content

Commit

Permalink
Merge branch 'develop' of github.com:go-park-mail-ru/2023_2_Hamster i…
Browse files Browse the repository at this point in the history
…nto deploy
  • Loading branch information
CodeMaster482 committed Dec 1, 2023
2 parents 1fa88e9 + c3932c3 commit cf9cc9d
Show file tree
Hide file tree
Showing 11 changed files with 412 additions and 27 deletions.
27 changes: 27 additions & 0 deletions build/schema/initdb.sql
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,33 @@ CREATE TABLE IF NOT EXISTS TransactionCategory (
PRIMARY KEY (transaction_id, category_id)
);

CREATE TABLE IF NOT EXISTS goal (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
user_id UUID REFERENCES "user"(user_id) NOT NULL,
"name" TEXT CHECK(LENGTH("name") <= 50) NOT NULL,
"description" TEXT DEFAULT '' CHECK(LENGTH("description") <= 255),
"target" NUMERIC(10,2) NOT NULL,
"date" DATE,
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP NOT NULL,
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP NOT NULL,
);

--========================================================================

CREATE OR REPLACE FUNCTION public.moddatetime()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE OR REPLACE TRIGGER modify_updated_at
BEFORE UPDATE
ON goal
FOR EACH ROW
EXECUTE PROCEDURE public.moddatetime(updated_at);

--========================================================================

CREATE OR REPLACE FUNCTION add_default_categories_accounts_transactions()
Expand Down
6 changes: 6 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ services:
- hammy-postgres
container_name: ${AUTH_CONTAINER}
image: ${REGISTRY}/${AUTH_CONTAINER}:${GITHUB_SHA_SHORT}
#container_name: hammywallet-auth
#image: codemaster482/hammywallet-auth:latest
#build:
# context: .
# dockerfile: build/auth.Dockerfile
Expand All @@ -88,6 +90,8 @@ services:
- hammy-postgres
container_name: ${ACCOUNT_CONTAINER}
image: ${REGISTRY}/${ACCOUNT_CONTAINER}:${GITHUB_SHA_SHORT}
#container_name: hammywallet-account
#image: codemaster482/hammywallet-account:latest
#build:
# context: .
# dockerfile: build/account.Dockerfile
Expand All @@ -104,6 +108,8 @@ services:
- hammy-postgres
container_name: ${CATEGORY_CONTAINER}
image: ${REGISTRY}/${CATEGORY_CONTAINER}:${GITHUB_SHA_SHORT}
#container_name: hammywallet-category
#image: codemaster482/hammywallet-category:latest
#build:
# context: .
# dockerfile: build/category.Dockerfile
Expand Down
16 changes: 11 additions & 5 deletions internal/microservices/auth/delivery/http/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,16 @@ func NewHandler(
// @Description Create Account
// @Accept json
// @Produce json
// @Param user body models.User true "user info"
// @Success 201 {object} Response[auth.SignResponse] "User Created"
// @Failure 400 {object} ResponseError "Incorrect Input"
// @Failure 429 {object} ResponseError "Server error"
// @Param user body models.User true "user info"
// @Success 201 {object} Response[auth.SignResponse] "User Created"
// @Failure 400 {object} ResponseError "Incorrect Input"
// @Failure 409 {object} ResponseError "User already exists"
// @Failure 429 {object} ResponseError "Server error"
// @Router /api/auth/signup [post]
func (h *Handler) SignUp(w http.ResponseWriter, r *http.Request) {
var signUpUser auth.SignUpInput

// Unmarshal r.Body
// Unmarshal request.Body
decoder := json.NewDecoder(r.Body)
if err := decoder.Decode(&signUpUser); err != nil {
h.log.WithField(
Expand All @@ -76,6 +77,11 @@ func (h *Handler) SignUp(w http.ResponseWriter, r *http.Request) {
Password: signUpUser.PlaintPassword,
})
if err != nil {
//var errUserAlreadyExists *models.UserAlreadyExistsError
//if errors.As(err, &errUserAlreadyExists) {
// response.ErrorResponse(w, http.StatusConflict, err, "User already exists", h.log)
// return
//}
h.log.WithField(
"Request-Id", contextutils.GetReqID(r.Context()),
).Errorf("Error in sign up: %v", err)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const (
WHERE user_id = $1 AND id = $2
);`

transactionAssociationDelete = "DELETE FROM transactionCategory WHERE category_id = $1;"
transactionAssociationDelete = "DELETE FROM TransactionCategory WHERE category_id = $1;"
)

type Repository struct {
Expand Down
145 changes: 145 additions & 0 deletions internal/microservices/goal/delivery/http/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package http

import (
"encoding/json"
"net/http"

contextutils "github.com/go-park-mail-ru/2023_2_Hamster/internal/common/context_utils"
response "github.com/go-park-mail-ru/2023_2_Hamster/internal/common/http"
"github.com/go-park-mail-ru/2023_2_Hamster/internal/models"

"github.com/go-park-mail-ru/2023_2_Hamster/internal/common/logger"
"github.com/go-park-mail-ru/2023_2_Hamster/internal/microservices/goal"
)

type Handler struct {
goalUsecase goal.Useace
log logger.Logger
}

func NewHandler(gu goal.Useace, l logger.Logger) *Handler {
return &Handler{
goalUsecase: gu,
log: l,
}
}

func (h *Handler) CreateGoal(w http.ResponseWriter, r *http.Request) {
// get user from context
user, err := response.GetUserFromRequest(r)
if err != nil {
response.ErrorResponse(w, http.StatusUnauthorized, err, response.ErrUnauthorized.Error(), h.log)
return
}

// unmarshal request body
var goalInput goal.GoalCreateRequest

decoder := json.NewDecoder(r.Body)
if err := decoder.Decode(&goalInput); err != nil {
h.log.WithField(
"Request-Id", contextutils.GetReqID(r.Context()),
).Errorf("[handler] Error Corupted request body: %v", err)
response.ErrorResponse(w, http.StatusBadRequest, err, "Corrupted request body can't unmarshal", h.log)
return
}
defer r.Body.Close()

goalInput.UserId = user.ID

goalId, err := h.goalUsecase.CreateGoal(r.Context(), goalInput)
if err != nil {
response.ErrorResponse(w, http.StatusBadRequest, err, "can't create goal", h.log)
return
}

response.SuccessResponse(w, http.StatusOK, goalId)
}

func (h *Handler) UpdateGoal(w http.ResponseWriter, r *http.Request) {
user, err := response.GetUserFromRequest(r)
if err != nil {
response.ErrorResponse(w, http.StatusUnauthorized, err, response.ErrUnauthorized.Error(), h.log)
return
}

var goalInput models.Goal

decoder := json.NewDecoder(r.Body)
if err := decoder.Decode(&goalInput); err != nil {
h.log.WithField(
"Request-Id", contextutils.GetReqID(r.Context()),
).Errorf("[handler] Error Corupted request body: %v", err)
response.ErrorResponse(w, http.StatusBadRequest, err, "Corrupted request body can't unmarshal", h.log)
return
}
defer r.Body.Close()

goalInput.UserId = user.ID

if err := h.goalUsecase.UpdateGoal(r.Context(), &goalInput); err != nil {
response.ErrorResponse(w, http.StatusBadRequest, err, "can't update goal", h.log)
return
}

response.SuccessResponse(w, http.StatusOK, response.NilBody{})
}

func (h *Handler) DeleteGoal(w http.ResponseWriter, r *http.Request) {
user, err := response.GetUserFromRequest(r)
if err != nil {
response.ErrorResponse(w, http.StatusUnauthorized, err, response.ErrUnauthorized.Error(), h.log)
return
}

var goalInput goal.GoalDeleteRequest

decoder := json.NewDecoder(r.Body)
if err := decoder.Decode(&goalInput); err != nil {
h.log.WithField(
"Request-Id", contextutils.GetReqID(r.Context()),
).Errorf("[handler] Error Corupted request body: %v", err)
response.ErrorResponse(w, http.StatusBadRequest, err, "Corrupted request body can't unmarshal", h.log)
return
}
defer r.Body.Close()

if err := h.goalUsecase.DeleteGoal(r.Context(), goalInput.ID, user.ID); err != nil {
response.ErrorResponse(w, http.StatusBadRequest, err, "can't delete goal", h.log)
return
}

response.SuccessResponse(w, http.StatusOK, response.NilBody{})
}

func (h *Handler) GetGoals(w http.ResponseWriter, r *http.Request) {
user, err := response.GetUserFromRequest(r)
if err != nil {
response.ErrorResponse(w, http.StatusUnauthorized, err, response.ErrUnauthorized.Error(), h.log)
return
}

goals, err := h.goalUsecase.GetGoals(r.Context(), user.ID)
if err != nil {
response.ErrorResponse(w, http.StatusInternalServerError, err, "can't get goals", h.log)
return
}

response.SuccessResponse(w, http.StatusOK, goals)
}

func (h *Handler) CheckGoalsState(w http.ResponseWriter, r *http.Request) {
user, err := response.GetUserFromRequest(r)
if err != nil {
response.ErrorResponse(w, http.StatusUnauthorized, err, response.ErrUnauthorized.Error(), h.log)
return
}

goals, err := h.goalUsecase.CheckGoalsState(r.Context(), user.ID)
if err != nil {
response.ErrorResponse(w, http.StatusBadRequest, err, "can't check goals state", h.log)
return
}

response.SuccessResponse(w, http.StatusOK, goals)
}
26 changes: 26 additions & 0 deletions internal/microservices/goal/goal.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package goal

import (
"context"

"github.com/go-park-mail-ru/2023_2_Hamster/internal/models"
"github.com/google/uuid"
)

type Useace interface {
CreateGoal(ctx context.Context, goal GoalCreateRequest) (uuid.UUID, error)
UpdateGoal(ctx context.Context, goal *models.Goal) error
DeleteGoal(ctx context.Context, goalId uuid.UUID, userId uuid.UUID) error
GetGoals(ctx context.Context, userId uuid.UUID) ([]models.Goal, error)

CheckGoalsState(ctx context.Context, userId uuid.UUID) ([]models.Goal, error) // check if any goals are completed
}

type Repository interface {
CreateGoal(ctx context.Context, goal models.Goal) (uuid.UUID, error)
UpdateGoal(ctx context.Context, goal *models.Goal) error
DeleteGoal(ctx context.Context, goalId uuid.UUID) error
GetGoals(ctx context.Context, userId uuid.UUID) ([]models.Goal, error)

CheckGoalsState(ctx context.Context, userId uuid.UUID) ([]models.Goal, error) // check if any goals are completed
}
26 changes: 26 additions & 0 deletions internal/microservices/goal/goal_models.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package goal

import "github.com/google/uuid"

type (
GoalCreateRequest struct {
UserId uuid.UUID `json:"user_id" valid:"required"`
Name string `json:"name" valid:"required"`
Description string `json:"description" valid:"-"`
Total float64 `json:"total" valid:"required,greaterzero"`
Date string `json:"date" valid:"isdate"`
}

GoalUpdateRequest struct {
ID uuid.UUID `json:"id" valid:"required"`
UserId uuid.UUID `json:"user_id" valid:"required"`
Name string `json:"name" valid:"required"`
Description string `json:"description" valid:"-"`
Total float64 `json:"total" valid:"required,greaterzero"`
Date string `json:"date" valid:"isdate"`
}

GoalDeleteRequest struct {
ID uuid.UUID `json:"id" valid:"required"`
}
)
81 changes: 81 additions & 0 deletions internal/microservices/goal/repository/postgres/repository.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package postgres

Check failure on line 1 in internal/microservices/goal/repository/postgres/repository.go

View workflow job for this annotation

GitHub Actions / lint_and_test

: # github.com/go-park-mail-ru/2023_2_Hamster/internal/microservices/goal/repository/postgres

import (
"context"
"fmt"

"github.com/go-park-mail-ru/2023_2_Hamster/cmd/api/init/db/postgresql"
"github.com/go-park-mail-ru/2023_2_Hamster/internal/common/logger"
"github.com/go-park-mail-ru/2023_2_Hamster/internal/models"
"github.com/google/uuid"
)

const (
GoalGet = `SELECT user_id, "name", "description", target, "date" FROM goal WHERE id=$1;`

GoalCreate = `INSERT INTO goal (user_id, "name", "description", target, "date")
VALUES ($1, $2, $3, $4, $5)
RETURNING id;`

GoalUpdate = `UPDATE goal SET "name"=$1, "description"=$2, target=$3, "date"=$4 WHERE id=$5;`

GoalDelete = "DELETE FROM goal WHERE id = $1;"

GoalAll = `SELECT * FROM goal WHERE user_id = $1;`
)

type Repository struct {
db postgresql.DbConn
log logger.Logger
}

func NewRepository(db postgresql.DbConn, log logger.Logger) *Repository {
return &Repository{
db: db,
log: log,
}
}

func (r *Repository) CreateGoal(ctx context.Context, goal models.Goal) (uuid.UUID, error) {
row := r.db.QueryRow(ctx, GoalCreate,
goal.UserId,
goal.Name,
goal.Description,
goal.Target,
goal.Date,
)

var id uuid.UUID
if err := row.Scan(&id); err != nil {
return uuid.Nil, err
}

return id, nil
}

func (r *Repository) UpdateGoal(ctx context.Context, goal *models.Goal) error {
_, err := r.db.Exec(ctx, GoalUpdate,
goal.Name,
goal.Description,
goal.Target,
goal.Date,
goal.ID,
)
if err != nil {
return fmt.Errorf("[repo] UpdateGoal: %w", err)
}

return nil
}

func (r *Repository) DeleteGoal(ctx context.Context, goalId uuid.UUID) error {

}

Check failure on line 73 in internal/microservices/goal/repository/postgres/repository.go

View workflow job for this annotation

GitHub Actions / test

missing return

Check failure on line 73 in internal/microservices/goal/repository/postgres/repository.go

View workflow job for this annotation

GitHub Actions / lint_and_test

missing return

Check failure on line 73 in internal/microservices/goal/repository/postgres/repository.go

View workflow job for this annotation

GitHub Actions / linter

missing return

func (r *Repository) GetGoals(ctx context.Context, userId uuid.UUID) ([]models.Goal, error) {

}

Check failure on line 77 in internal/microservices/goal/repository/postgres/repository.go

View workflow job for this annotation

GitHub Actions / test

missing return

Check failure on line 77 in internal/microservices/goal/repository/postgres/repository.go

View workflow job for this annotation

GitHub Actions / lint_and_test

missing return

Check failure on line 77 in internal/microservices/goal/repository/postgres/repository.go

View workflow job for this annotation

GitHub Actions / linter

missing return

func (r *Repository) CheckGoalsState(ctx context.Context, userId uuid.UUID) ([]models.Goal, error) {

}

Check failure on line 81 in internal/microservices/goal/repository/postgres/repository.go

View workflow job for this annotation

GitHub Actions / test

missing return

Check failure on line 81 in internal/microservices/goal/repository/postgres/repository.go

View workflow job for this annotation

GitHub Actions / lint_and_test

missing return (typecheck)

Check failure on line 81 in internal/microservices/goal/repository/postgres/repository.go

View workflow job for this annotation

GitHub Actions / linter

missing return
Loading

0 comments on commit cf9cc9d

Please sign in to comment.