- 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>
68 lines
1.9 KiB
Go
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"`
|
|
}
|