- 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
131 lines
3.8 KiB
Go
131 lines
3.8 KiB
Go
package usecase
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"math"
|
|
|
|
"github.com/gofrs/uuid/v5"
|
|
|
|
"github.com/saveinmed/backend-go/internal/domain"
|
|
)
|
|
|
|
// RegisterCompany persists a new company and sets a new UUID.
|
|
func (s *Service) RegisterCompany(ctx context.Context, company *domain.Company) error {
|
|
company.ID = uuid.Must(uuid.NewV7())
|
|
return s.repo.CreateCompany(ctx, company)
|
|
}
|
|
|
|
// ListCompanies returns a paginated list of companies matching the filter.
|
|
func (s *Service) ListCompanies(ctx context.Context, filter domain.CompanyFilter, page, pageSize int) (*domain.CompanyPage, error) {
|
|
if pageSize <= 0 {
|
|
pageSize = 20
|
|
}
|
|
if page <= 0 {
|
|
page = 1
|
|
}
|
|
filter.Limit = pageSize
|
|
filter.Offset = (page - 1) * pageSize
|
|
companies, total, err := s.repo.ListCompanies(ctx, filter)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &domain.CompanyPage{Companies: companies, Total: total, Page: page, PageSize: pageSize}, nil
|
|
}
|
|
|
|
// GetCompany retrieves a company by ID.
|
|
func (s *Service) GetCompany(ctx context.Context, id uuid.UUID) (*domain.Company, error) {
|
|
return s.repo.GetCompany(ctx, id)
|
|
}
|
|
|
|
// UpdateCompany persists changes to an existing company.
|
|
func (s *Service) UpdateCompany(ctx context.Context, company *domain.Company) error {
|
|
return s.repo.UpdateCompany(ctx, company)
|
|
}
|
|
|
|
// DeleteCompany removes a company by ID.
|
|
func (s *Service) DeleteCompany(ctx context.Context, id uuid.UUID) error {
|
|
return s.repo.DeleteCompany(ctx, id)
|
|
}
|
|
|
|
// VerifyCompany marks the company account as KYC-verified.
|
|
func (s *Service) VerifyCompany(ctx context.Context, id uuid.UUID) (*domain.Company, error) {
|
|
company, err := s.repo.GetCompany(ctx, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
company.IsVerified = true
|
|
|
|
if err := s.repo.UpdateCompany(ctx, company); err != nil {
|
|
return nil, err
|
|
}
|
|
return company, nil
|
|
}
|
|
|
|
// CalculateShippingOptions returns available delivery/pickup options for a vendor,
|
|
// based on the buyer's location and cart total.
|
|
func (s *Service) CalculateShippingOptions(ctx context.Context, vendorID uuid.UUID, buyerLat, buyerLng float64, cartTotalCents int64) ([]domain.ShippingOption, error) {
|
|
company, err := s.repo.GetCompany(ctx, vendorID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if company == nil {
|
|
return nil, errors.New("vendor not found")
|
|
}
|
|
|
|
settings, err := s.repo.GetShippingSettings(ctx, vendorID)
|
|
if err != nil {
|
|
return []domain.ShippingOption{}, nil
|
|
}
|
|
if settings == nil {
|
|
return []domain.ShippingOption{}, nil
|
|
}
|
|
|
|
distance := domain.HaversineDistance(company.Latitude, company.Longitude, buyerLat, buyerLng)
|
|
var options []domain.ShippingOption
|
|
|
|
// Delivery option
|
|
if settings.Active {
|
|
if settings.MaxRadiusKm > 0 && distance <= settings.MaxRadiusKm {
|
|
variableCost := int64(math.Round(distance * float64(settings.PricePerKmCents)))
|
|
price := settings.MinFeeCents
|
|
if variableCost > price {
|
|
price = variableCost
|
|
}
|
|
if settings.FreeShippingThresholdCents != nil && *settings.FreeShippingThresholdCents > 0 && cartTotalCents >= *settings.FreeShippingThresholdCents {
|
|
price = 0
|
|
}
|
|
|
|
estMins := 30 + int(math.Round(distance*5))
|
|
|
|
options = append(options, domain.ShippingOption{
|
|
Type: domain.ShippingOptionTypeDelivery,
|
|
ValueCents: price,
|
|
EstimatedMinutes: estMins,
|
|
Description: "Entrega Própria",
|
|
DistanceKm: distance,
|
|
})
|
|
}
|
|
}
|
|
|
|
// Pickup option
|
|
if settings.PickupActive {
|
|
desc := "Retirada na loja"
|
|
if settings.PickupAddress != "" {
|
|
desc = "Retirada em: " + settings.PickupAddress
|
|
}
|
|
if settings.PickupHours != "" {
|
|
desc += " (" + settings.PickupHours + ")"
|
|
}
|
|
|
|
options = append(options, domain.ShippingOption{
|
|
Type: domain.ShippingOptionTypePickup,
|
|
ValueCents: 0,
|
|
EstimatedMinutes: 60,
|
|
Description: desc,
|
|
DistanceKm: distance,
|
|
})
|
|
}
|
|
|
|
return options, nil
|
|
}
|