2026-02-23 20:02:17 +03:00
|
|
|
|
package merch
|
|
|
|
|
|
|
2026-03-01 22:13:39 +03:00
|
|
|
|
import (
|
2026-03-07 15:49:54 +03:00
|
|
|
|
"errors"
|
2026-03-01 22:13:39 +03:00
|
|
|
|
"github.com/gin-gonic/gin"
|
2026-03-04 17:59:46 +03:00
|
|
|
|
"github.com/google/uuid"
|
2026-03-01 22:13:39 +03:00
|
|
|
|
"merch-api/pkg/responses"
|
2026-03-04 17:02:11 +03:00
|
|
|
|
"merch-api/pkg/utils"
|
2026-03-01 22:13:39 +03:00
|
|
|
|
"net/http"
|
|
|
|
|
|
)
|
2026-02-23 20:02:17 +03:00
|
|
|
|
|
2026-03-08 15:12:17 +03:00
|
|
|
|
const controllerLogHeader string = "[Controller]"
|
|
|
|
|
|
|
2026-02-23 20:02:17 +03:00
|
|
|
|
type controller struct {
|
|
|
|
|
|
service *service
|
2026-03-04 17:02:11 +03:00
|
|
|
|
utils utils.Utils
|
2026-02-23 20:02:17 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-04 17:02:11 +03:00
|
|
|
|
func newController(s *service, u utils.Utils) *controller {
|
2026-02-23 20:02:17 +03:00
|
|
|
|
return &controller{
|
|
|
|
|
|
service: s,
|
2026-03-04 17:02:11 +03:00
|
|
|
|
utils: u,
|
2026-02-23 20:02:17 +03:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (h *Handler) RegisterRoutes(r *gin.RouterGroup) {
|
|
|
|
|
|
merchGroup := r.Group("/merch")
|
|
|
|
|
|
|
|
|
|
|
|
merchGroup.POST("/create", h.controller.create)
|
|
|
|
|
|
merchGroup.GET("/:id", h.controller.getOne)
|
|
|
|
|
|
merchGroup.GET("/list", h.controller.getMany)
|
2026-03-07 15:49:54 +03:00
|
|
|
|
merchGroup.PUT("/:id", h.controller.updateMerch)
|
|
|
|
|
|
merchGroup.PUT("/extra/:id", h.controller.updateExtraData)
|
2026-03-04 17:59:46 +03:00
|
|
|
|
merchGroup.DELETE("/:id", h.controller.deleteMerch)
|
2026-02-23 20:02:17 +03:00
|
|
|
|
|
2026-03-01 22:13:39 +03:00
|
|
|
|
originsGroup := merchGroup.Group("/origins")
|
|
|
|
|
|
originsGroup.POST("", h.controller.createOrigin)
|
|
|
|
|
|
originsGroup.GET("", h.controller.getOrigins)
|
|
|
|
|
|
originsGroup.DELETE("", h.controller.deleteOrigin)
|
|
|
|
|
|
|
2026-03-10 23:44:24 +03:00
|
|
|
|
chartsGroup := r.Group("/prices")
|
|
|
|
|
|
chartsGroup.GET("", h.controller.getChartsPrices)
|
|
|
|
|
|
chartsGroup.GET("/:uuid", h.controller.getDistinctPrices)
|
|
|
|
|
|
|
2026-03-11 20:17:30 +03:00
|
|
|
|
zeroPricesGroup := merchGroup.Group("/zeroprices")
|
|
|
|
|
|
zeroPricesGroup.GET("", h.controller.getZeroPrices)
|
|
|
|
|
|
zeroPricesGroup.DELETE("", h.controller.deleteZeroPrices)
|
|
|
|
|
|
|
|
|
|
|
|
zeroPricesGroup.DELETE("/period", h.controller.deleteZeroPricesPeriod)
|
|
|
|
|
|
|
2026-03-13 16:02:49 +03:00
|
|
|
|
labelsGroup := merchGroup.Group("/labels")
|
|
|
|
|
|
labelsGroup.POST("", h.controller.createLabel)
|
|
|
|
|
|
labelsGroup.GET("", h.controller.getLabels)
|
|
|
|
|
|
labelsGroup.PUT("/:uuid", h.controller.updateLabel)
|
|
|
|
|
|
labelsGroup.DELETE("/:uuid", h.controller.deleteLabel)
|
|
|
|
|
|
labelsGroup.POST("/attach", h.controller.attachLabel)
|
|
|
|
|
|
labelsGroup.POST("/detach", h.controller.detachLabel)
|
|
|
|
|
|
labelsGroup.GET("/:uuid", h.controller.getMerchLabels)
|
2026-02-23 20:02:17 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-04 17:02:11 +03:00
|
|
|
|
// create godoc
|
|
|
|
|
|
//
|
2026-03-11 20:17:30 +03:00
|
|
|
|
// @Summary Create new merch
|
|
|
|
|
|
// @Description Create new merch
|
|
|
|
|
|
// @Tags Merch
|
|
|
|
|
|
// @Accept json
|
|
|
|
|
|
// @Param merch body newMerchDTO true "merch body"
|
|
|
|
|
|
// @Success 201
|
|
|
|
|
|
// @Failure 400 {object} responses.BadRequest
|
|
|
|
|
|
// @Failure 401 {object} responses.Unauthorized
|
|
|
|
|
|
// @Failure 500 {object} responses.InternalServerError
|
|
|
|
|
|
// @Router /merch/create [POST]
|
2026-03-04 17:02:11 +03:00
|
|
|
|
func (co *controller) create(c *gin.Context) {
|
|
|
|
|
|
var newMerch newMerchDTO
|
2026-03-07 15:49:54 +03:00
|
|
|
|
if err := c.ShouldBindJSON(&newMerch); err != nil {
|
2026-03-04 17:02:11 +03:00
|
|
|
|
c.JSON(http.StatusBadRequest, responses.BadRequest{Error: err.Error()})
|
2026-03-08 15:12:17 +03:00
|
|
|
|
logErr(controllerLogHeader, err)
|
2026-03-04 17:02:11 +03:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-07 15:49:54 +03:00
|
|
|
|
if err := co.service.createMerch(c, getUserId(c), &newMerch); err != nil {
|
2026-03-04 17:02:11 +03:00
|
|
|
|
c.JSON(http.StatusInternalServerError, responses.InternalServerError{Error: err.Error()})
|
2026-03-08 15:12:17 +03:00
|
|
|
|
logErr(controllerLogHeader, err)
|
2026-03-04 17:02:11 +03:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
c.Status(http.StatusCreated)
|
|
|
|
|
|
}
|
2026-02-23 20:02:17 +03:00
|
|
|
|
|
|
|
|
|
|
func (co *controller) getOne(c *gin.Context) {}
|
|
|
|
|
|
|
2026-03-04 17:59:46 +03:00
|
|
|
|
// getMany godoc
|
|
|
|
|
|
//
|
2026-03-11 20:17:30 +03:00
|
|
|
|
// @Summary Get all merch
|
|
|
|
|
|
// @Description Get all merch without origins
|
|
|
|
|
|
// @Tags Merch
|
|
|
|
|
|
// @Produce json
|
2026-03-13 16:50:50 +03:00
|
|
|
|
// @Success 200 {array} ListResponse
|
2026-03-11 20:17:30 +03:00
|
|
|
|
// @Success 204
|
|
|
|
|
|
// @Failure 400 {object} responses.BadRequest
|
|
|
|
|
|
// @Failure 401 {object} responses.Unauthorized
|
|
|
|
|
|
// @Failure 500 {object} responses.InternalServerError
|
|
|
|
|
|
// @Router /merch/list [GET]
|
2026-03-04 17:59:46 +03:00
|
|
|
|
func (co *controller) getMany(c *gin.Context) {
|
2026-03-07 15:49:54 +03:00
|
|
|
|
response, err := co.service.getMany(c, getUserId(c))
|
2026-03-04 17:59:46 +03:00
|
|
|
|
if err != nil {
|
2026-03-07 15:49:54 +03:00
|
|
|
|
c.JSON(http.StatusInternalServerError, responses.InternalServerError{Error: err.Error()})
|
2026-03-08 15:12:17 +03:00
|
|
|
|
logErr(controllerLogHeader, err)
|
2026-03-04 17:59:46 +03:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-07 15:49:54 +03:00
|
|
|
|
if len(response) == 0 {
|
|
|
|
|
|
c.Status(http.StatusNoContent)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, response)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// updateMerch godoc
|
|
|
|
|
|
//
|
2026-03-11 20:17:30 +03:00
|
|
|
|
// @Summary Update merch
|
|
|
|
|
|
// @Description Update merch general info (except extra data)
|
|
|
|
|
|
// @Tags Merch
|
|
|
|
|
|
// @Accept json
|
|
|
|
|
|
// @Param uuid path string true "merch uuid"
|
|
|
|
|
|
// @Param payload body updateMerchDTO true "payload"
|
|
|
|
|
|
// @Produce json
|
|
|
|
|
|
// @Success 200 {object} merchDTO
|
|
|
|
|
|
// @Failure 400 {object} responses.BadRequest
|
|
|
|
|
|
// @Failure 401 {object} responses.Unauthorized
|
|
|
|
|
|
// @Failure 500 {object} responses.InternalServerError
|
|
|
|
|
|
// @Router /merch/{uuid} [PUT]
|
2026-03-07 15:49:54 +03:00
|
|
|
|
func (co *controller) updateMerch(c *gin.Context) {
|
|
|
|
|
|
merchUuid := c.Param("id")
|
|
|
|
|
|
if err := uuid.Validate(merchUuid); err != nil {
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, responses.BadRequest{Error: err.Error()})
|
2026-03-08 15:12:17 +03:00
|
|
|
|
logErr(controllerLogHeader, err)
|
2026-03-07 15:49:54 +03:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var payload updateMerchDTO
|
|
|
|
|
|
if err := c.ShouldBindJSON(&payload); err != nil {
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, responses.BadRequest{Error: err.Error()})
|
2026-03-08 15:12:17 +03:00
|
|
|
|
logErr(controllerLogHeader, err)
|
2026-03-07 15:49:54 +03:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if merchUuid != payload.MerchUuid {
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, responses.BadRequest{Error: "MerchUuid does not match"})
|
2026-03-08 15:12:17 +03:00
|
|
|
|
logErr(controllerLogHeader, errors.New("MerchUuid does not match"))
|
2026-03-07 15:49:54 +03:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
response, err := co.service.updateMerch(c, getUserId(c), &payload)
|
2026-03-04 17:59:46 +03:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
c.JSON(http.StatusInternalServerError, responses.InternalServerError{Error: err.Error()})
|
2026-03-08 15:12:17 +03:00
|
|
|
|
logErr(controllerLogHeader, err)
|
2026-03-04 17:59:46 +03:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-07 15:49:54 +03:00
|
|
|
|
c.JSON(http.StatusOK, response)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// updateMerch godoc
|
|
|
|
|
|
//
|
2026-03-11 20:17:30 +03:00
|
|
|
|
// @Summary Update merch extra data
|
|
|
|
|
|
// @Description Update ONLY merch extra data
|
|
|
|
|
|
// @Tags Merch
|
|
|
|
|
|
// @Accept json
|
|
|
|
|
|
// @Param uuid path string true "merch uuid"
|
|
|
|
|
|
// @Param payload body extraDataDTO true "payload"
|
|
|
|
|
|
// @Produce json
|
|
|
|
|
|
// @Success 200 {object} extraDataDTO
|
|
|
|
|
|
// @Failure 400 {object} responses.BadRequest
|
|
|
|
|
|
// @Failure 401 {object} responses.Unauthorized
|
|
|
|
|
|
// @Failure 500 {object} responses.InternalServerError
|
|
|
|
|
|
// @Router /merch/extra/{uuid} [PUT]
|
2026-03-07 15:49:54 +03:00
|
|
|
|
func (co *controller) updateExtraData(c *gin.Context) {
|
|
|
|
|
|
merchUuid := c.Param("id")
|
|
|
|
|
|
if err := uuid.Validate(merchUuid); err != nil {
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, responses.BadRequest{Error: err.Error()})
|
2026-03-08 15:12:17 +03:00
|
|
|
|
logErr(controllerLogHeader, err)
|
2026-03-07 15:49:54 +03:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var payload extraDataDTO
|
|
|
|
|
|
if err := c.ShouldBindJSON(&payload); err != nil {
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, responses.BadRequest{Error: err.Error()})
|
2026-03-08 15:12:17 +03:00
|
|
|
|
logErr(controllerLogHeader, err)
|
2026-03-07 15:49:54 +03:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if merchUuid != payload.MerchUuid {
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, responses.BadRequest{Error: "MerchUuid does not match"})
|
2026-03-08 15:12:17 +03:00
|
|
|
|
logErr(controllerLogHeader, errors.New("MerchUuid does not match"))
|
2026-03-07 15:49:54 +03:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
response, err := co.service.updateExtraData(c, getUserId(c), &payload)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
c.JSON(http.StatusInternalServerError, responses.InternalServerError{Error: err.Error()})
|
2026-03-08 15:12:17 +03:00
|
|
|
|
logErr(controllerLogHeader, err)
|
2026-03-04 17:59:46 +03:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, response)
|
|
|
|
|
|
}
|
2026-02-23 20:02:17 +03:00
|
|
|
|
|
2026-03-04 17:59:46 +03:00
|
|
|
|
// deleteMerch godoc
|
|
|
|
|
|
//
|
2026-03-11 20:17:30 +03:00
|
|
|
|
// @Summary Delete merch
|
|
|
|
|
|
// @Description Marks merch and all its extra data as deleted by uuid.
|
|
|
|
|
|
// @Tags Merch
|
|
|
|
|
|
// @Accept json
|
|
|
|
|
|
// @Param uuid path string true "merch uuid"
|
|
|
|
|
|
// @Success 204
|
|
|
|
|
|
// @Failure 400 {object} responses.BadRequest
|
|
|
|
|
|
// @Failure 401 {object} responses.Unauthorized
|
|
|
|
|
|
// @Failure 500 {object} responses.InternalServerError
|
|
|
|
|
|
// @Router /merch/{uuid} [DELETE]
|
2026-03-04 17:59:46 +03:00
|
|
|
|
func (co *controller) deleteMerch(c *gin.Context) {
|
|
|
|
|
|
merchUuid := c.Param("id")
|
2026-03-07 15:49:54 +03:00
|
|
|
|
if err := uuid.Validate(merchUuid); err != nil {
|
2026-03-04 17:59:46 +03:00
|
|
|
|
c.JSON(http.StatusBadRequest, responses.BadRequest{Error: err.Error()})
|
2026-03-08 15:12:17 +03:00
|
|
|
|
logErr(controllerLogHeader, err)
|
2026-03-04 17:59:46 +03:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-07 15:49:54 +03:00
|
|
|
|
if err := co.service.deleteOneMerchRecord(c, getUserId(c), merchUuid); err != nil {
|
2026-03-04 17:59:46 +03:00
|
|
|
|
c.JSON(http.StatusInternalServerError, responses.InternalServerError{Error: err.Error()})
|
2026-03-08 15:12:17 +03:00
|
|
|
|
logErr(controllerLogHeader, err)
|
2026-03-04 17:59:46 +03:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
c.Status(http.StatusNoContent)
|
|
|
|
|
|
}
|
2026-03-01 22:13:39 +03:00
|
|
|
|
|
|
|
|
|
|
// createOrigin godoc
|
|
|
|
|
|
//
|
2026-03-11 20:17:30 +03:00
|
|
|
|
// @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]
|
2026-03-01 22:13:39 +03:00
|
|
|
|
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()})
|
2026-03-08 15:12:17 +03:00
|
|
|
|
logErr(controllerLogHeader, err)
|
2026-03-01 22:13:39 +03:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-04 17:02:11 +03:00
|
|
|
|
if err := co.service.createOrigin(c, origin); err != nil {
|
2026-03-01 22:13:39 +03:00
|
|
|
|
c.JSON(http.StatusInternalServerError, responses.InternalServerError{Error: err.Error()})
|
2026-03-08 15:12:17 +03:00
|
|
|
|
logErr(controllerLogHeader, err)
|
2026-03-01 22:13:39 +03:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-08 15:12:17 +03:00
|
|
|
|
logDebug(controllerLogHeader, "create origin success")
|
2026-03-01 22:13:39 +03:00
|
|
|
|
c.Status(http.StatusCreated)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// getOrigins godoc
|
|
|
|
|
|
//
|
2026-03-11 20:17:30 +03:00
|
|
|
|
// @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]
|
2026-03-01 22:13:39 +03:00
|
|
|
|
func (co *controller) getOrigins(c *gin.Context) {
|
2026-03-04 17:02:11 +03:00
|
|
|
|
response, err := co.service.getOrigins(c)
|
2026-03-01 22:13:39 +03:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
c.JSON(http.StatusInternalServerError, responses.InternalServerError{Error: err.Error()})
|
2026-03-08 15:12:17 +03:00
|
|
|
|
logErr(controllerLogHeader, err)
|
2026-03-01 22:13:39 +03:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-08 15:12:17 +03:00
|
|
|
|
logDebug(controllerLogHeader, "get origins success")
|
2026-03-01 22:13:39 +03:00
|
|
|
|
c.JSON(http.StatusOK, response)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// deleteOrigin godoc
|
|
|
|
|
|
//
|
2026-03-11 20:17:30 +03:00
|
|
|
|
// @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]
|
2026-03-01 22:13:39 +03:00
|
|
|
|
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()})
|
2026-03-08 15:12:17 +03:00
|
|
|
|
logErr(controllerLogHeader, err)
|
2026-03-01 22:13:39 +03:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-04 17:02:11 +03:00
|
|
|
|
if err := co.service.deleteOrigin(c, origin); err != nil {
|
2026-03-01 22:13:39 +03:00
|
|
|
|
c.JSON(http.StatusInternalServerError, responses.InternalServerError{Error: err.Error()})
|
2026-03-08 15:12:17 +03:00
|
|
|
|
logErr(controllerLogHeader, err)
|
2026-03-01 22:13:39 +03:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-08 15:12:17 +03:00
|
|
|
|
logDebug(controllerLogHeader, "delete origin success")
|
2026-03-01 22:13:39 +03:00
|
|
|
|
c.Status(http.StatusNoContent)
|
|
|
|
|
|
}
|
2026-03-10 23:44:24 +03:00
|
|
|
|
|
|
|
|
|
|
// getChartsPrices godoc
|
|
|
|
|
|
//
|
2026-03-11 20:17:30 +03:00
|
|
|
|
// @Summary Получить цены мерча за период
|
|
|
|
|
|
// @Description Получить цены мерча за период
|
|
|
|
|
|
// @Tags Merch
|
|
|
|
|
|
// @Produce json
|
|
|
|
|
|
// @Param days query string false "period in days"
|
|
|
|
|
|
// @Success 200 {array} PricesResponse
|
|
|
|
|
|
// @Failure 400 {object} responses.BadRequest
|
|
|
|
|
|
// @Failure 401 {object} responses.Unauthorized
|
|
|
|
|
|
// @Failure 500 {object} responses.InternalServerError
|
|
|
|
|
|
// @Router /prices [get]
|
2026-03-10 23:44:24 +03:00
|
|
|
|
func (co *controller) getChartsPrices(c *gin.Context) {
|
|
|
|
|
|
response, err := co.service.getPrices(c, getUserId(c), getDays(c))
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, responses.InternalServerError{Error: err.Error()})
|
|
|
|
|
|
logErr(controllerLogHeader, err)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, response)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// getDistinctPrices godoc
|
|
|
|
|
|
//
|
2026-03-11 20:17:30 +03:00
|
|
|
|
// @Summary Получить перепады цен мерча за период по его merch_uuid
|
|
|
|
|
|
// @Description Получить перепады цен мерча за период по его merch_uuid
|
|
|
|
|
|
// @Tags Merch
|
|
|
|
|
|
// @Produce json
|
|
|
|
|
|
// @Param uuid path string true "merch_uuid"
|
|
|
|
|
|
// @Param days query string false "period in days"
|
|
|
|
|
|
// @Success 200 {object} PricesResponse
|
|
|
|
|
|
// @Success 204
|
|
|
|
|
|
// @Failure 400 {object} responses.BadRequest
|
|
|
|
|
|
// @Failure 401 {object} responses.Unauthorized
|
|
|
|
|
|
// @Failure 500 {object} responses.InternalServerError
|
|
|
|
|
|
// @Router /prices/{uuid} [get]
|
2026-03-10 23:44:24 +03:00
|
|
|
|
func (co *controller) getDistinctPrices(c *gin.Context) {
|
|
|
|
|
|
merchUuid := c.Param("uuid")
|
|
|
|
|
|
if merchUuid == "" {
|
|
|
|
|
|
err := errors.New("MerchUuid is empty")
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, responses.BadRequest{Error: err.Error()})
|
|
|
|
|
|
logErr(controllerLogHeader, err)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
response, err := co.service.getDistinctPrices(c, getUserId(c), merchUuid, getDays(c))
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, responses.InternalServerError{Error: err.Error()})
|
|
|
|
|
|
logErr(controllerLogHeader, err)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if response == nil {
|
|
|
|
|
|
c.Status(http.StatusNoContent)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, response)
|
|
|
|
|
|
}
|
2026-03-11 20:17:30 +03:00
|
|
|
|
|
|
|
|
|
|
// getZeroPrices godoc
|
|
|
|
|
|
//
|
|
|
|
|
|
// @Summary Получить нулевые цены
|
|
|
|
|
|
// @Description Получить нулевые цены
|
|
|
|
|
|
// @Tags Merch zero prices
|
|
|
|
|
|
// @Produce json
|
|
|
|
|
|
// @Success 200 {array} ZeroPrice
|
|
|
|
|
|
// @Success 204
|
|
|
|
|
|
// @Failure 401 {object} responses.Unauthorized
|
|
|
|
|
|
// @Failure 500 {object} responses.InternalServerError
|
|
|
|
|
|
// @Router /merch/zeroprices [get]
|
|
|
|
|
|
func (co *controller) getZeroPrices(c *gin.Context) {
|
|
|
|
|
|
response, err := co.service.getZeroPrices(c, getUserId(c))
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
c.JSON(http.StatusInternalServerError, responses.InternalServerError{Error: err.Error()})
|
|
|
|
|
|
logErr(controllerLogHeader, err)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if response == nil {
|
|
|
|
|
|
c.Status(http.StatusNoContent)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, response)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// deleteZeroPrices godoc
|
|
|
|
|
|
//
|
|
|
|
|
|
// @Summary Пометить нулевые цены как удаленные
|
|
|
|
|
|
// @Description Пометить нулевые цены как удаленные
|
|
|
|
|
|
// @Tags Merch zero prices
|
|
|
|
|
|
// @Security BearerAuth
|
|
|
|
|
|
// @Accept json
|
|
|
|
|
|
// @Param payload body DeleteZeroPrices true "payload"
|
|
|
|
|
|
// @Success 204
|
|
|
|
|
|
// @Failure 400 {object} responses.BadRequest
|
|
|
|
|
|
// @Failure 401 {object} responses.Unauthorized
|
|
|
|
|
|
// @Failure 500 {object} responses.InternalServerError
|
|
|
|
|
|
// @Router /merch/zeroprices [delete]
|
|
|
|
|
|
func (co *controller) deleteZeroPrices(c *gin.Context) {
|
|
|
|
|
|
var payload []DeleteZeroPrices
|
|
|
|
|
|
if err := c.ShouldBindJSON(&payload); err != nil {
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, responses.BadRequest{Error: err.Error()})
|
|
|
|
|
|
logErr(controllerLogHeader, err)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if len(payload) < 1 || payload == nil {
|
|
|
|
|
|
c.Status(http.StatusNoContent)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := co.service.deleteZeroPrices(c, getUserId(c), payload); err != nil {
|
|
|
|
|
|
c.JSON(http.StatusInternalServerError, responses.InternalServerError{Error: err.Error()})
|
|
|
|
|
|
logErr(controllerLogHeader, err)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
c.Status(http.StatusNoContent)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-13 16:02:49 +03:00
|
|
|
|
// deleteZeroPricesPeriod godoc
|
|
|
|
|
|
//
|
2026-03-11 20:17:30 +03:00
|
|
|
|
// @Summary Пометить нулевые цены как удаленные за указанный период
|
|
|
|
|
|
// @Description Пометить нулевые цены как удаленные за указанный период
|
|
|
|
|
|
// @Tags Merch zero prices
|
|
|
|
|
|
// @Security BearerAuth
|
|
|
|
|
|
// @Param start query string true "start"
|
|
|
|
|
|
// @Param end query string true "end"
|
|
|
|
|
|
// @Success 204
|
|
|
|
|
|
// @Failure 400 {object} responses.BadRequest
|
|
|
|
|
|
// @Failure 401 {object} responses.Unauthorized
|
|
|
|
|
|
// @Failure 500 {object} responses.InternalServerError
|
|
|
|
|
|
// @Router /merch/zeroprices/period [delete]
|
|
|
|
|
|
func (co *controller) deleteZeroPricesPeriod(c *gin.Context) {
|
|
|
|
|
|
start, err := co.utils.ParseTime(c.Query("start"))
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, responses.BadRequest{Error: err.Error()})
|
|
|
|
|
|
logErr(controllerLogHeader, err)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
end, err := co.utils.ParseTime(c.Query("end"))
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, responses.BadRequest{Error: err.Error()})
|
|
|
|
|
|
logErr(controllerLogHeader, err)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err = co.service.deleteZeroPricesPeriod(c, getUserId(c), start, end); err != nil {
|
|
|
|
|
|
c.JSON(http.StatusInternalServerError, responses.InternalServerError{Error: err.Error()})
|
|
|
|
|
|
logErr(controllerLogHeader, err)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
c.Status(http.StatusOK)
|
|
|
|
|
|
}
|
2026-03-13 16:02:49 +03:00
|
|
|
|
|
|
|
|
|
|
// createLabel godoc
|
|
|
|
|
|
//
|
|
|
|
|
|
// @Summary Создать новую метку для товара
|
|
|
|
|
|
// @Description Создать новую метку для товара
|
|
|
|
|
|
// @Tags Merch labels
|
|
|
|
|
|
// @Security BearerAuth
|
|
|
|
|
|
// @Accept json
|
|
|
|
|
|
// @Param payload body LabelDTO true "payload"
|
|
|
|
|
|
// @Success 200
|
|
|
|
|
|
// @Failure 400 {object} responses.BadRequest
|
|
|
|
|
|
// @Failure 401 {object} responses.Unauthorized
|
|
|
|
|
|
// @Failure 500 {object} responses.InternalServerError
|
|
|
|
|
|
// @Router /merch/labels [post]
|
|
|
|
|
|
func (co *controller) createLabel(c *gin.Context) {
|
|
|
|
|
|
var payload LabelDTO
|
|
|
|
|
|
if err := c.ShouldBindJSON(&payload); err != nil {
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, responses.BadRequest{Error: err.Error()})
|
|
|
|
|
|
logErr(controllerLogHeader, err)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := co.service.createLabel(c, getUserId(c), &payload); err != nil {
|
|
|
|
|
|
c.JSON(http.StatusInternalServerError, responses.InternalServerError{Error: err.Error()})
|
|
|
|
|
|
logErr(controllerLogHeader, err)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
c.Status(http.StatusOK)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// getLabels godoc
|
|
|
|
|
|
//
|
|
|
|
|
|
// @Summary Получить все метки товаров
|
|
|
|
|
|
// @Description Получить все метки товаров
|
|
|
|
|
|
// @Tags Merch labels
|
|
|
|
|
|
// @Security BearerAuth
|
|
|
|
|
|
// @Produce json
|
|
|
|
|
|
// @Success 200 {array} LabelsList
|
|
|
|
|
|
// @Failure 400 {object} responses.BadRequest
|
|
|
|
|
|
// @Failure 401 {object} responses.Unauthorized
|
|
|
|
|
|
// @Failure 500 {object} responses.InternalServerError
|
|
|
|
|
|
// @Router /merch/labels [get]
|
|
|
|
|
|
func (co *controller) getLabels(c *gin.Context) {
|
|
|
|
|
|
response, err := co.service.getLabels(c, getUserId(c))
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
c.JSON(http.StatusInternalServerError, responses.InternalServerError{Error: err.Error()})
|
|
|
|
|
|
logErr(controllerLogHeader, err)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, response)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// updateLabel godoc
|
|
|
|
|
|
//
|
|
|
|
|
|
// @Summary Изменить метку
|
|
|
|
|
|
// @Description Изменить метку
|
|
|
|
|
|
// @Tags Merch labels
|
|
|
|
|
|
// @Security BearerAuth
|
|
|
|
|
|
// @Accept json
|
|
|
|
|
|
// @Param uuid path string true "label uuid"
|
|
|
|
|
|
// @Param payload body LabelDTO true "payload"
|
|
|
|
|
|
// @Success 200
|
|
|
|
|
|
// @Failure 400 {object} responses.BadRequest
|
|
|
|
|
|
// @Failure 401 {object} responses.Unauthorized
|
|
|
|
|
|
// @Failure 500 {object} responses.InternalServerError
|
|
|
|
|
|
// @Router /merch/labels/{uuid} [put]
|
|
|
|
|
|
func (co *controller) updateLabel(c *gin.Context) {
|
|
|
|
|
|
labelUuid := c.Param("uuid")
|
|
|
|
|
|
if labelUuid == "" {
|
|
|
|
|
|
e := errors.New("LabelUuid is empty")
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, responses.BadRequest{Error: e.Error()})
|
|
|
|
|
|
logErr(controllerLogHeader, e)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var payload LabelDTO
|
|
|
|
|
|
if err := c.ShouldBindJSON(&payload); err != nil {
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, responses.BadRequest{Error: err.Error()})
|
|
|
|
|
|
logErr(controllerLogHeader, err)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := co.service.updateLabel(c, getUserId(c), labelUuid, &payload); err != nil {
|
|
|
|
|
|
c.JSON(http.StatusInternalServerError, responses.InternalServerError{Error: err.Error()})
|
|
|
|
|
|
logErr(controllerLogHeader, err)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
c.Status(http.StatusOK)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// deleteLabel godoc
|
|
|
|
|
|
//
|
|
|
|
|
|
// @Summary Пометить метку как удаленную
|
|
|
|
|
|
// @Description Пометить метку как удаленную
|
|
|
|
|
|
// @Tags Merch labels
|
|
|
|
|
|
// @Security BearerAuth
|
|
|
|
|
|
// @Param uuid path string true "label uuid"
|
|
|
|
|
|
// @Success 200
|
|
|
|
|
|
// @Failure 400 {object} responses.BadRequest
|
|
|
|
|
|
// @Failure 401 {object} responses.Unauthorized
|
|
|
|
|
|
// @Failure 500 {object} responses.InternalServerError
|
|
|
|
|
|
// @Router /merch/labels/{uuid} [delete]
|
|
|
|
|
|
func (co *controller) deleteLabel(c *gin.Context) {
|
|
|
|
|
|
labelUuid := c.Param("uuid")
|
|
|
|
|
|
if labelUuid == "" {
|
|
|
|
|
|
e := errors.New("LabelUuid is empty")
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, responses.BadRequest{Error: e.Error()})
|
|
|
|
|
|
logErr(controllerLogHeader, e)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := co.service.deleteLabel(c, getUserId(c), labelUuid); err != nil {
|
|
|
|
|
|
c.JSON(http.StatusInternalServerError, responses.InternalServerError{Error: err.Error()})
|
|
|
|
|
|
logErr(controllerLogHeader, err)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
c.Status(http.StatusOK)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// attachLabel godoc
|
|
|
|
|
|
//
|
|
|
|
|
|
// @Summary Прикрепить метку к товару
|
|
|
|
|
|
// @Description Прикрепить метку к товару
|
|
|
|
|
|
// @Tags Merch labels
|
|
|
|
|
|
// @Security BearerAuth
|
|
|
|
|
|
// @Accept json
|
|
|
|
|
|
// @Param payload body LabelLink true "payload"
|
|
|
|
|
|
// @Success 200
|
|
|
|
|
|
// @Failure 400 {object} responses.BadRequest
|
|
|
|
|
|
// @Failure 401 {object} responses.Unauthorized
|
|
|
|
|
|
// @Failure 500 {object} responses.InternalServerError
|
|
|
|
|
|
// @Router /merch/labels/attach [post]
|
|
|
|
|
|
func (co *controller) attachLabel(c *gin.Context) {
|
|
|
|
|
|
var payload LabelLink
|
|
|
|
|
|
if err := c.ShouldBindJSON(&payload); err != nil {
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, responses.BadRequest{Error: err.Error()})
|
|
|
|
|
|
logErr(controllerLogHeader, err)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := co.service.attachLabel(c, getUserId(c), &payload); err != nil {
|
|
|
|
|
|
c.JSON(http.StatusInternalServerError, responses.InternalServerError{Error: err.Error()})
|
|
|
|
|
|
logErr(controllerLogHeader, err)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
c.Status(http.StatusOK)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// detachLabel godoc
|
|
|
|
|
|
//
|
|
|
|
|
|
// @Summary Удалить привязку метки к товару
|
|
|
|
|
|
// @Description Удалить привязку метки к товару
|
|
|
|
|
|
// @Tags Merch labels
|
|
|
|
|
|
// @Security BearerAuth
|
|
|
|
|
|
// @Accept json
|
|
|
|
|
|
// @Param payload body LabelLink true "payload"
|
|
|
|
|
|
// @Success 200
|
|
|
|
|
|
// @Failure 400 {object} responses.BadRequest
|
|
|
|
|
|
// @Failure 401 {object} responses.Unauthorized
|
|
|
|
|
|
// @Failure 500 {object} responses.InternalServerError
|
|
|
|
|
|
// @Router /merch/labels/detach [post]
|
|
|
|
|
|
func (co *controller) detachLabel(c *gin.Context) {
|
|
|
|
|
|
var payload LabelLink
|
|
|
|
|
|
if err := c.ShouldBindJSON(&payload); err != nil {
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, responses.BadRequest{Error: err.Error()})
|
|
|
|
|
|
logErr(controllerLogHeader, err)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := co.service.detachLabel(c, getUserId(c), &payload); err != nil {
|
|
|
|
|
|
c.JSON(http.StatusInternalServerError, responses.InternalServerError{Error: err.Error()})
|
|
|
|
|
|
logErr(controllerLogHeader, err)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
c.Status(http.StatusOK)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// getMerchLabels godoc
|
|
|
|
|
|
//
|
|
|
|
|
|
// @Summary Получить метки товара по его uuid
|
|
|
|
|
|
// @Description Получить метки товара по его uuid
|
|
|
|
|
|
// @Tags Merch labels
|
|
|
|
|
|
// @Security BearerAuth
|
|
|
|
|
|
// @Produce json
|
|
|
|
|
|
// @Param uuid path string true "label uuid"
|
|
|
|
|
|
// @Success 200
|
|
|
|
|
|
// @Failure 400 {object} responses.BadRequest
|
|
|
|
|
|
// @Failure 401 {object} responses.Unauthorized
|
|
|
|
|
|
// @Failure 500 {object} responses.InternalServerError
|
|
|
|
|
|
// @Router /merch/labels/{uuid} [get]
|
|
|
|
|
|
func (co *controller) getMerchLabels(c *gin.Context) {
|
|
|
|
|
|
merchUuid := c.Param("uuid")
|
|
|
|
|
|
if merchUuid == "" {
|
|
|
|
|
|
e := errors.New("MerchUuid is empty")
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, responses.BadRequest{Error: e.Error()})
|
|
|
|
|
|
logErr(controllerLogHeader, e)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
response, err := co.service.getMerchLabels(c, getUserId(c), merchUuid)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
c.JSON(http.StatusInternalServerError, responses.InternalServerError{Error: err.Error()})
|
|
|
|
|
|
logErr(controllerLogHeader, err)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
c.JSON(http.StatusOK, response)
|
|
|
|
|
|
}
|