90a96b4125
- Remove api_es service, Dockerfile, all Go source files - Remove api_es from docker-compose.yml, nginx-ssl.conf, .env, Makefile - Replace nginx /api/ proxy with /api/v1/ → api_yal:8787 - Add amenity/upload domains, AuthResponse, GET /auth/me, GET /objects/my to api_yal - Rewrite easysite frontend: types, composables, and all 5 pages to use api_yal DTOs - Wire nuxt.config public.apiBase, add useObjects CRUD composable - Update docs references from api_es to api_yal
802 lines
24 KiB
Go
802 lines
24 KiB
Go
package object
|
|
|
|
import (
|
|
"api_yal/internal/domain/account"
|
|
"api_yal/internal/models"
|
|
"api_yal/internal/repository"
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type ObjectService interface {
|
|
GetObjectByID(ctx context.Context, id uint) (*ObjectResponse, error)
|
|
CreateObject(ctx context.Context, req *CreateObjectRequest) (*ObjectResponse, error)
|
|
UpdateObject(ctx context.Context, id uint, req *UpdateObjectRequest) (*ObjectResponse, error)
|
|
DeleteObject(ctx context.Context, id uint) error
|
|
ListObjects(ctx context.Context, req *ListObjectsRequest) (*ObjectListResponse, error)
|
|
GetObjectsByOwner(ctx context.Context, ownerID uint, page, pageSize int) (*ObjectListResponse, error)
|
|
GetObjectsByType(ctx context.Context, objectType string, page, pageSize int) (*ObjectListResponse, error)
|
|
SearchObjects(ctx context.Context, query string, page, pageSize int) (*ObjectListResponse, error)
|
|
GetNearbyObjects(ctx context.Context, lat, lng, radius float64, page, pageSize int) (*ObjectListResponse, error)
|
|
ToggleVerification(ctx context.Context, id uint, verified bool) error
|
|
|
|
// Feedback methods
|
|
CreateFeedback(ctx context.Context, req *CreateFeedbackRequest, ownerID uint) (*FeedbackResponse, error)
|
|
UpdateFeedback(ctx context.Context, id uint, req *UpdateFeedbackRequest, ownerID uint) (*FeedbackResponse, error)
|
|
DeleteFeedback(ctx context.Context, id uint, ownerID uint) error
|
|
GetFeedbackByID(ctx context.Context, id uint) (*FeedbackResponse, error)
|
|
GetFeedbacksByObject(ctx context.Context, objectID uint, page, pageSize int) (*FeedbackListResponse, error)
|
|
|
|
// Rating methods
|
|
CreateRatingVote(ctx context.Context, req *CreateRatingVoteRequest, voterID uint) (*RatingVoteResponse, error)
|
|
GetObjectRating(ctx context.Context, objectID uint, platform models.PlatformType) (*RatingResponse, error)
|
|
GetUserRatingVote(ctx context.Context, objectID uint, userID uint, platform models.PlatformType) (*RatingVoteResponse, error)
|
|
}
|
|
|
|
type objectServiceImpl struct {
|
|
objectRepository repository.ObjectRepository
|
|
}
|
|
|
|
func NewObjectService(objectRepository repository.ObjectRepository) ObjectService {
|
|
return &objectServiceImpl{
|
|
objectRepository: objectRepository,
|
|
}
|
|
}
|
|
|
|
// GetObjectByID возвращает объект по ID с полной информацией
|
|
func (s *objectServiceImpl) GetObjectByID(ctx context.Context, id uint) (*ObjectResponse, error) {
|
|
object, err := s.objectRepository.GetByID(id)
|
|
if err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, ErrObjectNotFound
|
|
}
|
|
return nil, fmt.Errorf("failed to get object by id: %w", err)
|
|
}
|
|
|
|
// Получаем дополнительные данные
|
|
owner, _ := s.objectRepository.GetOwner(id)
|
|
touristRating, _ := s.objectRepository.GetTouristRating(id)
|
|
entrepreneurRating, _ := s.objectRepository.GetEntrepreneurRating(id)
|
|
feedbacks, _ := s.objectRepository.GetFeedbacks(id, 0, 5) // Последние 5 отзывов
|
|
|
|
return s.mapToObjectResponse(object, owner, touristRating, entrepreneurRating, feedbacks), nil
|
|
}
|
|
|
|
// CreateObject создает новый объект
|
|
func (s *objectServiceImpl) CreateObject(ctx context.Context, req *CreateObjectRequest) (*ObjectResponse, error) {
|
|
// Валидация
|
|
if err := s.validateCreateRequest(req); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Устанавливаем значения по умолчанию
|
|
isActive := true
|
|
if req.IsActive != nil {
|
|
isActive = *req.IsActive
|
|
}
|
|
|
|
isVerified := false
|
|
if req.IsVerified != nil {
|
|
isVerified = *req.IsVerified
|
|
}
|
|
|
|
title := req.Title
|
|
if title == "" {
|
|
title = req.ShortName
|
|
}
|
|
status := models.ObjectStatusActive
|
|
if req.Status != "" {
|
|
status = models.ObjectStatus(req.Status)
|
|
}
|
|
|
|
object := &models.Object{
|
|
OwnerID: req.OwnerID,
|
|
Title: title,
|
|
ShortName: req.ShortName,
|
|
LongName: req.LongName,
|
|
Type: req.Type,
|
|
Price: req.Price,
|
|
PricePeriod: req.PricePeriod,
|
|
Phone: req.Phone,
|
|
Email: req.Email,
|
|
Site: req.Site,
|
|
ShortDescription: req.ShortDescription,
|
|
Description: req.Description,
|
|
Address: req.Address,
|
|
Latitude: req.Latitude,
|
|
Longitude: req.Longitude,
|
|
IsActive: isActive,
|
|
IsVerified: isVerified,
|
|
Status: status,
|
|
ViewCount: 0,
|
|
FeedbackCount: 0,
|
|
}
|
|
|
|
if err := s.objectRepository.Create(object); err != nil {
|
|
return nil, fmt.Errorf("failed to create object: %w", err)
|
|
}
|
|
|
|
// Создаем начальные записи рейтингов
|
|
s.initializeRatings(object.ID)
|
|
|
|
return s.GetObjectByID(ctx, object.ID)
|
|
}
|
|
|
|
// UpdateObject обновляет существующий объект
|
|
func (s *objectServiceImpl) UpdateObject(ctx context.Context, id uint, req *UpdateObjectRequest) (*ObjectResponse, error) {
|
|
// Проверяем существование объекта
|
|
existing, err := s.objectRepository.GetByID(id)
|
|
if err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, ErrObjectNotFound
|
|
}
|
|
return nil, fmt.Errorf("failed to get object: %w", err)
|
|
}
|
|
|
|
// Применяем изменения
|
|
s.applyUpdates(existing, req)
|
|
|
|
if err := s.objectRepository.Update(existing); err != nil {
|
|
return nil, fmt.Errorf("failed to update object: %w", err)
|
|
}
|
|
|
|
return s.GetObjectByID(ctx, id)
|
|
}
|
|
|
|
// DeleteObject мягко удаляет объект
|
|
func (s *objectServiceImpl) DeleteObject(ctx context.Context, id uint) error {
|
|
// Проверяем существование
|
|
if _, err := s.objectRepository.GetByID(id); err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return ErrObjectNotFound
|
|
}
|
|
return fmt.Errorf("failed to get object: %w", err)
|
|
}
|
|
|
|
if err := s.objectRepository.Delete(id); err != nil {
|
|
return fmt.Errorf("failed to delete object: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// ListObjects возвращает список объектов с пагинацией и фильтрацией
|
|
func (s *objectServiceImpl) ListObjects(ctx context.Context, req *ListObjectsRequest) (*ObjectListResponse, error) {
|
|
// Устанавливаем значения по умолчанию
|
|
page := req.Page
|
|
if page < 1 {
|
|
page = 1
|
|
}
|
|
|
|
pageSize := req.PageSize
|
|
if pageSize < 1 {
|
|
pageSize = 10
|
|
}
|
|
if pageSize > 100 {
|
|
pageSize = 100
|
|
}
|
|
|
|
offset := (page - 1) * pageSize
|
|
|
|
var objects []models.Object
|
|
var total int64
|
|
var err error
|
|
|
|
// Применяем фильтры
|
|
switch {
|
|
case req.ObjectStatus != "":
|
|
objects, err = s.objectRepository.ListByObjectStatus(req.ObjectStatus, offset, pageSize)
|
|
if err == nil {
|
|
total, _ = s.countObjectsByStatusString(req.ObjectStatus)
|
|
}
|
|
case req.Type != "":
|
|
objects, err = s.objectRepository.ListByType(req.Type, offset, pageSize)
|
|
if err == nil {
|
|
total, _ = s.countObjectsByType(req.Type)
|
|
}
|
|
case req.Status != nil:
|
|
objects, err = s.objectRepository.ListByStatus(*req.Status, offset, pageSize)
|
|
if err == nil {
|
|
total, _ = s.countObjectsByStatus(*req.Status)
|
|
}
|
|
case req.Query != "":
|
|
objects, err = s.objectRepository.Search(req.Query, offset, pageSize)
|
|
if err == nil {
|
|
total, _ = s.countObjectsBySearch(req.Query)
|
|
}
|
|
default:
|
|
objects, err = s.objectRepository.List(offset, pageSize)
|
|
if err == nil {
|
|
total, _ = s.objectRepository.Count()
|
|
}
|
|
}
|
|
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to list objects: %w", err)
|
|
}
|
|
|
|
items := make([]ObjectShortResponse, len(objects))
|
|
for i, obj := range objects {
|
|
items[i] = s.mapToObjectShortResponse(&obj)
|
|
}
|
|
|
|
totalPages := int(total) / pageSize
|
|
if int(total)%pageSize > 0 {
|
|
totalPages++
|
|
}
|
|
|
|
return &ObjectListResponse{
|
|
Items: items,
|
|
Total: total,
|
|
Page: page,
|
|
PageSize: pageSize,
|
|
TotalPages: totalPages,
|
|
}, nil
|
|
}
|
|
|
|
// GetObjectsByOwner возвращает объекты владельца
|
|
func (s *objectServiceImpl) GetObjectsByOwner(ctx context.Context, ownerID uint, page, pageSize int) (*ObjectListResponse, error) {
|
|
if page < 1 {
|
|
page = 1
|
|
}
|
|
if pageSize < 1 {
|
|
pageSize = 10
|
|
}
|
|
if pageSize > 100 {
|
|
pageSize = 100
|
|
}
|
|
|
|
offset := (page - 1) * pageSize
|
|
objects, err := s.objectRepository.ListByOwner(ownerID, offset, pageSize)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get objects by owner: %w", err)
|
|
}
|
|
|
|
total, _ := s.countObjectsByOwner(ownerID)
|
|
|
|
items := make([]ObjectShortResponse, len(objects))
|
|
for i, obj := range objects {
|
|
items[i] = s.mapToObjectShortResponse(&obj)
|
|
}
|
|
|
|
totalPages := int(total) / pageSize
|
|
if int(total)%pageSize > 0 {
|
|
totalPages++
|
|
}
|
|
|
|
return &ObjectListResponse{
|
|
Items: items,
|
|
Total: total,
|
|
Page: page,
|
|
PageSize: pageSize,
|
|
TotalPages: totalPages,
|
|
}, nil
|
|
}
|
|
|
|
// GetObjectsByType возвращает объекты по типу
|
|
func (s *objectServiceImpl) GetObjectsByType(ctx context.Context, objectType string, page, pageSize int) (*ObjectListResponse, error) {
|
|
if page < 1 {
|
|
page = 1
|
|
}
|
|
if pageSize < 1 {
|
|
pageSize = 10
|
|
}
|
|
if pageSize > 100 {
|
|
pageSize = 100
|
|
}
|
|
|
|
offset := (page - 1) * pageSize
|
|
objects, err := s.objectRepository.ListByType(objectType, offset, pageSize)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get objects by type: %w", err)
|
|
}
|
|
|
|
total, _ := s.countObjectsByType(objectType)
|
|
|
|
items := make([]ObjectShortResponse, len(objects))
|
|
for i, obj := range objects {
|
|
items[i] = s.mapToObjectShortResponse(&obj)
|
|
}
|
|
|
|
totalPages := int(total) / pageSize
|
|
if int(total)%pageSize > 0 {
|
|
totalPages++
|
|
}
|
|
|
|
return &ObjectListResponse{
|
|
Items: items,
|
|
Total: total,
|
|
Page: page,
|
|
PageSize: pageSize,
|
|
TotalPages: totalPages,
|
|
}, nil
|
|
}
|
|
|
|
// SearchObjects ищет объекты по запросу
|
|
func (s *objectServiceImpl) SearchObjects(ctx context.Context, query string, page, pageSize int) (*ObjectListResponse, error) {
|
|
if page < 1 {
|
|
page = 1
|
|
}
|
|
if pageSize < 1 {
|
|
pageSize = 10
|
|
}
|
|
if pageSize > 100 {
|
|
pageSize = 100
|
|
}
|
|
|
|
offset := (page - 1) * pageSize
|
|
objects, err := s.objectRepository.Search(query, offset, pageSize)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to search objects: %w", err)
|
|
}
|
|
|
|
total, _ := s.countObjectsBySearch(query)
|
|
|
|
items := make([]ObjectShortResponse, len(objects))
|
|
for i, obj := range objects {
|
|
items[i] = s.mapToObjectShortResponse(&obj)
|
|
}
|
|
|
|
totalPages := int(total) / pageSize
|
|
if int(total)%pageSize > 0 {
|
|
totalPages++
|
|
}
|
|
|
|
return &ObjectListResponse{
|
|
Items: items,
|
|
Total: total,
|
|
Page: page,
|
|
PageSize: pageSize,
|
|
TotalPages: totalPages,
|
|
}, nil
|
|
}
|
|
|
|
// GetNearbyObjects возвращает объекты в радиусе
|
|
func (s *objectServiceImpl) GetNearbyObjects(ctx context.Context, lat, lng, radius float64, page, pageSize int) (*ObjectListResponse, error) {
|
|
if page < 1 {
|
|
page = 1
|
|
}
|
|
if pageSize < 1 {
|
|
pageSize = 10
|
|
}
|
|
if pageSize > 100 {
|
|
pageSize = 100
|
|
}
|
|
|
|
offset := (page - 1) * pageSize
|
|
objects, err := s.objectRepository.GetNearby(lat, lng, radius, offset, pageSize)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get nearby objects: %w", err)
|
|
}
|
|
|
|
items := make([]ObjectShortResponse, len(objects))
|
|
for i, obj := range objects {
|
|
items[i] = s.mapToObjectShortResponse(&obj)
|
|
}
|
|
|
|
return &ObjectListResponse{
|
|
Items: items,
|
|
Total: int64(len(objects)),
|
|
Page: page,
|
|
PageSize: pageSize,
|
|
TotalPages: 1,
|
|
}, nil
|
|
}
|
|
|
|
// ToggleVerification переключает статус верификации
|
|
func (s *objectServiceImpl) ToggleVerification(ctx context.Context, id uint, verified bool) error {
|
|
if err := s.objectRepository.ToggleVerification(id, verified); err != nil {
|
|
return fmt.Errorf("failed to toggle verification: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// CreateFeedback создает отзыв
|
|
func (s *objectServiceImpl) CreateFeedback(ctx context.Context, req *CreateFeedbackRequest, ownerID uint) (*FeedbackResponse, error) {
|
|
// Проверяем существование объекта
|
|
if _, err := s.objectRepository.GetByID(req.ObjectID); err != nil {
|
|
return nil, ErrObjectNotFound
|
|
}
|
|
|
|
feedback := &models.Feedback{
|
|
OwnerID: ownerID,
|
|
ObjectID: req.ObjectID,
|
|
Platform: req.Platform,
|
|
Score: req.Score,
|
|
Text: req.Text,
|
|
}
|
|
|
|
// TODO: Добавить метод CreateFeedback в репозиторий
|
|
// if err := s.objectRepository.CreateFeedback(feedback); err != nil {
|
|
// return nil, fmt.Errorf("failed to create feedback: %w", err)
|
|
// }
|
|
|
|
// Обновляем счетчик отзывов
|
|
if err := s.objectRepository.UpdateFeedbackCount(req.ObjectID, 1); err != nil {
|
|
// Логируем ошибку, но не прерываем выполнение
|
|
fmt.Printf("Failed to update feedback count: %v\n", err)
|
|
}
|
|
|
|
return s.GetFeedbackByID(ctx, feedback.ID)
|
|
}
|
|
|
|
// UpdateFeedback обновляет отзыв
|
|
func (s *objectServiceImpl) UpdateFeedback(ctx context.Context, id uint, req *UpdateFeedbackRequest, ownerID uint) (*FeedbackResponse, error) {
|
|
// TODO: Реализовать обновление отзыва
|
|
return nil, ErrNotImplemented
|
|
}
|
|
|
|
// DeleteFeedback удаляет отзыв
|
|
func (s *objectServiceImpl) DeleteFeedback(ctx context.Context, id uint, ownerID uint) error {
|
|
// TODO: Реализовать удаление отзыва
|
|
return ErrNotImplemented
|
|
}
|
|
|
|
// GetFeedbackByID возвращает отзыв по ID
|
|
func (s *objectServiceImpl) GetFeedbackByID(ctx context.Context, id uint) (*FeedbackResponse, error) {
|
|
// TODO: Добавить метод GetFeedbackByID в репозиторий
|
|
// feedback, err := s.objectRepository.GetFeedbackByID(id)
|
|
// if err != nil {
|
|
// return nil, fmt.Errorf("failed to get feedback: %w", err)
|
|
// }
|
|
|
|
// return s.mapToFeedbackResponse(feedback), nil
|
|
return nil, ErrNotImplemented
|
|
}
|
|
|
|
// GetFeedbacksByObject возвращает отзывы объекта
|
|
func (s *objectServiceImpl) GetFeedbacksByObject(ctx context.Context, objectID uint, page, pageSize int) (*FeedbackListResponse, error) {
|
|
if page < 1 {
|
|
page = 1
|
|
}
|
|
if pageSize < 1 {
|
|
pageSize = 10
|
|
}
|
|
if pageSize > 100 {
|
|
pageSize = 100
|
|
}
|
|
|
|
offset := (page - 1) * pageSize
|
|
feedbacks, err := s.objectRepository.GetFeedbacks(objectID, offset, pageSize)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get feedbacks: %w", err)
|
|
}
|
|
|
|
count, err := s.objectRepository.GetFeedbackCount(objectID)
|
|
if err != nil {
|
|
count = 0
|
|
}
|
|
|
|
items := make([]FeedbackResponse, len(feedbacks))
|
|
for i, fb := range feedbacks {
|
|
items[i] = *s.mapToFeedbackResponse(&fb)
|
|
}
|
|
|
|
totalPages := count / pageSize
|
|
if count%pageSize > 0 {
|
|
totalPages++
|
|
}
|
|
|
|
return &FeedbackListResponse{
|
|
Items: items,
|
|
Total: int64(count),
|
|
Page: page,
|
|
PageSize: pageSize,
|
|
TotalPages: totalPages,
|
|
}, nil
|
|
}
|
|
|
|
// CreateRatingVote создает голос в рейтинге
|
|
func (s *objectServiceImpl) CreateRatingVote(ctx context.Context, req *CreateRatingVoteRequest, voterID uint) (*RatingVoteResponse, error) {
|
|
// Проверяем, не голосовал ли уже пользователь
|
|
existing, _ := s.GetUserRatingVote(ctx, req.TargetID, voterID, req.Platform)
|
|
if existing != nil {
|
|
return nil, ErrAlreadyVoted
|
|
}
|
|
|
|
ratingVote := &models.RatingVote{
|
|
Platform: req.Platform,
|
|
TargetID: req.TargetID,
|
|
VoterID: voterID,
|
|
Score: req.Score,
|
|
}
|
|
|
|
// TODO: Добавить метод CreateRatingVote в репозиторий
|
|
// if err := s.objectRepository.CreateRatingVote(ratingVote); err != nil {
|
|
// return nil, fmt.Errorf("failed to create rating vote: %w", err)
|
|
// }
|
|
|
|
// Обновляем статистику рейтинга
|
|
s.updateRatingStats(req.TargetID, req.Platform)
|
|
|
|
return &RatingVoteResponse{
|
|
ID: ratingVote.ID,
|
|
CreatedAt: ratingVote.CreatedAt,
|
|
Platform: ratingVote.Platform,
|
|
TargetID: ratingVote.TargetID,
|
|
VoterID: ratingVote.VoterID,
|
|
Score: ratingVote.Score,
|
|
}, nil
|
|
}
|
|
|
|
// GetObjectRating возвращает рейтинг объекта
|
|
func (s *objectServiceImpl) GetObjectRating(ctx context.Context, objectID uint, platform models.PlatformType) (*RatingResponse, error) {
|
|
var rating *models.Rating
|
|
var err error
|
|
|
|
if platform == models.PlatformTourist {
|
|
rating, err = s.objectRepository.GetTouristRating(objectID)
|
|
} else {
|
|
rating, err = s.objectRepository.GetEntrepreneurRating(objectID)
|
|
}
|
|
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get rating: %w", err)
|
|
}
|
|
|
|
return s.mapToRatingResponse(rating), nil
|
|
}
|
|
|
|
// GetUserRatingVote возвращает голос пользователя
|
|
func (s *objectServiceImpl) GetUserRatingVote(ctx context.Context, objectID uint, userID uint, platform models.PlatformType) (*RatingVoteResponse, error) {
|
|
// TODO: Добавить метод GetUserRatingVote в репозиторий
|
|
// vote, err := s.objectRepository.GetUserRatingVote(objectID, userID, platform)
|
|
// if err != nil {
|
|
// return nil, err
|
|
// }
|
|
|
|
// return &RatingVoteResponse{
|
|
// ID: vote.ID,
|
|
// CreatedAt: vote.CreatedAt,
|
|
// Platform: vote.Platform,
|
|
// TargetID: vote.TargetID,
|
|
// VoterID: vote.VoterID,
|
|
// Score: vote.Score,
|
|
// }, nil
|
|
return nil, ErrNotImplemented
|
|
}
|
|
|
|
// Вспомогательные методы
|
|
|
|
func (s *objectServiceImpl) validateCreateRequest(req *CreateObjectRequest) error {
|
|
if req.OwnerID == 0 {
|
|
return ErrInvalidOwnerID
|
|
}
|
|
if req.ShortName == "" {
|
|
return ErrShortNameRequired
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *objectServiceImpl) applyUpdates(object *models.Object, req *UpdateObjectRequest) {
|
|
if req.Title != nil {
|
|
object.Title = *req.Title
|
|
}
|
|
if req.ShortName != nil {
|
|
object.ShortName = *req.ShortName
|
|
}
|
|
if req.LongName != nil {
|
|
object.LongName = *req.LongName
|
|
}
|
|
if req.Type != nil {
|
|
object.Type = *req.Type
|
|
}
|
|
if req.Price != nil {
|
|
object.Price = *req.Price
|
|
}
|
|
if req.PricePeriod != nil {
|
|
object.PricePeriod = *req.PricePeriod
|
|
}
|
|
if req.Phone != nil {
|
|
object.Phone = *req.Phone
|
|
}
|
|
if req.Email != nil {
|
|
object.Email = *req.Email
|
|
}
|
|
if req.Site != nil {
|
|
object.Site = *req.Site
|
|
}
|
|
if req.ShortDescription != nil {
|
|
object.ShortDescription = *req.ShortDescription
|
|
}
|
|
if req.Description != nil {
|
|
object.Description = *req.Description
|
|
}
|
|
if req.Address != nil {
|
|
object.Address = *req.Address
|
|
}
|
|
if req.Latitude != nil {
|
|
object.Latitude = *req.Latitude
|
|
}
|
|
if req.Longitude != nil {
|
|
object.Longitude = *req.Longitude
|
|
}
|
|
if req.Status != nil {
|
|
object.Status = models.ObjectStatus(*req.Status)
|
|
}
|
|
if req.IsActive != nil {
|
|
object.IsActive = *req.IsActive
|
|
}
|
|
if req.IsVerified != nil {
|
|
object.IsVerified = *req.IsVerified
|
|
}
|
|
}
|
|
|
|
func (s *objectServiceImpl) initializeRatings(objectID uint) {
|
|
// Создаем записи рейтингов для туристической и предпринимательской платформ
|
|
// TODO: Добавить создание рейтингов в репозиторий
|
|
}
|
|
|
|
func (s *objectServiceImpl) updateRatingStats(objectID uint, platform models.PlatformType) {
|
|
// Обновляем статистику рейтинга
|
|
// TODO: Реализовать обновление статистики
|
|
}
|
|
|
|
func (s *objectServiceImpl) mapToObjectResponse(object *models.Object, owner *models.Account, touristRating, entrepreneurRating *models.Rating, feedbacks []models.Feedback) *ObjectResponse {
|
|
resp := &ObjectResponse{
|
|
ID: object.ID,
|
|
CreatedAt: object.CreatedAt,
|
|
UpdatedAt: object.UpdatedAt,
|
|
OwnerID: object.OwnerID,
|
|
Title: object.Title,
|
|
ShortName: object.ShortName,
|
|
LongName: object.LongName,
|
|
Type: object.Type,
|
|
Price: object.Price,
|
|
PricePeriod: object.PricePeriod,
|
|
Phone: object.Phone,
|
|
Email: object.Email,
|
|
Site: object.Site,
|
|
ShortDescription: object.ShortDescription,
|
|
Description: object.Description,
|
|
Address: object.Address,
|
|
Latitude: object.Latitude,
|
|
Longitude: object.Longitude,
|
|
IsActive: object.IsActive,
|
|
IsVerified: object.IsVerified,
|
|
Status: string(object.Status),
|
|
ViewCount: object.ViewCount,
|
|
FeedbackCount: object.FeedbackCount,
|
|
}
|
|
|
|
if object.DeletedAt.Valid {
|
|
resp.DeletedAt = &object.DeletedAt.Time
|
|
}
|
|
|
|
if owner != nil {
|
|
resp.Owner = &account.AccountResponse{
|
|
ID: owner.ID,
|
|
FullName: owner.FullName,
|
|
Email: owner.Email,
|
|
// Добавьте другие поля
|
|
}
|
|
}
|
|
|
|
if touristRating != nil {
|
|
resp.TouristRating = s.mapToRatingResponse(touristRating)
|
|
}
|
|
|
|
if entrepreneurRating != nil {
|
|
resp.EntrepreneurRating = s.mapToRatingResponse(entrepreneurRating)
|
|
}
|
|
|
|
if len(feedbacks) > 0 {
|
|
resp.Feedbacks = make([]FeedbackShortResponse, len(feedbacks))
|
|
for i, fb := range feedbacks {
|
|
resp.Feedbacks[i] = FeedbackShortResponse{
|
|
ID: fb.ID,
|
|
CreatedAt: fb.CreatedAt,
|
|
OwnerID: fb.OwnerID,
|
|
Platform: fb.Platform,
|
|
Score: fb.Score,
|
|
Text: fb.Text,
|
|
}
|
|
}
|
|
}
|
|
|
|
if len(object.Images) > 0 {
|
|
resp.Images = make([]ImageResponse, len(object.Images))
|
|
for i, img := range object.Images {
|
|
resp.Images[i] = ImageResponse{
|
|
ID: img.ID,
|
|
ObjectID: img.ObjectID,
|
|
URL: img.URL,
|
|
IsPrimary: img.IsPrimary,
|
|
SortOrder: img.SortOrder,
|
|
}
|
|
}
|
|
}
|
|
|
|
if len(object.Amenities) > 0 {
|
|
resp.Amenities = make([]AmenityResponse, len(object.Amenities))
|
|
for i, a := range object.Amenities {
|
|
resp.Amenities[i] = AmenityResponse{
|
|
ID: a.ID,
|
|
Name: a.Name,
|
|
Category: a.Category,
|
|
Icon: a.Icon,
|
|
Description: a.Description,
|
|
}
|
|
}
|
|
}
|
|
|
|
return resp
|
|
}
|
|
|
|
func (s *objectServiceImpl) mapToObjectShortResponse(object *models.Object) ObjectShortResponse {
|
|
return ObjectShortResponse{
|
|
ID: object.ID,
|
|
Title: object.Title,
|
|
ShortName: object.ShortName,
|
|
LongName: object.LongName,
|
|
Type: object.Type,
|
|
Price: object.Price,
|
|
PricePeriod: object.PricePeriod,
|
|
Address: object.Address,
|
|
IsActive: object.IsActive,
|
|
IsVerified: object.IsVerified,
|
|
Status: string(object.Status),
|
|
FeedbackCount: object.FeedbackCount,
|
|
}
|
|
}
|
|
|
|
func (s *objectServiceImpl) mapToRatingResponse(rating *models.Rating) *RatingResponse {
|
|
return &RatingResponse{
|
|
ID: rating.ID,
|
|
CreatedAt: rating.CreatedAt,
|
|
UpdatedAt: rating.UpdatedAt,
|
|
Platform: rating.Platform,
|
|
AverageScore: rating.AverageScore,
|
|
TotalVotes: rating.TotalVotes,
|
|
VoteBreakdown: VoteBreakdownDTO{
|
|
Score1: rating.VoteBreakdown.Score1,
|
|
Score2: rating.VoteBreakdown.Score2,
|
|
Score3: rating.VoteBreakdown.Score3,
|
|
Score4: rating.VoteBreakdown.Score4,
|
|
Score5: rating.VoteBreakdown.Score5,
|
|
},
|
|
}
|
|
}
|
|
|
|
func (s *objectServiceImpl) mapToFeedbackResponse(feedback *models.Feedback) *FeedbackResponse {
|
|
return &FeedbackResponse{
|
|
ID: feedback.ID,
|
|
CreatedAt: feedback.CreatedAt,
|
|
UpdatedAt: feedback.UpdatedAt,
|
|
OwnerID: feedback.OwnerID,
|
|
ObjectID: feedback.ObjectID,
|
|
Platform: feedback.Platform,
|
|
Score: feedback.Score,
|
|
Text: feedback.Text,
|
|
CommentCount: feedback.CommentCount,
|
|
}
|
|
}
|
|
|
|
// Методы для подсчета (временные, должны быть в репозитории)
|
|
func (s *objectServiceImpl) countObjectsByType(objectType string) (int64, error) {
|
|
// TODO: Добавить метод CountByType в репозиторий
|
|
return 0, nil
|
|
}
|
|
|
|
func (s *objectServiceImpl) countObjectsByStatus(isActive bool) (int64, error) {
|
|
// TODO: Добавить метод CountByStatus в репозиторий
|
|
return 0, nil
|
|
}
|
|
|
|
func (s *objectServiceImpl) countObjectsByOwner(ownerID uint) (int64, error) {
|
|
// TODO: Добавить метод CountByOwner в репозиторий
|
|
return 0, nil
|
|
}
|
|
|
|
func (s *objectServiceImpl) countObjectsBySearch(query string) (int64, error) {
|
|
// TODO: Добавить метод CountBySearch в репозиторий
|
|
return 0, nil
|
|
}
|
|
|
|
func (s *objectServiceImpl) countObjectsByStatusString(status string) (int64, error) {
|
|
return 0, nil
|
|
}
|