|
@@ -3,6 +3,7 @@ package repository
|
|
|
|
|
|
|
|
import (
|
|
import (
|
|
|
"context"
|
|
"context"
|
|
|
|
|
+ "encoding/json"
|
|
|
"fmt"
|
|
"fmt"
|
|
|
|
|
|
|
|
"github.com/jackc/pgx/v5"
|
|
"github.com/jackc/pgx/v5"
|
|
@@ -59,6 +60,54 @@ func (r *PlaceRepo) GetByID(ctx context.Context, id string) (*models.Place, erro
|
|
|
return scanPlace(row)
|
|
return scanPlace(row)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+func (r *PlaceRepo) GetByIDWithDetails(ctx context.Context, id string) (*models.Place, error) {
|
|
|
|
|
+ query := `
|
|
|
|
|
+ SELECT p.id, p.type, p.owner_id, p.title, p.description, p.address,
|
|
|
|
|
+ ST_Y(p.coordinates::geometry), ST_X(p.coordinates::geometry),
|
|
|
|
|
+ p.cover_image, p.access_info, p.status, p.moderation_comment,
|
|
|
|
|
+ p.rating, p.reviews_count, p.hourly_rate, p.currency, p.min_hours, p.booking_url,
|
|
|
|
|
+ p.created_at, p.updated_at, p.published_at, p.deleted_at,
|
|
|
|
|
+ COALESCE(json_agg(DISTINCT jsonb_build_object('id', t.id, 'name', t.name, 'category', t.category))
|
|
|
|
|
+ FILTER (WHERE t.id IS NOT NULL), '[]'::jsonb) as tags,
|
|
|
|
|
+ COALESCE(json_agg(DISTINCT jsonb_build_object('id', f.id, 'name', f.name, 'category', f.category, 'icon', f.icon))
|
|
|
|
|
+ FILTER (WHERE f.id IS NOT NULL), '[]'::jsonb) as features
|
|
|
|
|
+ FROM places p
|
|
|
|
|
+ LEFT JOIN place_tags pt ON pt.place_id = p.id
|
|
|
|
|
+ LEFT JOIN tags t ON t.id = pt.tag_id
|
|
|
|
|
+ LEFT JOIN place_features pf ON pf.place_id = p.id
|
|
|
|
|
+ LEFT JOIN features f ON f.id = pf.feature_id
|
|
|
|
|
+ WHERE p.id = $1 AND p.deleted_at IS NULL
|
|
|
|
|
+ GROUP BY p.id`
|
|
|
|
|
+
|
|
|
|
|
+ row := r.pool.QueryRow(ctx, query, id)
|
|
|
|
|
+
|
|
|
|
|
+ var p models.Place
|
|
|
|
|
+ var tagsJSON, featuresJSON []byte
|
|
|
|
|
+ err := row.Scan(
|
|
|
|
|
+ &p.ID, &p.Type, &p.OwnerID, &p.Title, &p.Description, &p.Address,
|
|
|
|
|
+ &p.Lat, &p.Lng,
|
|
|
|
|
+ &p.CoverImage, &p.AccessInfo, &p.Status, &p.ModerationComment,
|
|
|
|
|
+ &p.Rating, &p.ReviewsCount, &p.HourlyRate, &p.Currency, &p.MinHours, &p.BookingURL,
|
|
|
|
|
+ &p.CreatedAt, &p.UpdatedAt, &p.PublishedAt, &p.DeletedAt,
|
|
|
|
|
+ &tagsJSON, &featuresJSON,
|
|
|
|
|
+ )
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ if err == pgx.ErrNoRows {
|
|
|
|
|
+ return nil, nil
|
|
|
|
|
+ }
|
|
|
|
|
+ return nil, fmt.Errorf("get place with details: %w", err)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if err := json.Unmarshal(tagsJSON, &p.Tags); err != nil {
|
|
|
|
|
+ return nil, fmt.Errorf("unmarshal tags: %w", err)
|
|
|
|
|
+ }
|
|
|
|
|
+ if err := json.Unmarshal(featuresJSON, &p.Features); err != nil {
|
|
|
|
|
+ return nil, fmt.Errorf("unmarshal features: %w", err)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return &p, nil
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func (r *PlaceRepo) List(ctx context.Context, filter models.PlaceFilter) ([]*models.Place, error) {
|
|
func (r *PlaceRepo) List(ctx context.Context, filter models.PlaceFilter) ([]*models.Place, error) {
|
|
|
q := `SELECT p.id, p.type, p.owner_id, p.title, p.description, p.address,
|
|
q := `SELECT p.id, p.type, p.owner_id, p.title, p.description, p.address,
|
|
|
ST_Y(p.coordinates::geometry), ST_X(p.coordinates::geometry),
|
|
ST_Y(p.coordinates::geometry), ST_X(p.coordinates::geometry),
|