saveinmed/backend/internal/domain/distance.go
Gabbriiel 90467db1ec refactor: substitui backend Medusa por backend Go e corrige testes do marketplace
- Remove backend Medusa.js (TypeScript) e substitui pelo backend Go (saveinmed-performance-core)
- Corrige testes auth.test.ts: alinha paths de API (v1/ sem barra inicial) e campo access_token
- Corrige GroupedProductCard.test.tsx: ajusta distância formatada (toFixed) e troca userEvent por fireEvent com fakeTimers
- Corrige AuthContext.test.tsx: usa vi.hoisted() para mocks e corrige parênteses no waitFor

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 04:56:37 -06:00

68 lines
1.9 KiB
Go

package domain
import (
"math"
"time"
"github.com/gofrs/uuid/v5"
)
const earthRadiusKm = 6371.0
// HaversineDistance calculates the distance in kilometers between two points
// using the Haversine formula. The result is approximate (±5km for security).
func HaversineDistance(lat1, lng1, lat2, lng2 float64) float64 {
dLat := degreesToRadians(lat2 - lat1)
dLng := degreesToRadians(lng2 - lng1)
lat1Rad := degreesToRadians(lat1)
lat2Rad := degreesToRadians(lat2)
a := math.Sin(dLat/2)*math.Sin(dLat/2) +
math.Cos(lat1Rad)*math.Cos(lat2Rad)*
math.Sin(dLng/2)*math.Sin(dLng/2)
c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a))
distance := earthRadiusKm * c
// Round to nearest km for approximate distance (security)
return math.Round(distance)
}
func degreesToRadians(degrees float64) float64 {
return degrees * math.Pi / 180
}
// ProductWithDistance extends Product with distance information for search results.
type ProductWithDistance struct {
Product
DistanceKm float64 `json:"distance_km"`
TenantCity string `json:"tenant_city,omitempty"`
TenantState string `json:"tenant_state,omitempty"`
// TenantID is hidden for anonymous browsing, revealed only at checkout
}
// ProductSearchFilter captures search constraints.
type ProductSearchFilter struct {
Search string
Category string
MinPriceCents *int64
MaxPriceCents *int64
ExpiresAfter *time.Time
ExpiresBefore *time.Time
MaxDistanceKm *float64
BuyerLat float64
BuyerLng float64
ExcludeSellerID *uuid.UUID // Exclude products from buyer's own company
Limit int
Offset int
}
// ProductSearchPage wraps search results with pagination.
type ProductSearchPage struct {
Products []ProductWithDistance `json:"products"`
Total int64 `json:"total"`
Page int `json:"page"`
PageSize int `json:"page_size"`
}