SPACI, ОАЭ

Каталог коммерческой недвижимости Дубая: импорт, который не теряет данные

Публичный справочник коммерческой недвижимости Дубая: здания, помещения, локации, застройщики, лицензии, сделки и сервисные сборы. Разработали платформу целиком — от пакетного импорта из Excel до витрины и эксплуатации прода.

Платформа каталога коммерческой недвижимости Дубая — SPACI
Отрасль
Коммерческая недвижимость, ОАЭ
Платформа
Laravel, PostgreSQL/PostGIS
Срок работ
платформа в эксплуатации
Бюджет проекта
NDA*
Делаем такие проекты под ключ Обсудим задачу, назовём срок и стоимость до начала работ.
Результат

Результат в цифрах

около 7 000 строк

Вернулись в базу

Раньше терялись при импорте без следа: здания, сделки и сборы
1 678 логотипов

Привязаны через ZIP-шаблон

Партнёры, здания, локации и лицензии
5 498 зданий

Объём каталога

88 145 помещений, 40 127 сделок, 882 локации
Задача

Данные о рынке жили в разрозненных таблицах

SPACI — публичный справочник коммерческой недвижимости Дубая: здания, отдельные помещения, локации и комплексы, застройщики и партнёры, бизнес-лицензии и свободные зоны, сделки и сервисные сборы. Данные ведёт клиент из ОАЭ, выгружая их из официальных реестров Земельного департамента.

Задача звучала как «загрузить выгрузки на сайт», но настоящая проблема была не в загрузке, а в достоверности. Excel-файлы приходят с разными заголовками, с невидимыми символами внутри названий, с конфликтующими строками. При наивном импорте часть данных молча пропадает: строка не совпала с существующей записью — и её просто нет, а никто об этом не узнал.

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

Пакетная загрузка из Excel Файлы клиента — это десятки тысяч строк по семи типам сущностей. Их нужно принимать регулярно, без ручного разбора и без переполнения памяти.
Разные заголовки в файлах Один и тот же тип листа приходит с разными названиями колонок: определять его нужно и по имени листа, и по набору полей.
Правила уникальности из предметной области Здание уникально в паре «название плюс локация», локация — в паре «название плюс район», а сделки не дедуплицируются вовсе: так требует заказчик и правила Земельного департамента.
Медиа для тысяч объектов Логотипы, фотографии и планы нужно привязывать массово, а не по одному файлу через админку.
Достоверность витрины Счётчики на публичных страницах показывали то суммарные, то маркетинговые числа, расходясь между блоками одной и той же страницы.
Решение

Что сделали

01

Двухфазный конвейер импорта

Файл сначала попадает в промежуточную таблицу, и только после подтверждения выполняется загрузка — в фоновой очереди, потоковым разбором, без переполнения памяти на больших файлах. На каждый тип листа своя стратегия: здания, помещения, локации, партнёры, лицензии, сделки, сборы. Тип определяется и по имени листа, и по набору колонок.

02

Прослеживаемость до ячейки

Каждая запись хранит источник: файл, лист и номер строки. Повторная загрузка того же файла не создаёт дублей — запись сопоставляется по координатам исходной строки. Конфликтующие данные, например два разных тарифа сбора на одно здание и год, не затирают друг друга молча, а попадают в отчёт об ошибках с точным указанием места.

03

Чистка того, что ломает сопоставление

Невидимые символы из Excel — неразрывные пробелы и zero-width-маркеры — вычищаются: из-за них название переставало находиться при следующей загрузке. Перекрёстные ссылки между файлами разрешаются по файлу-источнику, а при неоднозначности импорт не угадывает, а сообщает об ошибке.

О проекте

Платформа каталога коммерческой недвижимости Дубая — SPACI

SPACI — публичный справочник коммерческой недвижимости Дубая. В каталоге здания, отдельные помещения, локации и комплексы, застройщики и партнёры, бизнес-лицензии и свободные зоны, сделки и сервисные сборы. Данные ведёт клиент из ОАЭ: он выгружает их из официальных реестров Земельного департамента в Excel и передаёт в систему.

Мы делали платформу целиком: импорт данных, доменную логику, витрину и эксплуатацию боевого сервера. Стек — PHP 8.2 и Laravel, PostgreSQL 16 с PostGIS для геоданных, Redis, админка на Next.js, всё в Docker Compose с очередями и планировщиком.

