initial commit
This commit is contained in:
412
internal/database/geospatial.sql.go
Normal file
412
internal/database/geospatial.sql.go
Normal file
@@ -0,0 +1,412 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// source: geospatial.sql
|
||||
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const CountRequestsNearby = `-- name: CountRequestsNearby :one
|
||||
|
||||
SELECT COUNT(*) FROM requests r
|
||||
WHERE r.deleted_at IS NULL
|
||||
AND r.status = $3
|
||||
AND ST_DWithin(
|
||||
r.location,
|
||||
ST_SetSRID(ST_MakePoint($1, $2), 4326)::geography,
|
||||
$4
|
||||
)
|
||||
`
|
||||
|
||||
type CountRequestsNearbyParams struct {
|
||||
StMakepoint interface{} `json:"st_makepoint"`
|
||||
StMakepoint_2 interface{} `json:"st_makepoint_2"`
|
||||
Status NullRequestStatus `json:"status"`
|
||||
StDwithin interface{} `json:"st_dwithin"`
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Подсчет заявок поблизости
|
||||
// ============================================================================
|
||||
func (q *Queries) CountRequestsNearby(ctx context.Context, arg CountRequestsNearbyParams) (int64, error) {
|
||||
row := q.db.QueryRow(ctx, CountRequestsNearby,
|
||||
arg.StMakepoint,
|
||||
arg.StMakepoint_2,
|
||||
arg.Status,
|
||||
arg.StDwithin,
|
||||
)
|
||||
var count int64
|
||||
err := row.Scan(&count)
|
||||
return count, err
|
||||
}
|
||||
|
||||
const FindNearestRequestsForVolunteer = `-- name: FindNearestRequestsForVolunteer :many
|
||||
|
||||
SELECT
|
||||
r.id,
|
||||
r.title,
|
||||
r.description,
|
||||
r.urgency,
|
||||
r.status,
|
||||
r.created_at,
|
||||
ST_Y(r.location::geometry) as latitude,
|
||||
ST_X(r.location::geometry) as longitude,
|
||||
ST_Distance(
|
||||
r.location,
|
||||
(SELECT u.location FROM users u WHERE u.id = $1)
|
||||
) as distance_meters,
|
||||
rt.name as request_type_name,
|
||||
rt.icon as request_type_icon
|
||||
FROM requests r
|
||||
JOIN request_types rt ON rt.id = r.request_type_id
|
||||
WHERE r.deleted_at IS NULL
|
||||
AND r.status = 'approved'
|
||||
AND r.assigned_volunteer_id IS NULL
|
||||
AND ST_DWithin(
|
||||
r.location,
|
||||
(SELECT u.location FROM users u WHERE u.id = $1),
|
||||
$2
|
||||
)
|
||||
ORDER BY
|
||||
CASE r.urgency
|
||||
WHEN 'urgent' THEN 1
|
||||
WHEN 'high' THEN 2
|
||||
WHEN 'medium' THEN 3
|
||||
ELSE 4
|
||||
END,
|
||||
distance_meters
|
||||
LIMIT $3
|
||||
`
|
||||
|
||||
type FindNearestRequestsForVolunteerParams struct {
|
||||
ID int64 `json:"id"`
|
||||
StDwithin interface{} `json:"st_dwithin"`
|
||||
Limit int32 `json:"limit"`
|
||||
}
|
||||
|
||||
type FindNearestRequestsForVolunteerRow struct {
|
||||
ID int64 `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Urgency pgtype.Text `json:"urgency"`
|
||||
Status NullRequestStatus `json:"status"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
Latitude interface{} `json:"latitude"`
|
||||
Longitude interface{} `json:"longitude"`
|
||||
DistanceMeters interface{} `json:"distance_meters"`
|
||||
RequestTypeName string `json:"request_type_name"`
|
||||
RequestTypeIcon pgtype.Text `json:"request_type_icon"`
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Поиск ближайших заявок для волонтера
|
||||
// ============================================================================
|
||||
func (q *Queries) FindNearestRequestsForVolunteer(ctx context.Context, arg FindNearestRequestsForVolunteerParams) ([]FindNearestRequestsForVolunteerRow, error) {
|
||||
rows, err := q.db.Query(ctx, FindNearestRequestsForVolunteer, arg.ID, arg.StDwithin, arg.Limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []FindNearestRequestsForVolunteerRow{}
|
||||
for rows.Next() {
|
||||
var i FindNearestRequestsForVolunteerRow
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Title,
|
||||
&i.Description,
|
||||
&i.Urgency,
|
||||
&i.Status,
|
||||
&i.CreatedAt,
|
||||
&i.Latitude,
|
||||
&i.Longitude,
|
||||
&i.DistanceMeters,
|
||||
&i.RequestTypeName,
|
||||
&i.RequestTypeIcon,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const FindRequestsInBounds = `-- name: FindRequestsInBounds :many
|
||||
|
||||
SELECT
|
||||
r.id,
|
||||
r.title,
|
||||
r.urgency,
|
||||
r.status,
|
||||
r.created_at,
|
||||
ST_Y(r.location::geometry) as latitude,
|
||||
ST_X(r.location::geometry) as longitude,
|
||||
rt.icon as request_type_icon,
|
||||
rt.name as request_type_name
|
||||
FROM requests r
|
||||
JOIN request_types rt ON rt.id = r.request_type_id
|
||||
WHERE r.deleted_at IS NULL
|
||||
AND r.status::text = ANY($1::text[])
|
||||
AND ST_Within(
|
||||
r.location::geometry,
|
||||
ST_MakeEnvelope($2, $3, $4, $5, 4326)
|
||||
)
|
||||
ORDER BY r.created_at DESC
|
||||
LIMIT 200
|
||||
`
|
||||
|
||||
type FindRequestsInBoundsParams struct {
|
||||
Column1 []string `json:"column_1"`
|
||||
StMakeenvelope interface{} `json:"st_makeenvelope"`
|
||||
StMakeenvelope_2 interface{} `json:"st_makeenvelope_2"`
|
||||
StMakeenvelope_3 interface{} `json:"st_makeenvelope_3"`
|
||||
StMakeenvelope_4 interface{} `json:"st_makeenvelope_4"`
|
||||
}
|
||||
|
||||
type FindRequestsInBoundsRow struct {
|
||||
ID int64 `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Urgency pgtype.Text `json:"urgency"`
|
||||
Status NullRequestStatus `json:"status"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
Latitude interface{} `json:"latitude"`
|
||||
Longitude interface{} `json:"longitude"`
|
||||
RequestTypeIcon pgtype.Text `json:"request_type_icon"`
|
||||
RequestTypeName string `json:"request_type_name"`
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Поиск заявок в прямоугольной области (для карты)
|
||||
// ============================================================================
|
||||
func (q *Queries) FindRequestsInBounds(ctx context.Context, arg FindRequestsInBoundsParams) ([]FindRequestsInBoundsRow, error) {
|
||||
rows, err := q.db.Query(ctx, FindRequestsInBounds,
|
||||
arg.Column1,
|
||||
arg.StMakeenvelope,
|
||||
arg.StMakeenvelope_2,
|
||||
arg.StMakeenvelope_3,
|
||||
arg.StMakeenvelope_4,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []FindRequestsInBoundsRow{}
|
||||
for rows.Next() {
|
||||
var i FindRequestsInBoundsRow
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Title,
|
||||
&i.Urgency,
|
||||
&i.Status,
|
||||
&i.CreatedAt,
|
||||
&i.Latitude,
|
||||
&i.Longitude,
|
||||
&i.RequestTypeIcon,
|
||||
&i.RequestTypeName,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const FindRequestsNearby = `-- name: FindRequestsNearby :many
|
||||
|
||||
|
||||
SELECT
|
||||
r.id,
|
||||
r.title,
|
||||
r.description,
|
||||
r.address,
|
||||
r.city,
|
||||
r.urgency,
|
||||
r.status,
|
||||
r.created_at,
|
||||
r.desired_completion_date,
|
||||
ST_Y(r.location::geometry) as latitude,
|
||||
ST_X(r.location::geometry) as longitude,
|
||||
ST_Distance(
|
||||
r.location,
|
||||
ST_SetSRID(ST_MakePoint($1, $2), 4326)::geography
|
||||
) as distance_meters,
|
||||
rt.name as request_type_name,
|
||||
rt.icon as request_type_icon,
|
||||
(u.first_name || ' ' || u.last_name) as requester_name
|
||||
FROM requests r
|
||||
JOIN request_types rt ON rt.id = r.request_type_id
|
||||
JOIN users u ON u.id = r.requester_id
|
||||
WHERE r.deleted_at IS NULL
|
||||
AND r.status::text = ANY($3::text[])
|
||||
AND ST_DWithin(
|
||||
r.location,
|
||||
ST_SetSRID(ST_MakePoint($1, $2), 4326)::geography,
|
||||
$4
|
||||
)
|
||||
ORDER BY distance_meters
|
||||
LIMIT $5 OFFSET $6
|
||||
`
|
||||
|
||||
type FindRequestsNearbyParams struct {
|
||||
StMakepoint interface{} `json:"st_makepoint"`
|
||||
StMakepoint_2 interface{} `json:"st_makepoint_2"`
|
||||
Column3 []string `json:"column_3"`
|
||||
StDwithin interface{} `json:"st_dwithin"`
|
||||
Limit int32 `json:"limit"`
|
||||
Offset int32 `json:"offset"`
|
||||
}
|
||||
|
||||
type FindRequestsNearbyRow struct {
|
||||
ID int64 `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Address string `json:"address"`
|
||||
City pgtype.Text `json:"city"`
|
||||
Urgency pgtype.Text `json:"urgency"`
|
||||
Status NullRequestStatus `json:"status"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
DesiredCompletionDate pgtype.Timestamptz `json:"desired_completion_date"`
|
||||
Latitude interface{} `json:"latitude"`
|
||||
Longitude interface{} `json:"longitude"`
|
||||
DistanceMeters interface{} `json:"distance_meters"`
|
||||
RequestTypeName string `json:"request_type_name"`
|
||||
RequestTypeIcon pgtype.Text `json:"request_type_icon"`
|
||||
RequesterName interface{} `json:"requester_name"`
|
||||
}
|
||||
|
||||
// Фаза 2B: Геопространственные запросы (ВЫСОКИЙ ПРИОРИТЕТ)
|
||||
// PostGIS запросы для поиска заявок по геолокации
|
||||
// ============================================================================
|
||||
// Поиск заявок рядом с точкой
|
||||
// ============================================================================
|
||||
func (q *Queries) FindRequestsNearby(ctx context.Context, arg FindRequestsNearbyParams) ([]FindRequestsNearbyRow, error) {
|
||||
rows, err := q.db.Query(ctx, FindRequestsNearby,
|
||||
arg.StMakepoint,
|
||||
arg.StMakepoint_2,
|
||||
arg.Column3,
|
||||
arg.StDwithin,
|
||||
arg.Limit,
|
||||
arg.Offset,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []FindRequestsNearbyRow{}
|
||||
for rows.Next() {
|
||||
var i FindRequestsNearbyRow
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Title,
|
||||
&i.Description,
|
||||
&i.Address,
|
||||
&i.City,
|
||||
&i.Urgency,
|
||||
&i.Status,
|
||||
&i.CreatedAt,
|
||||
&i.DesiredCompletionDate,
|
||||
&i.Latitude,
|
||||
&i.Longitude,
|
||||
&i.DistanceMeters,
|
||||
&i.RequestTypeName,
|
||||
&i.RequestTypeIcon,
|
||||
&i.RequesterName,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const FindVolunteersNearRequest = `-- name: FindVolunteersNearRequest :many
|
||||
|
||||
SELECT
|
||||
u.id,
|
||||
(u.first_name || ' ' || u.last_name) as full_name,
|
||||
u.avatar_url,
|
||||
u.volunteer_rating,
|
||||
u.completed_requests_count,
|
||||
ST_Y(u.location::geometry) as latitude,
|
||||
ST_X(u.location::geometry) as longitude,
|
||||
ST_Distance(
|
||||
u.location,
|
||||
(SELECT req.location FROM requests req WHERE req.id = $1)
|
||||
) as distance_meters
|
||||
FROM users u
|
||||
JOIN user_roles ur ON ur.user_id = u.id
|
||||
JOIN roles r ON r.id = ur.role_id
|
||||
WHERE r.name = 'volunteer'
|
||||
AND u.deleted_at IS NULL
|
||||
AND u.is_blocked = FALSE
|
||||
AND u.location IS NOT NULL
|
||||
AND ST_DWithin(
|
||||
u.location,
|
||||
(SELECT req.location FROM requests req WHERE req.id = $1),
|
||||
$2
|
||||
)
|
||||
ORDER BY distance_meters
|
||||
LIMIT $3
|
||||
`
|
||||
|
||||
type FindVolunteersNearRequestParams struct {
|
||||
ID int64 `json:"id"`
|
||||
StDwithin interface{} `json:"st_dwithin"`
|
||||
Limit int32 `json:"limit"`
|
||||
}
|
||||
|
||||
type FindVolunteersNearRequestRow struct {
|
||||
ID int64 `json:"id"`
|
||||
FullName interface{} `json:"full_name"`
|
||||
AvatarUrl pgtype.Text `json:"avatar_url"`
|
||||
VolunteerRating pgtype.Numeric `json:"volunteer_rating"`
|
||||
CompletedRequestsCount pgtype.Int4 `json:"completed_requests_count"`
|
||||
Latitude interface{} `json:"latitude"`
|
||||
Longitude interface{} `json:"longitude"`
|
||||
DistanceMeters interface{} `json:"distance_meters"`
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Поиск волонтеров рядом с заявкой
|
||||
// ============================================================================
|
||||
func (q *Queries) FindVolunteersNearRequest(ctx context.Context, arg FindVolunteersNearRequestParams) ([]FindVolunteersNearRequestRow, error) {
|
||||
rows, err := q.db.Query(ctx, FindVolunteersNearRequest, arg.ID, arg.StDwithin, arg.Limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []FindVolunteersNearRequestRow{}
|
||||
for rows.Next() {
|
||||
var i FindVolunteersNearRequestRow
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.FullName,
|
||||
&i.AvatarUrl,
|
||||
&i.VolunteerRating,
|
||||
&i.CompletedRequestsCount,
|
||||
&i.Latitude,
|
||||
&i.Longitude,
|
||||
&i.DistanceMeters,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
Reference in New Issue
Block a user