saveinmed/backend/internal/usecase/product_usecase.go
caio-machado-dev bf85072bff chore: remove legacy services and restructure monorepo
- remove backend-old (Medusa), saveinmed-frontend (Next.js/Appwrite) and marketplace dirs
- split Go usecases by domain and move notifications/payments to infrastructure
- reorganize frontend pages into auth, dashboard and marketplace modules
- add Makefile, docker-compose.yml and architecture docs
2026-02-25 16:51:34 -03:00

138 lines
4 KiB
Go

package usecase
import (
"context"
"math"
"strings"
"github.com/gofrs/uuid/v5"
"github.com/saveinmed/backend-go/internal/domain"
)
// RegisterProduct generates an ID and persists a new product.
func (s *Service) RegisterProduct(ctx context.Context, product *domain.Product) error {
product.ID = uuid.Must(uuid.NewV7())
return s.repo.CreateProduct(ctx, product)
}
// ListProducts returns a paginated list of products matching the filter.
func (s *Service) ListProducts(ctx context.Context, filter domain.ProductFilter, page, pageSize int) (*domain.ProductPage, error) {
if pageSize <= 0 {
pageSize = 20
}
if page <= 0 {
page = 1
}
filter.Limit = pageSize
filter.Offset = (page - 1) * pageSize
products, total, err := s.repo.ListProducts(ctx, filter)
if err != nil {
return nil, err
}
return &domain.ProductPage{Products: products, Total: total, Page: page, PageSize: pageSize}, nil
}
// SearchProducts returns products with distance, ordered by expiration date.
// Seller info is anonymised until checkout.
func (s *Service) SearchProducts(ctx context.Context, filter domain.ProductSearchFilter, page, pageSize int) (*domain.ProductSearchPage, error) {
if pageSize <= 0 {
pageSize = 20
}
if page <= 0 {
page = 1
}
filter.Limit = pageSize
filter.Offset = (page - 1) * pageSize
products, total, err := s.repo.SearchProducts(ctx, filter)
if err != nil {
return nil, err
}
return &domain.ProductSearchPage{Products: products, Total: total, Page: page, PageSize: pageSize}, nil
}
// ListRecords provides advanced search for marketplace listings.
func (s *Service) ListRecords(ctx context.Context, req domain.SearchRequest) (*domain.PaginationResponse[domain.Product], error) {
page := req.Page
pageSize := req.PageSize
if pageSize <= 0 {
pageSize = 20
}
if page <= 0 {
page = 1
}
sortBy := strings.TrimSpace(req.SortBy)
if sortBy == "" {
sortBy = "updated_at"
}
sortOrder := strings.ToLower(strings.TrimSpace(req.SortOrder))
if sortOrder == "" {
sortOrder = "desc"
}
filter := domain.RecordSearchFilter{
Query: strings.TrimSpace(req.Query),
SortBy: sortBy,
SortOrder: sortOrder,
CreatedAfter: req.CreatedAfter,
CreatedBefore: req.CreatedBefore,
Limit: pageSize,
Offset: (page - 1) * pageSize,
}
items, total, err := s.repo.ListRecords(ctx, filter)
if err != nil {
return nil, err
}
totalPages := int(math.Ceil(float64(total) / float64(pageSize)))
return &domain.PaginationResponse[domain.Product]{
Items: items,
TotalCount: total,
CurrentPage: page,
TotalPages: totalPages,
}, nil
}
// GetProduct retrieves a product by ID.
func (s *Service) GetProduct(ctx context.Context, id uuid.UUID) (*domain.Product, error) {
return s.repo.GetProduct(ctx, id)
}
// UpdateProduct persists changes to a product.
func (s *Service) UpdateProduct(ctx context.Context, product *domain.Product) error {
return s.repo.UpdateProduct(ctx, product)
}
// DeleteProduct removes a product by ID.
func (s *Service) DeleteProduct(ctx context.Context, id uuid.UUID) error {
return s.repo.DeleteProduct(ctx, id)
}
// ListInventory returns a paginated list of inventory items for a seller.
func (s *Service) ListInventory(ctx context.Context, filter domain.InventoryFilter, page, pageSize int) (*domain.InventoryPage, error) {
if pageSize <= 0 {
pageSize = 20
}
if page <= 0 {
page = 1
}
filter.Limit = pageSize
filter.Offset = (page - 1) * pageSize
items, total, err := s.repo.ListInventory(ctx, filter)
if err != nil {
return nil, err
}
return &domain.InventoryPage{Items: items, Total: total, Page: page, PageSize: pageSize}, nil
}
// AdjustInventory increments or decrements the stock of a product.
func (s *Service) AdjustInventory(ctx context.Context, productID uuid.UUID, delta int64, reason string) (*domain.InventoryItem, error) {
return s.repo.AdjustInventory(ctx, productID, delta, reason)
}
// ListManufacturers returns all distinct manufacturer names in the catalogue.
func (s *Service) ListManufacturers(ctx context.Context) ([]string, error) {
return s.repo.ListManufacturers(ctx)
}