Правила уникальности из предметной области

Результат этой работы измеряется прямо: в базу вернулось около семи тысяч строк, которые прежде терялись без следа. Зданий стало 5 498 вместо 5 465, сделок 40 127 вместо 37 050, сервисных сборов 12 353 вместо 8 382.

  • здание уникально в паре «название плюс локация» — одинаковые имена в разных местах допустимы, переименовывать нельзя;
  • локация уникальна в паре «название плюс район»;
  • сделки не дедуплицируются: каждая уникальна по требованию клиента;
  • каждая запись хранит источник — файл, лист и номер строки, поэтому повторная загрузка безопасна, а значение прослеживается до конкретной ячейки;
  • конфликтующие данные не затирают друг друга молча, а роняют строку в отчёт об ошибках.

Мелочи, которые портят данные

Отдельная часть работы — ловушки, из-за которых цифры получаются правдоподобными, но неверными. Парковка исключена из расчёта среднего сервисного сбора: она измеряется за машиноместо, а не за квадратный метр, и в отдельных зданиях завышала средний тариф в 163 раза.

Ещё пример: ячейка Excel с форматом «30%» хранится как число 0,3, и формат теряется при чтении. Парсер понимает обе формы, а значение больше 100% роняет строку в отчёт, а не пишет мусор в базу.

Медиа для тысяч объектов

Логотипы, фотографии и планы нельзя загружать по одному. Система генерирует пустой ZIP-шаблон со структурой папок по всем объектам базы: клиент раскладывает файлы по папкам и загружает архив обратно, привязка идёт автоматически по именам. Несопоставленные файлы попадают в очередь на ручную привязку, шаблон пересобирается из актуальной базы по расписанию.

Так привязано и отображается 1 678 логотипов: 749 у партнёров, 709 у зданий, 207 у локаций и 13 у лицензий. Где логотипа нет, работает генератор изображений-заглушек, поэтому на витрине нет пустых мест. Отдельно клиенту передан точный список из 233 партнёров без логотипа — без выдуманных сопоставлений.

Витрина без выдуманных чисел

Мы прошли по публичным страницам и привели счётчики к живым данным. Главная считала помещения по материализованному представлению без учёта видимости и показывала все 88 тысяч записей рядом с «19 зданий». На странице лицензий стояли статические «45+ типов и 20+ свободных зон», на странице локаций — «500+» и «15K+», хотя соседний блок той же страницы уже выводил реальные значения.

Принцип по всему проекту простой: в поле либо реальные данные, либо честная заглушка, либо блок скрыт. Выдуманных чисел на витрине нет.

Эксплуатация

Для клиентской приёмки понадобилось временно показать на сайте только тестовый набор данных. Сделали обратимо: сняли полный дамп базы, включили тестовый режим одной транзакцией, откат — восстановлением дампа. Клиент проверял на чистом наборе, боевые данные не пострадали и вернулись в один шаг.

Деплой идёт из общей ветки с обязательным перезапуском фоновых воркеров и пересборкой админки; процедуры задокументированы, план отката есть. Правила импорта покрыты функциональными тестами: уникальность, прослеживаемость, конфликты, разбор процентов и сквозной round-trip экспорта и импорта.

Посчитаем ваш проект

Расскажите про задачу — вернёмся со сроком, составом работ и вилкой бюджета.

Спроектируем импорт, который не теряет данные молча Соберём каталог с прослеживаемостью значения до ячейки исходного файла Возьмём на себя эксплуатацию: обратимые изменения, дампы, план отката

Наши клиенты

Работаем и с небольшими компаниями, и с крупным бизнесом. Успех проекта меряем не сдачей работ, а тем, сколько лет клиент остаётся с нами.

ФК Зенит ФК Зенит
Родные просторы - Девелоперская компания Родные просторы - Девелоперская компания
FMA FMA
Торговый дом Лакомка Торговый дом Лакомка
Пикалёвская сода Пикалёвская сода
1Sportal 1Sportal
Благовещенский собор Благовещенский собор
TIKWA TIKWA
Морелли Морелли
Двери Нева Двери Нева
Прораб Нева Прораб Нева
Ещё работы

Другие проекты

Похожие задачи, которые мы уже закрывали в этом направлении.

Обсудить проект