- 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
138 lines
4 KiB
Go
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)
|
|
}
|