|
|
@@ -0,0 +1,78 @@
|
|
|
+# PATCH /places/{id} — теги и характеристики не обновлялись
|
|
|
+
|
|
|
+**Контекст**: При редактировании места через `PATCH /places/{id}` поля `tags` и `features` игнорировались. Фронтенд их отправлял, хендлер парсил, но никогда не передавал в сервис.
|
|
|
+
|
|
|
+## Проблема
|
|
|
+
|
|
|
+Две точки отказа:
|
|
|
+
|
|
|
+### 1. Хендлер (`handlers/places.go:282-296`)
|
|
|
+
|
|
|
+`updatePlaceRequest` содержал `Tags []string` и `Features []string`, но метод `Update()` копировал только: Title, Description, Address, Lat, Lng, AccessInfo, HourlyRate, Currency, MinHours.
|
|
|
+
|
|
|
+**CoverImage** тоже не копировался — был в обоих структурах, но не завайрены.
|
|
|
+
|
|
|
+```go
|
|
|
+// Было — Tags, Features, CoverImage не копировались
|
|
|
+if req.Title != nil { input.Title = req.Title }
|
|
|
+// ... остальные поля ...
|
|
|
+// CoverImage, Tags, Features — потеряны
|
|
|
+```
|
|
|
+
|
|
|
+### 2. Сервис (`services/places.go:194-207`)
|
|
|
+
|
|
|
+`UpdatePlaceInput` не имел полей `Tags` и `Features`. Метод `Update()` не вызывал `placeRepo.SetTags()` / `placeRepo.SetFeatures()`.
|
|
|
+
|
|
|
+## Исправление
|
|
|
+
|
|
|
+### Хендлер — копирование CoverImage, Tags, Features
|
|
|
+
|
|
|
+```go
|
|
|
+if req.CoverImage != nil { input.CoverImage = req.CoverImage }
|
|
|
+
|
|
|
+if req.Tags != nil {
|
|
|
+ tags := make([]models.Tag, len(req.Tags))
|
|
|
+ for i, t := range req.Tags {
|
|
|
+ tags[i] = models.Tag{ID: t}
|
|
|
+ }
|
|
|
+ input.Tags = tags
|
|
|
+}
|
|
|
+if req.Features != nil {
|
|
|
+ features := make([]models.Feature, len(req.Features))
|
|
|
+ for i, f := range req.Features {
|
|
|
+ features[i] = models.Feature{ID: f}
|
|
|
+ }
|
|
|
+ input.Features = features
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### Сервис — SetTags/SetFeatures при наличии данных
|
|
|
+
|
|
|
+```go
|
|
|
+if input.Tags != nil {
|
|
|
+ if err := s.placeRepo.SetTags(ctx, place.ID, input.Tags); err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ place.Tags = input.Tags
|
|
|
+}
|
|
|
+// Аналогично для Features
|
|
|
+```
|
|
|
+
|
|
|
+`SetTags` и `SetFeatures` уже были реализованы в `repository/places.go` — используют транзакцию: DELETE всех старых + INSERT новых. Проблема была только в отсутствии вызова.
|
|
|
+
|
|
|
+## Ключевой инсайт
|
|
|
+
|
|
|
+Использование `nil` vs `[]string{}` в JSON-десериализации позволило различать "поле не отправлено" (не обновляем) и "отправлен пустой массив" (очищаем теги/фичи). Для PATCH-семантики это критично.
|
|
|
+
|
|
|
+## Связанные заметки
|
|
|
+
|
|
|
+- [[decision-patch-tags-features-fix]] — ADR по выбору подхода
|
|
|
+- [[MOC-backend-patterns]] — антипаттерны
|
|
|
+
|
|
|
+## Источник
|
|
|
+
|
|
|
+Code review PhotoPlaces 2026-06-29. `handlers/places.go`, `services/places.go`.
|
|
|
+
|
|
|
+## Теги
|
|
|
+
|
|
|
+#bug #golang #api #patch #critical
|