130 lines
3.4 KiB
Go
130 lines
3.4 KiB
Go
// Package service for service's
|
|
package service
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"errors"
|
|
"log/slog"
|
|
"math"
|
|
"steam_analyzer/internal/domain"
|
|
"steam_analyzer/internal/repository"
|
|
"steam_analyzer/internal/utils"
|
|
"steam_analyzer/internal/utils/slogutils"
|
|
"steam_analyzer/pkg/postgresql"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/jackc/pgx/v5/pgconn"
|
|
)
|
|
|
|
type ItemRepository interface {
|
|
AddItem(ctx context.Context, item domain.DBItem) error
|
|
AddItemHistory(ctx context.Context, dbItemHistory domain.DBItemHistory) error
|
|
GetItemByClassID(ctx context.Context, classID string) (*domain.SteamItem, error)
|
|
GetItemPriceHistoryByID(ctx context.Context, itemID uuid.UUID, limit int, offset int) ([]domain.ItemPriceHistory, error)
|
|
GetItemsWithLastPriceByName(ctx context.Context, name string) ([]repository.ItemWithLastPrice, error)
|
|
}
|
|
|
|
type ItemService struct {
|
|
logger *slog.Logger
|
|
|
|
itemRepo ItemRepository
|
|
}
|
|
|
|
func NewItemService(logger *slog.Logger, itemRepo ItemRepository) *ItemService {
|
|
return &ItemService{
|
|
logger: logger,
|
|
itemRepo: itemRepo,
|
|
}
|
|
}
|
|
|
|
func (s ItemService) AddItemWithHistory(ctx context.Context, item domain.SteamItem) error {
|
|
searchedItem, err := s.itemRepo.GetItemByClassID(ctx, item.ClassID)
|
|
if err != nil {
|
|
switch {
|
|
case errors.Is(err, sql.ErrNoRows):
|
|
s.logger.Info("Item is new, creating it")
|
|
default:
|
|
return err
|
|
}
|
|
}
|
|
|
|
if searchedItem != nil {
|
|
item.ID = searchedItem.ID
|
|
} else {
|
|
item.ID = uuid.New()
|
|
|
|
err = s.itemRepo.AddItem(ctx, item.ToDB())
|
|
if err != nil {
|
|
if pgErr, ok := err.(*pgconn.PgError); ok && pgErr.Code == postgresql.ErrConstraintUnique {
|
|
s.logger.Error("Error while adding item", slog.String("error", "Item already exists"))
|
|
} else {
|
|
s.logger.Error("Error while adding item", slogutils.Error(err))
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
err = s.itemRepo.AddItemHistory(ctx, item.ToDBHistory())
|
|
if err != nil {
|
|
s.logger.Error("Error while adding item history", slogutils.Error(sql.ErrNoRows))
|
|
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s ItemService) GetItemWithPriceHistoryByClassID(ctx context.Context, classID string, limit int, offset int) (*domain.SteamItem, error) {
|
|
steamItem, err := s.itemRepo.GetItemByClassID(ctx, classID)
|
|
if err != nil {
|
|
s.logger.Error("Error while getting item by class id", slogutils.Error(err))
|
|
|
|
return nil, err
|
|
}
|
|
|
|
itemPriceHistory, err := s.itemRepo.GetItemPriceHistoryByID(ctx, steamItem.ID, limit, offset)
|
|
if err != nil {
|
|
s.logger.Error("Error while getting item price history by id", slogutils.Error(err))
|
|
|
|
return nil, err
|
|
}
|
|
|
|
steamItem.History = itemPriceHistory
|
|
|
|
return steamItem, nil
|
|
}
|
|
|
|
func (s ItemService) GetAllItemsWithLastPrice(ctx context.Context, itemName string) ([]repository.ItemWithLastPrice, error) {
|
|
s.logger.Info("ItemService.GetAllItemsWithLastPrice", slog.String("item name is", itemName))
|
|
|
|
items, err := s.itemRepo.GetItemsWithLastPriceByName(ctx, itemName)
|
|
if err != nil {
|
|
s.logger.Error("Error while getting item with last price", slogutils.Error(err))
|
|
|
|
return nil, err
|
|
}
|
|
|
|
for i, item := range items {
|
|
items[i].Price = formatPrice(item.Price)
|
|
items[i].Date = formatDate(item.Date)
|
|
}
|
|
|
|
return items, nil
|
|
}
|
|
|
|
func formatPrice(price float64) float64 {
|
|
formattedPrice := price / 100 * utils.CURRENCY_RUB
|
|
formattedPrice = math.Round(formattedPrice*100) / 100
|
|
|
|
return formattedPrice
|
|
}
|
|
|
|
func formatDate(date time.Time) time.Time {
|
|
location, _ := time.LoadLocation("Europe/Moscow")
|
|
foramettedDate := date.In(location)
|
|
|
|
return foramettedDate
|
|
}
|