Как завезти данные из старой системы и не сломать дом. Модули: 6.16.26.36.47.9. Подробно с реальными ловушками: kb/migration/.
Загрузить CSV можно за минуту. Неделями занимает всё остальное: решить, что переносить, перевести поля и значения, почистить, проверить, что перенеслось ровно то, что нужно. Цикл «загрузил, сверил, поправил» повторяется несколько раз в sandbox, прежде чем данные пойдут в production.
Шаги 5-7 крутятся несколько раз. Правило: исправляют правило преобразования и грузят заново, а не правят записи руками после загрузки.
Ребёнок не может сослаться на родителя, которого ещё нет. Поэтому объекты грузят слоями. Users, record types и значения picklist обычно не грузят, а сопоставляют по таблице соответствий.
У каждой загружаемой записи свой ключ из старой системы (External ID). По нему ребёнок находит родителя без знания новых Salesforce Id.
Ключ из старой системы кладут в поле с галочкой External ID. Тогда загрузка делает upsert: если запись с таким ключом уже есть, она обновляется, если нет, создаётся. Повторный прогон того же файла не создаёт дублей, а ребёнок ссылается на родителя по старому ключу.
В CSV для Bulk API и sf data import колонка ссылки называется Account.Legacy_Id__c. В Data Loader то же самое выбирается на шаге связанных объектов при upsert.
В Revenue Cloud часть записей нельзя загрузить вообще: историю актива (AssetAction, AssetStatePeriod) строит движок, когда активируют order. Поэтому работают так: загружают заказы черновиками, проверяют до активации, активируют, и платформа сама строит активы. После активации цены становятся историей актива, и исправить её обычными средствами почти невозможно.
Это упрощение. Полный порядок, исключения и что делать с открытыми сделками: kb/migration/case-legacy-cpq-to-revenue-cloud.md. Стратегии смены продуктовой модели: kb/migration/product-model-change-strategies.md.
| Ловушка | Как проявляется | Правило |
|---|---|---|
| Бизнес-определение, которого нет в данных | «Переносим только активных клиентов», а поля «активный» нет | Каждый критерий переводи в конкретное поле и условие, считай SOQL-запросом, подписывай у клиента |
| Похожие символы в значениях | Стадия с длинным тире вместо дефиса не попадает в фильтр | Выгружай реальные уникальные значения, а не набирай их руками |
| Пустая дата окончания выглядит как живая подписка | Миллионы «вечных» строк попадают в scope | Пустые значения проверяй отдельным запросом и решай явно |
| Значение по умолчанию в picklist | Поле не загрузили, а у всех записей стоит одно значение | Каждое поле с default в mapping явно: грузим или оставляем |
| Системные поля нельзя загрузить | Загрузка игнорирует или падает на поле, которое ставит платформа | Проверь describe: createable и updateable до того, как обещать клиенту |
| Автоматизация срабатывает на каждую запись | Загрузка медленная, письма клиентам, ошибки лимитов | Bypass через настройку (custom permission или custom setting), а не выключение flows руками |
| Место в org | Загрузка остановилась на середине: STORAGE_LIMIT_EXCEEDED | Проверь storage до загрузки и оцени объём |
| Устаревшая копия источника | Числа в отчёте не сходятся с тем, что видит клиент | Считай по самому свежему источнику и пиши, откуда число |
Полный список с примерами запросов: kb/migration/selection-criteria-lessons.md и kb/migration/data-migration-traps.md.