added get merch prices method

This commit is contained in:
nquidox 2025-09-24 20:28:36 +03:00
parent ecf00fef22
commit ba78dd9772
5 changed files with 163 additions and 8 deletions

View file

@ -6,6 +6,7 @@ import (
"merch-parser-api/internal/interfaces"
"merch-parser-api/pkg/responses"
"net/http"
"strings"
)
type controller struct {
@ -29,6 +30,9 @@ func (h *Handler) RegisterRoutes(r *gin.RouterGroup, authMW gin.HandlerFunc, ref
merchGroup.PUT("/", h.controller.updateMerch)
merchGroup.DELETE("/:uuid", h.controller.deleteMerch)
chartsGroup := r.Group("/prices", authMW)
chartsGroup.GET("", h.controller.getChartsPrices)
}
// @Summary Добавить новый мерч
@ -103,9 +107,9 @@ func (co *controller) getSingleMerch(c *gin.Context) {
// @Description Получить все записи мерча
// @Tags Merch
// @Security BearerAuth
// @Success 200 {array} ListResponse
// @Failure 400 {object} responses.ErrorResponse400
// @Failure 500 {object} responses.ErrorResponse500
// @Success 200 {array} ListResponse
// @Failure 400 {object} responses.ErrorResponse400
// @Failure 500 {object} responses.ErrorResponse500
// @Router /merch/ [get]
func (co *controller) getAllMerch(c *gin.Context) {
userUuid, err := co.utils.GetUserUuidFromContext(c)
@ -187,3 +191,32 @@ func (co *controller) deleteMerch(c *gin.Context) {
c.Status(http.StatusOK)
}
// @Summary Получить цены мерча за период
// @Description Получить цены мерча за период
// @Tags Merch
// @Security BearerAuth
// @Param days query string false "merch_uuid"
// @Success 200 {array} PricesResponse
// @Failure 400 {object} responses.ErrorResponse400
// @Failure 500 {object} responses.ErrorResponse500
// @Router /prices [get]
func (co *controller) getChartsPrices(c *gin.Context) {
daysQuery := strings.ToLower(c.DefaultQuery("days", ""))
userUuid, err := co.utils.GetUserUuidFromContext(c)
if err != nil {
c.JSON(http.StatusInternalServerError, responses.ErrorResponse500{Error: err.Error()})
log.WithError(err).Error("Merch | Failed to get user uuid from context")
return
}
response, err := co.service.getPrices(userUuid, daysQuery)
if err != nil {
c.JSON(http.StatusBadRequest, responses.ErrorResponse500{Error: err.Error()})
log.WithError(err).Error("Merch | Failed to get single merch")
return
}
c.JSON(http.StatusOK, response)
}

View file

@ -1,5 +1,7 @@
package merch
import "time"
type merchBundle struct {
Merch *Merch
Surugaya *Surugaya
@ -30,3 +32,19 @@ type ListResponse struct {
MerchUuid string `json:"merch_uuid"`
Name string `json:"name"`
}
type PriceEntry struct {
CreatedAt time.Time `json:"created_at"`
Value int `json:"value"`
}
type OriginWithPrices struct {
Origin Origin `json:"origin"`
Prices []PriceEntry
}
type PricesResponse struct {
Name string `json:"name"`
MerchUuid string `json:"merch_uuid"`
Origins []OriginWithPrices `json:"origins"`
}

View file

@ -7,11 +7,11 @@ import (
type Merch struct {
Id uint `json:"id" gorm:"primary_key"`
CreatedAt time.Time `json:"created_at" gorm:"created_at"`
UpdatedAt sql.NullTime `json:"updated_at" gorm:"updated_at"`
DeletedAt sql.NullTime `json:"deleted_at" gorm:"deleted_at"`
MerchUuid string `json:"merch_uuid" gorm:"type:varchar(36);unique_index"`
UserUuid string `json:"user_uuid" gorm:"type:varchar(36)"`
CreatedAt time.Time `json:"created_at" gorm:"column:created_at"`
UpdatedAt sql.NullTime `json:"updated_at" gorm:"column:updated_at"`
DeletedAt sql.NullTime `json:"deleted_at" gorm:"column:deleted_at"`
MerchUuid string `json:"merch_uuid" gorm:"column:merch_uuid"`
UserUuid string `json:"user_uuid" gorm:"column:user_uuid"`
Name string `json:"name" gorm:"column:name"`
}
@ -41,3 +41,13 @@ type Mandarake struct {
func (Mandarake) TableName() string {
return "origin_mandarake"
}
type Price struct {
Id uint `json:"id" gorm:"primary_key"`
CreatedAt time.Time `json:"created_at" gorm:"column:created_at"`
UpdatedAt sql.NullTime `json:"updated_at" gorm:"column:updated_at"`
DeletedAt sql.NullTime `json:"deleted_at" gorm:"column:deleted_at"`
MerchUuid string `json:"merch_uuid" gorm:"column:merch_uuid"`
Price int `json:"price" gorm:"column:price"`
Origin Origin `json:"origin" gorm:"column:origin"`
}

View file

@ -26,6 +26,14 @@ type repository interface {
updateMerch(payload MerchDTO, userUuid string) error
deleteMerch(userUuid, merchUuid string) error
getAllUserMerch(userUuid string) ([]Merch, error)
prices
}
type prices interface {
getPricesWithDays(userUuid string, period time.Time) ([]Price, error)
}
func (r *Repo) addMerch(bundle merchBundle) error {
@ -161,3 +169,28 @@ func (r *Repo) deleteMerch(userUuid, merchUuid string) error {
return nil
}
func (r *Repo) getAllUserMerch(userUuid string) (merchList []Merch, err error) {
err = r.db.Model(&Merch{}).Where("user_uuid = ?", userUuid).Find(&merchList).Error
if err != nil {
return nil, err
}
return merchList, nil
}
func (r *Repo) getPricesWithDays(userUuid string, period time.Time) (prices []Price, err error) {
err = r.db.Raw(`
SELECT p.created_at, p.merch_uuid, p.price, p.origin
FROM prices AS p
JOIN merch AS m ON m.merch_uuid = p.merch_uuid
where m.user_uuid = ?
and p.created_at > ?
and p.deleted_at IS NULL
order by p.created_at desc
`, userUuid, period).Scan(&prices).Error
if err != nil {
return nil, err
}
return prices, nil
}

View file

@ -4,6 +4,7 @@ import (
"database/sql"
"errors"
"github.com/google/uuid"
"strconv"
"time"
)
@ -77,3 +78,63 @@ func (s *service) updateMerch(payload MerchDTO, userUuid string) error {
func (s *service) deleteMerch(userUuid, merchUuid string) error {
return s.repo.deleteMerch(userUuid, merchUuid)
}
func (s *service) getPrices(userUuid string, days string) ([]PricesResponse, error) {
merchList, err := s.repo.getAllUserMerch(userUuid)
if err != nil {
return nil, err
}
if len(merchList) == 0 {
return nil, errors.New("no merch found")
}
var response []PricesResponse
for _, item := range merchList {
response = append(response, PricesResponse{
MerchUuid: item.MerchUuid,
Name: item.Name,
Origins: []OriginWithPrices{},
})
}
daysInt, err := strconv.Atoi(days)
if err != nil {
daysInt = 7
}
period := time.Now().UTC().Add(-(time.Duration(daysInt) * time.Hour * 24))
pricesList, err := s.repo.getPricesWithDays(userUuid, period)
if err != nil {
return nil, err
}
pricesMap := make(map[string]map[Origin][]PriceEntry)
for _, item := range pricesList {
if _, ok := pricesMap[item.MerchUuid]; !ok {
pricesMap[item.MerchUuid] = make(map[Origin][]PriceEntry)
}
pricesMap[item.MerchUuid][item.Origin] = append(pricesMap[item.MerchUuid][item.Origin], PriceEntry{
CreatedAt: item.CreatedAt,
Value: item.Price,
})
}
for i := range response {
originSurugaya := OriginWithPrices{
Origin: surugaya,
Prices: pricesMap[response[i].MerchUuid][surugaya],
}
response[i].Origins = append(response[i].Origins, originSurugaya)
originMandarake := OriginWithPrices{
Origin: mandarake,
Prices: pricesMap[response[i].MerchUuid][mandarake],
}
response[i].Origins = append(response[i].Origins, originMandarake)
}
return response, nil
}