From 669bfbf5a06115ddd7d0698603c59623c025fde9 Mon Sep 17 00:00:00 2001 From: nquidox Date: Sun, 1 Mar 2026 22:13:39 +0300 Subject: [PATCH] origins --- internal/app/handler.go | 8 ++- internal/merch/controller.go | 97 +++++++++++++++++++++++++++++++++++- internal/merch/handler.go | 10 ++-- internal/merch/model.go | 19 +++++++ internal/merch/repository.go | 59 +++++++++++++++++++++- internal/merch/service.go | 51 +++++++++++++++++-- 6 files changed, 232 insertions(+), 12 deletions(-) diff --git a/internal/app/handler.go b/internal/app/handler.go index ecee711..ed1dcd6 100644 --- a/internal/app/handler.go +++ b/internal/app/handler.go @@ -8,6 +8,7 @@ import ( "merch-api/internal/merch" "merch-api/pkg/dbase" "merch-api/pkg/router" + "merch-api/pkg/utils" "time" ) @@ -36,6 +37,8 @@ func New(cfg config.Config) *App { DBName: cfg.DBase.DBName, }) + u := utils.New() + if err != nil { log.WithError(err).Fatalf("%v failed to connect database", pkgLogHeader) } @@ -43,7 +46,10 @@ func New(cfg config.Config) *App { //modules var modules []Module - m := merch.New(db) + m := merch.New(merch.Deps{ + DB: db, + Utils: u, + }) modules = append(modules, m) return &App{ diff --git a/internal/merch/controller.go b/internal/merch/controller.go index 4a8c1fc..41961a5 100644 --- a/internal/merch/controller.go +++ b/internal/merch/controller.go @@ -1,6 +1,10 @@ package merch -import "github.com/gin-gonic/gin" +import ( + "github.com/gin-gonic/gin" + "merch-api/pkg/responses" + "net/http" +) type controller struct { service *service @@ -21,6 +25,11 @@ func (h *Handler) RegisterRoutes(r *gin.RouterGroup) { merchGroup.PUT("/update", h.controller.update) merchGroup.DELETE("/delete", h.controller.delete) + originsGroup := merchGroup.Group("/origins") + originsGroup.POST("", h.controller.createOrigin) + originsGroup.GET("", h.controller.getOrigins) + originsGroup.DELETE("", h.controller.deleteOrigin) + } func (co *controller) create(c *gin.Context) {} @@ -32,3 +41,89 @@ func (co *controller) getMany(c *gin.Context) {} func (co *controller) update(c *gin.Context) {} func (co *controller) delete(c *gin.Context) {} + +// createOrigin godoc +// +// @Summary Create new origin +// @Description Create new origin with name +// @Tags Origins +// @Accept json +// @Param origin body newOriginDTO true "origin body" +// @Success 201 +// @Failure 400 {object} responses.BadRequest +// @Failure 401 {object} responses.Unauthorized +// @Failure 500 {object} responses.InternalServerError +// @Router /merch/origins [POST] +func (co *controller) createOrigin(c *gin.Context) { + var origin *newOriginDTO + + if err := c.ShouldBindJSON(&origin); err != nil { + c.JSON(http.StatusBadRequest, responses.BadRequest{Error: err.Error()}) + logErrController(err) + return + } + + if err := co.service.createOrigin(origin); err != nil { + c.JSON(http.StatusInternalServerError, responses.InternalServerError{Error: err.Error()}) + logErrController(err) + return + } + + logDebugController("create origin success") + c.Status(http.StatusCreated) +} + +// getOrigins godoc +// +// @Summary Get all origins +// @Description Get all origins +// @Tags Origins +// @Produce json +// @Success 200 {object} originsDTO +// @Success 204 +// @Failure 400 {object} responses.BadRequest +// @Failure 401 {object} responses.Unauthorized +// @Failure 500 {object} responses.InternalServerError +// @Router /merch/origins [GET] +func (co *controller) getOrigins(c *gin.Context) { + response, err := co.service.getOrigins() + if err != nil { + c.JSON(http.StatusInternalServerError, responses.InternalServerError{Error: err.Error()}) + logErrController(err) + return + } + + logDebugController("get origins success") + c.JSON(http.StatusOK, response) +} + +// deleteOrigin godoc +// +// @Summary Delete origin +// @Description Marks origin as deleted by name. +// @Tags Origins +// @Accept json +// @Param origin body deleteOriginDTO true "origin body" +// @Success 204 +// @Failure 400 {object} responses.BadRequest +// @Failure 401 {object} responses.Unauthorized +// @Failure 500 {object} responses.InternalServerError +// @Router /merch/origins [DELETE] +func (co *controller) deleteOrigin(c *gin.Context) { + var origin *deleteOriginDTO + + if err := c.ShouldBindJSON(&origin); err != nil { + c.JSON(http.StatusBadRequest, responses.BadRequest{Error: err.Error()}) + logErrController(err) + return + } + + if err := co.service.deleteOrigin(origin); err != nil { + c.JSON(http.StatusInternalServerError, responses.InternalServerError{Error: err.Error()}) + logErrController(err) + return + } + + logDebugController("delete origin success") + c.Status(http.StatusNoContent) +} diff --git a/internal/merch/handler.go b/internal/merch/handler.go index 8f0c462..a469151 100644 --- a/internal/merch/handler.go +++ b/internal/merch/handler.go @@ -2,7 +2,7 @@ package merch import ( "database/sql" - "github.com/gin-gonic/gin" + "merch-api/pkg/utils" ) type Handler struct { @@ -11,12 +11,12 @@ type Handler struct { type Deps struct { DB *sql.DB - Group *gin.RouterGroup + Utils utils.Utils } -func New(db *sql.DB) *Handler { - r := newRepo(db) - s := newService(r) +func New(deps Deps) *Handler { + r := newRepo(deps.DB) + s := newService(r, deps.Utils) c := newController(s) return &Handler{ diff --git a/internal/merch/model.go b/internal/merch/model.go index c09055f..82d75ad 100644 --- a/internal/merch/model.go +++ b/internal/merch/model.go @@ -14,3 +14,22 @@ type Merch struct { UserId string Name string } + +// Origin model. Table name: merch_origins +type Origin struct { + Id uint + CreatedAt time.Time + DeletedAt sql.NullTime + Name string +} + +// Price model. Table name: merch_prices +type Price struct { + Id uint + CreatedAt time.Time + UpdatedAt sql.NullTime + DeletedAt sql.NullTime + MerchUuid string + Price int + OriginId uint +} diff --git a/internal/merch/repository.go b/internal/merch/repository.go index 0562192..a5fb03f 100644 --- a/internal/merch/repository.go +++ b/internal/merch/repository.go @@ -2,14 +2,69 @@ package merch import "database/sql" -type Repository interface{} +type Repository interface { + Origins +} + +type Origins interface { + createOrigin(origin *Origin) error + getOrigins() ([]Origin, error) + deleteOriginByName(name string, deletedAt sql.NullTime) error +} type repo struct { db *sql.DB } func newRepo(db *sql.DB) Repository { - return repo{ + return &repo{ db: db, } } + +func (r *repo) createOrigin(origin *Origin) error { + q := `INSERT INTO merch_origins (created_at, deleted_at, name) VALUES ($1, $2, $3)` + + _, err := r.db.Exec(q, origin.CreatedAt, origin.DeletedAt, origin.Name) + if err != nil { + return err + } + + return nil +} + +func (r *repo) getOrigins() ([]Origin, error) { + q := `SELECT * FROM merch_origins WHERE deleted_at IS NULL` + + rows, err := r.db.Query(q) + if err != nil { + return nil, err + } + defer rows.Close() + + var origins []Origin + for rows.Next() { + var o Origin + if err = rows.Scan(&o.Id, &o.CreatedAt, &o.DeletedAt, &o.Name); err != nil { + return nil, err + } + origins = append(origins, o) + } + + if err = rows.Err(); err != nil { + return nil, err + } + + return origins, nil +} + +func (r *repo) deleteOriginByName(name string, deletedAt sql.NullTime) error { + q := `UPDATE merch_origins SET deleted_at = $1 WHERE name = $2` + + _, err := r.db.Exec(q, deletedAt.Time, name) + if err != nil { + return err + } + + return nil +} diff --git a/internal/merch/service.go b/internal/merch/service.go index 921348d..e55c05d 100644 --- a/internal/merch/service.go +++ b/internal/merch/service.go @@ -1,11 +1,56 @@ package merch +import ( + "merch-api/pkg/utils" +) + type service struct { - repo Repository + repo Repository + utils utils.Utils } -func newService(repo Repository) *service { +func newService(repo Repository, u utils.Utils) *service { return &service{ - repo: repo, + repo: repo, + utils: u, } } + +func (s *service) createOrigin(o *newOriginDTO) error { + newOrigin := &Origin{ + CreatedAt: s.utils.TimeNowUTC(), + DeletedAt: s.utils.DeletedNullTime(), + Name: o.Name, + } + + logDebugService("create origin success") + return s.repo.createOrigin(newOrigin) +} + +func (s *service) getOrigins() (*originsDTO, error) { + data, err := s.repo.getOrigins() + if err != nil { + logErrService(err) + return nil, err + } + + var origins []originItem + for _, item := range data { + origins = append(origins, originItem{ + Id: item.Id, + Name: item.Name, + }) + } + + response := &originsDTO{ + Origins: origins, + } + + logDebugService("get origins success") + return response, nil +} + +func (s *service) deleteOrigin(origin *deleteOriginDTO) error { + logDebugService("delete origin success") + return s.repo.deleteOriginByName(origin.Name, s.utils.NullTimeNowUTC()) +}