Real Estate Mobile API

API для каталога недвижимости и заявок по квартирам

Это backend-приложение для мобильного или web-фронтенда в сфере недвижимости. Оно отдаёт список жилых комплексов, позволяет получать квартиры с фильтрацией, открывать детальную карточку квартиры и отправлять целевые заявки на консультацию, бронирование или покупку.

Контекст тестового задания

Тестовое задание реализовано как backend-модуль для мобильного приложения недвижимости. Основной поток: пользователь выбирает жилой комплекс, просматривает квартиры, открывает карточку квартиры и отправляет заявку на консультацию, бронирование или покупку с последующей передачей в CRM.

Каталог объектов

API предоставляет список жилых комплексов и квартир, фильтрацию каталога и детальную карточку объекта.

Заявки клиентов

Пользователь может отправить заявку по квартире на консультацию, бронирование или покупку с обязательной валидацией данных.

CRM интеграция

После локального сохранения заявка должна быть передана во внешнюю систему без дублей и без потери лида.

20 уточняющих вопросов к заказчику перед стартом разработки.
11 шагов в предполагаемой логике работы пользовательского потока.
12 сценариев использования, включая позитивные и негативные.
8 блоков анализа, полностью закрывающих требования тестового задания.

1. Уточняющие вопросы к заказчику

До начала реализации важно зафиксировать бизнес-границы модуля, правила работы заявки и ожидания от интеграции с CRM.

Продукт и роли

  1. Кто является пользователем модуля: анонимный клиент, авторизованный клиент или оба варианта?
  2. Какие типы заявок обязательны в первой версии: консультация, бронь, покупка, ипотека, просмотр?
  3. В чем бизнес-разница между заявкой на покупку и заявкой на бронирование?
  4. Нужно ли полностью запрещать заявки для проданных квартир?
  5. Можно ли принимать заявки по забронированным квартирам?

Жизненный цикл заявки

  1. Допустимы ли несколько активных заявок по одной квартире от одного клиента?
  2. Что считается успешной обработкой заявки: локальное сохранение, постановка в очередь или подтверждение CRM?
  3. Интеграция с CRM синхронная или асинхронная?
  4. Что делать, если CRM временно недоступна?
  5. Нужны ли уведомления клиенту после создания заявки?

Данные и валидация

  1. Нужна ли история изменения статусов заявки?
  2. Какие поля являются обязательными: имя, телефон, email, комментарий, способ связи?
  3. Нужна ли отдельная валидация номера телефона по стране?
  4. Нужно ли хранить источник лида: iOS, Android, web, рекламный канал?
  5. Есть ли SLA на обработку заявки менеджером?

Ограничения и сопровождение

  1. Должна ли бронь иметь срок истечения?
  2. Нужно ли фиксировать согласие на обработку персональных данных?
  3. Нужна ли мультиязычность API и текстов ошибок?
  4. Должна ли система поддерживать роли сотрудников или админ-панель?
  5. Какие есть требования по аудиту, логированию и отказоустойчивости?

2. Предполагаемая логика работы модуля

  1. Пользователь получает список жилых комплексов.
  2. Выбирает жилой комплекс и фильтрует квартиры по параметрам.
  3. Открывает карточку квартиры.
  4. Система показывает атрибуты квартиры и доступные действия.
  5. Пользователь заполняет форму заявки.
  6. API валидирует поля запроса.
  7. API проверяет бизнес-ограничения с учетом статуса квартиры.
  8. Если передан тот же Idempotency-Key, система возвращает уже созданную заявку без дубля.
  9. Если проверка успешна, заявка сохраняется в БД со стартовым статусом queued_for_sync.
  10. Далее заявка отправляется во внешнюю CRM.
  11. После ответа интеграции статус заявки обновляется.

3. Пользовательские сценарии

Основные сценарии

  1. Просмотр списка жилых комплексов.
  2. Просмотр карточки жилого комплекса.
  3. Фильтрация списка квартир.
  4. Просмотр карточки квартиры.
  5. Создание заявки на консультацию.
  6. Создание заявки на бронирование доступной квартиры.
  7. Создание заявки на покупку.

Негативные сценарии

  1. Попытка создать заявку по проданной квартире.
  2. Попытка забронировать квартиру, которая уже не available.
  3. Повторная отправка того же запроса с тем же Idempotency-Key.
  4. Отправка формы с невалидными данными.
  5. Ошибка передачи данных во внешнюю CRM.

