Add Customer Discovery
This commit is contained in:
@@ -156,3 +156,119 @@ func (r *SiteRepository) Count(ctx mycontext.Context, req entity.SiteSearch) (*e
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func (r *SiteRepository) GetNearestSites(ctx context.Context, latitude, longitude, radius float64) ([]entity.SiteProductInfo, error) {
|
||||
const limit = 5
|
||||
var siteProducts []entity.SiteProductInfo
|
||||
|
||||
distanceQuery := `
|
||||
(6371 * acos(cos(radians(?)) * cos(radians(latitude)) * cos(radians(longitude) - radians(?)) + sin(radians(?)) * sin(radians(latitude))))
|
||||
`
|
||||
|
||||
// Primary query for sites within the radius
|
||||
err := r.db.WithContext(ctx).Raw(`
|
||||
SELECT s.id AS site_id, s.name AS site_name, s.region, s.regency, s.partner_id, s.image, s.address, s.location_link, s.description,
|
||||
s.highlight, s.contact_person, s.tnc, s.additional_info, s.status, s.is_season_ticket, s.is_discount_active,
|
||||
s.latitude, s.longitude, s.created_at, s.updated_at,
|
||||
`+distanceQuery+` AS distance,
|
||||
p.id AS product_id, p.name AS product_name, p.type AS product_type, p.price AS product_price,
|
||||
p.is_weekend_ticket, p.is_season_ticket, p.status AS product_status, p.description AS product_description
|
||||
FROM sites s
|
||||
LEFT JOIN (
|
||||
SELECT *, ROW_NUMBER() OVER (PARTITION BY site_id ORDER BY price ASC) AS rn
|
||||
FROM products
|
||||
) p ON s.id = p.site_id AND p.rn = 1
|
||||
WHERE `+distanceQuery+` < ?
|
||||
ORDER BY distance
|
||||
LIMIT ?`,
|
||||
latitude, longitude, latitude, latitude, longitude, latitude, radius, limit).Scan(&siteProducts).Error
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If fewer than 5 sites found, fetch additional ones regardless of distance
|
||||
if len(siteProducts) < limit {
|
||||
additionalLimit := limit - len(siteProducts)
|
||||
err = r.db.WithContext(ctx).Raw(`
|
||||
SELECT s.id AS site_id, s.name AS site_name, s.region, s.regency, s.partner_id, s.image, s.address, s.location_link, s.description,
|
||||
s.highlight, s.contact_person, s.tnc, s.additional_info, s.status, s.is_season_ticket, s.is_discount_active,
|
||||
s.latitude, s.longitude, s.created_at, s.updated_at,
|
||||
`+distanceQuery+` AS distance,
|
||||
p.id AS product_id, p.name AS product_name, p.type AS product_type, p.price AS product_price,
|
||||
p.is_weekend_ticket, p.is_season_ticket, p.status AS product_status, p.description AS product_description
|
||||
FROM sites s
|
||||
LEFT JOIN (
|
||||
SELECT *, ROW_NUMBER() OVER (PARTITION BY site_id ORDER BY price ASC) AS rn
|
||||
FROM products
|
||||
) p ON s.id = p.site_id AND p.rn = 1
|
||||
ORDER BY distance
|
||||
LIMIT ?`,
|
||||
latitude, longitude, latitude, additionalLimit).Scan(&siteProducts).Error
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return siteProducts, nil
|
||||
}
|
||||
|
||||
func (r *SiteRepository) SearchSites(ctx context.Context, search *entity.DiscoverySearch) ([]entity.SiteProductInfo, int64, error) {
|
||||
var siteProducts []entity.SiteProductInfo
|
||||
var total int64
|
||||
|
||||
// Adding wildcard for partial matching
|
||||
searchName := "%" + search.Name + "%"
|
||||
|
||||
// Base conditions and parameters
|
||||
conditions := "s.name ILIKE ?"
|
||||
params := []interface{}{searchName}
|
||||
|
||||
// Add region filtering if region is provided
|
||||
if search.Region != "" {
|
||||
conditions += " AND s.region = ?"
|
||||
params = append(params, search.Region)
|
||||
}
|
||||
|
||||
if search.Discover != "" {
|
||||
conditions += " AND s.address ILIKE ?"
|
||||
params = append(params, "%"+search.Discover+"%")
|
||||
}
|
||||
|
||||
// Count query to get the total number of matching records
|
||||
countQuery := `
|
||||
SELECT COUNT(*)
|
||||
FROM sites s
|
||||
WHERE ` + conditions
|
||||
err := r.db.WithContext(ctx).Raw(countQuery, params...).Scan(&total).Error
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
// Add limit and offset for the data query
|
||||
dataParams := append(params, search.Limit, search.Offset)
|
||||
|
||||
// Primary query for sites matching name and region, with pagination
|
||||
dataQuery := `
|
||||
SELECT s.id AS site_id, s.name AS site_name, s.region, s.regency, s.partner_id, s.image, s.address, s.location_link, s.description,
|
||||
s.highlight, s.contact_person, s.tnc, s.additional_info, s.status, s.is_season_ticket, s.is_discount_active,
|
||||
s.latitude, s.longitude, s.created_at, s.updated_at,
|
||||
p.id AS product_id, p.name AS product_name, p.type AS product_type, p.price AS product_price,
|
||||
p.is_weekend_ticket, p.is_season_ticket, p.status AS product_status, p.description AS product_description
|
||||
FROM sites s
|
||||
LEFT JOIN (
|
||||
SELECT *, ROW_NUMBER() OVER (PARTITION BY site_id ORDER BY price ASC) AS rn
|
||||
FROM products
|
||||
) p ON s.id = p.site_id AND p.rn = 1
|
||||
WHERE ` + conditions + `
|
||||
ORDER BY s.name
|
||||
LIMIT ? OFFSET ?
|
||||
`
|
||||
err = r.db.WithContext(ctx).Raw(dataQuery, dataParams...).Scan(&siteProducts).Error
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return siteProducts, total, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user