4. Бизнес-ограничения и исключительные ситуации

Ограничения

  1. Для квартиры со статусом sold создание целевых заявок недоступно.
  2. Заявка типа reservation разрешена только для квартир со статусом available.
  3. Заявка типа purchase для квартиры со статусом reserved может требовать подтверждения менеджера.
  4. Одна и та же заявка не должна создаваться повторно при сетевых ретраях клиента.

Исключительные ситуации

  1. Между просмотром карточки и отправкой формы статус квартиры может измениться.
  2. CRM может быть временно недоступна, но лид не должен теряться.
  3. Персональные данные клиента должны храниться и передаваться безопасно.
  4. Бронь может иметь срок действия и сниматься автоматически после истечения.

5. Возможные риски реализации

  1. Гонки данных: квартира была доступна на момент просмотра, но изменила статус к моменту отправки заявки.
  2. Дубли заявок из-за повторных отправок с мобильного клиента.
  3. Потеря лидов при сбоях интеграции с CRM.
  4. Рассинхронизация статусов между локальной системой и CRM.
  5. Недостаточно формализованные бизнес-правила по типам заявок.
  6. Слабая валидация контактов, ухудшающая качество лидов.
  7. Усложнение логики при добавлении новых каналов и типов заявок.
  8. Юридические риски по персональным данным и согласию пользователя.
  9. Нехватка аудита по смене статусов и ручным действиям менеджеров.
  10. Непрозрачные ошибки API для мобильного приложения.

6. Архитектурный подход

API-слой

REST + Request Validation

Endpoints для ЖК, квартир и заявок, request-валидаторы для входных данных и API resources для единообразного JSON-ответа.

Доменный слой

ResidentialComplex / Apartment / ApartmentRequest

Основные сущности предметной области и enum-ы для типов и статусов, чтобы бизнес-логика оставалась явной и управляемой.

Бизнес-логика

Сервисы и правила

Сервис создания заявки, определение доступных действий по квартире и идемпотентность на уровне сервиса и базы данных.

Интеграция

CRM Adapter / Gateway

Выделенный интеграционный слой для внешней CRM, чтобы изолировать transport logic и упростить доработки.

Надежность

Очереди и ретраи

Асинхронная синхронизация, повторные попытки отправки и журнал ошибок, чтобы лид не терялся при отказах внешней системы.

Текущее состояние

Основа уже есть в проекте

В кодовой базе уже присутствуют модели, enum-ы, endpoint создания заявки, Swagger и feature-тесты пользовательского потока.

7. Структура данных

residential_complexes

  • id
  • name
  • slug
  • city
  • address
  • description
  • external_id
  • gallery

apartments

  • id
  • residential_complex_id
  • unit_number
  • rooms
  • floor
  • total_floors
  • area_sqm
  • price
  • currency
  • status
  • layout_image_url
  • finishing
  • orientation
  • features
  • description
  • booking_expires_at
  • external_system
  • external_id

apartment_requests

  • id
  • apartment_id
  • type
  • status
  • customer_name
  • phone
  • email
  • comment
  • preferred_contact_method
  • source_channel
  • idempotency_key
  • external_system
  • external_reference
  • integration_payload
  • submitted_at
  • created_at
  • updated_at

Дополнительно рекомендовано

  • таблица истории смены статусов заявки;
  • журнал попыток синхронизации с CRM;
  • поля согласия на обработку персональных данных;
  • привязка ответственного менеджера, если это требуется бизнесом.

8. Обоснование принятых решений

  1. ApartmentRequest вынесена в отдельную сущность, потому что заявка имеет собственный жизненный цикл и статусную модель.
  2. Идемпотентность обязательна, так как мобильный клиент может повторно отправить один и тот же запрос.
  3. Локальное сохранение заявки до синхронизации с CRM снижает риск потери лида при сбоях внешней системы.
  4. Использование enum-ов делает бизнес-правила более явными и уменьшает вероятность неконсистентных состояний.
  5. Разделение API, доменной логики и интеграционного слоя упрощает поддержку и развитие решения.
  6. Бизнес-проверки на стороне backend обязательны, потому что нельзя полагаться только на ограничения в мобильном интерфейсе.
  7. Хранение source_channel полезно для аналитики и оценки качества каналов привлечения.
  8. История статусов и журнал интеграции важны для поддержки, аудита и разбора инцидентов.