Rules: integration
Правила: импорт данных (IMPORT)
-
Ассистент ОБЯЗАН осознанно выбирать стиль импорта:
- плоские файлы (
CSV,XLS,DBF,TABLE) -> предпочестьIMPORT ... TOилиFIELDS - вложенные
JSON/XML, структуры родитель-потомок, пространства имён или сопоставлениеEXTID-> предпочесть импорт через форму - построчные интеграционные ответы
-> предпочесть
FIELDS ... DO
- плоские файлы (
-
Для плоских импортов, требующих валидации, дедупликации, многопроходной обработки или постобработки, ассистенту СЛЕДУЕТ сначала складывать данные в
LOCAL-свойства, обычно поINTEGER-строке, а затем обрабатывать их отдельным проходомFOR imported(INTEGER i). -
Ассистенту СЛЕДУЕТ использовать
FIELDS ... DO, когда импортируемые значения используются лишь однажды и введение переиспользуемых локальных свойств добавило бы шум. -
Ассистенту СЛЕДУЕТ указывать сопоставление колонок явно, когда внешний шаблон фиксирован или разрежен.
Последовательное сопоставление без явных идентификаторов колонок допустимо только когда сам порядок колонок является согласованным интерфейсом.
-
Для импорта через форму ассистент ОБЯЗАН объявить выделенную форму импорта до использования.
Форма ОБЯЗАНА использовать один объект на группу объектов с числовыми или конкретными пользовательскими классами.
Форме СЛЕДУЕТ отражать внешнюю структуру через:
FILTERSдля связей родитель-потомокEXTID,FORMEXTID, группы иATTRтолько там, где этого требует внешняя схема — массив на корневом уровнеJSONкак раз такое место (правило 6)
Ассистент ОБЯЗАН помнить, что импорт в форму отменяет ожидающие изменения импортируемых свойств формы в текущей сессии.
-
Для массива на корневом уровне
JSONассистент ОБЯЗАН задать группе объектов формы импорта имя экспорта / импортаvalue(OBJECTS receipts = INTEGER EXTID 'value'): такой файл платформа читает как{ "value" : [ ... ] }(см. предопределенное значение).Группа объектов, чьему имени экспорта / импорта не соответствует ни один ключ файла, импортирует ноль записей без ошибки и без предупреждения, поэтому новую форму импорта ассистент ОБЯЗАН проверить на непустом примере.
-
После импорта формы ассистент НЕ ДОЛЖЕН итерировать по
imported[INTEGER], если на форме нет фильтра с ним (FILTERS imported(receipts)): импорт формы записывает данные только в свойства и фильтры формы. Без фильтра эту роль играет промежуточное свойство, которое заполнено всегда.Ассистент НЕ ДОЛЖЕН указывать одно свойство-признак в фильтрах нескольких групп объектов: каждая группа нумерует свои записи с 0, и признаки смешиваются. Каждой следующей группе нужно собственное
LOCAL-свойство-признак. -
Ассистент ОБЯЗАН явно выбирать опции формата, когда от них зависит внешний контракт:
HEADER/NOHEADERSHEETCHARSET
Ассистенту СЛЕДУЕТ предпочитать
HEADERдля стабильных шаблоновCSV/XLS, потому чтоNOHEADERможет незаметно сопоставить отсутствующие или неверно типизированные колонки вNULL. -
Ассистент ОБЯЗАН валидировать ссылочные бизнес-ключи до создания или обновления постоянных объектов.
Типичные ключи —
id,number, коды партнёров или товаров и внешние ссылки.Каждая ссылка ДОЛЖНА проверяться в отдельном
FORчерезGROUP SUM 1 BYпо импортируемым значениям ключей.По возможности ассистенту НЕ СЛЕДУЕТ записывать разрешённые ссылки в отдельный
LOCALдо основной логики импорта.Отсутствующие мастер-данные или некорректные данные ДОЛЖНЫ останавливать импорт или выдавать понятную ошибку.
-
Ассистенту СЛЕДУЕТ разделять сырой импорт и доменное разрешение:
- сначала разобрать файл или данные в локальные свойства или форму импорта
- затем проверить ссылки, такие как товар, партнёр, статус, тип или другие справочники
- только потом создавать или обновлять доменные объекты
-
Для запускаемых пользователем пакетных импортов и внешних интеграций ассистенту СЛЕДУЕТ изолировать сохранение в
NEWSESSIONи СЛЕДУЕТ выполнятьAPPLY;после доменных записей одного импорта.В какой сессии выполняется импорт, как в неё попадает буфер верхней сессии и что следует за
APPLY;, определяют правила сессий изменений из статьи о доменной логике (lsfusion_get_guidance(rules='logic')). -
Ассистент НЕ ДОЛЖЕН частично сохранять неудавшийся импорт молча. Для ошибок, которые ассистент обнаруживает сам (отсутствующие ссылки, некорректные данные, валидация до
APPLY), ему СЛЕДУЕТ использоватьMESSAGE,RETURN,throwExceptionили явный флаг неудачи, согласованно с вызывающей стороной:- интерактивный импорт ->
MESSAGE - API или фоновая интеграция -> исключение или явное состояние неудачи
- интерактивный импорт ->
-
Для импортов-синхронизаций «создать-или-обновить» ассистент ОБЯЗАН разделять создание объектов и обновление свойств.
Ассистент ОБЯЗАН делать один отдельный проход, только создающий недостающие объекты.
FOR— один из способов его записать. Множественная формаNEW ... WHERE ... TOсоздает объект на каждый подходящий набор одной операцией и предпочтительна везде, где подходит.Если импортируемые значения ключей могут быть неуникальны, проход создания СЛЕДУЕТ итерировать по сгруппированным ключам через
GROUP SUM ... BY, а не по сырым импортируемым строкам.Затем ассистент ОБЯЗАН обновить свойства найденных объектов вторым отдельным проходом — прямое
<- ... WHEREменяет все подходящие наборы разом, аFORнужен только там, где тело делает то, чего множественное изменение не умеет.Ассистент НЕ ДОЛЖЕН смешивать создание объектов и обновление свойств в одном проходе для импортов-синхронизаций.
Если требуется полная синхронизация, ассистенту СЛЕДУЕТ добавить явный шаг удаления.
-
LOCAL-свойства промежуточного хранения, используемые одним действием импорта, ДОЛЖНЫ объявляться внутри этого действия. Уровень модуля — дляLOCAL, который использует форма импорта или разделяют несколько связанных действий. -
Импортируемый признак, отсутствие которого должно передаваться как
NULL, ДОЛЖЕН объявляться вFIELDSсNULL: иначе пропущенное значение заменяется значением по умолчанию класса (0для числа).
Правила: экспорт данных (EXPORT)
Выбор источника экспорта
Данные экспортируются оператором EXPORT.
-
Экспорт списка свойств (
EXPORT FROM ...) СЛЕДУЕТ использовать, когда результат — одна плоская таблица колонок и структура выгрузки не совпадает ни с одной формой. -
Экспорт формы (
EXPORT formName ...) СЛЕДУЕТ использовать, когда выгрузка повторяет уже существующую форму или когда в результате нужна иерархия групп объектов. Иерархия сохраняется только в JSON и XML. В плоских форматах каждая группа объектов дает отдельный файл, поэтому для них приемники перечисляются по группам в блокеTO— только для нужных групп: не попавшая в список группа просто не экспортируется. -
Форму, созданную исключительно ради выгрузки, СЛЕДУЕТ объявлять рядом с действием экспорта и НЕ СЛЕДУЕТ добавлять в навигатор.
Явное указание того, что влияет на результат
-
Формат СЛЕДУЕТ указывать явно даже тогда, когда нужен JSON: умолчание делает выгрузку зависимой от того, что читающий код помнит про умолчание.
-
Условие
WHEREСЛЕДУЕТ указывать явно. Без него условием считается дизъюнкция всех экспортируемых свойств, то есть в выгрузку попадут наборы объектов, у которых заполнено хотя бы одно поле, — это почти никогда не совпадает с нужным набором строк. -
Идентификаторы колонок СЛЕДУЕТ задавать явно (
columnId = expr). Умолчаниеexpr1, ...,exprNпривязывает имена полей во внешнем формате к порядку выражений, поэтому вставка колонки в середину списка молча меняет контракт выгрузки. -
ORDERСЛЕДУЕТ указывать явно всегда, когда принимающая сторона зависит от порядка строк. Выражения в нем произвольны и не обязаны входить в список экспортируемых — выражение сортировки добавляется во внутренний запрос скрытой колонкой и в результат не попадает, — поэтому колонку СЛЕДУЕТ включать в выгрузку только тогда, когда она нужна получателю, а не ради того, чтобы по ней отсортировать. -
В иерархических форматах свойство со значением
NULLпропускается в записи (в JSON отсутствует ключ, в XML — элемент), а плоские форматы (CSV, XLS, XLSX, DBF) сохраняют колонку и записывают пустую ячейку. Поэтому в JSON отсутствующий ключ означаетNULL, а не сбой выгрузки (для свойств формы соSHOWIFвключение определяется значениемSHOWIF: не-NULLзначение может быть пропущено, аNULL— выгружено). -
Когда одной выгрузкой возвращается несколько скалярных значений (результаты проверок, диагностика), отдельные колонки
EXPORT FROM a = ..., b = ...СЛЕДУЕТ предпочитать одной склеенной строке:NULLубирает только свой ключ, тогда как в конкатенации через+он обнуляет весь результат. Чтобы ключ присутствовал всегда, значение оборачивается вOVERRIDE ..., <умолчание>(при экспорте формы МОЖЕТ использоваться опция свойстваEXTNULL). Выгрузка выражений без параметров сохраняет свою единственную запись, даже когда все значенияNULL. Для строк, порождаемых параметрами выгрузки, умолчаниеWHERE(дизъюнкция) выбрасывает полностьюNULL-запись — условиеWHEREСЛЕДУЕТ задать явно или добавить константную колонку.
Опции формата
-
Опции, у которых умолчание отличается для разных форматов, СЛЕДУЕТ задавать явно: наличие строки заголовка (
HEADER/NOHEADER) в CSV, XLS, XLSX, разделитель CSV (по умолчанию;) и кодировку (CHARSET, по умолчаниюUTF-8, а для DBF —CP1251). -
NOESCAPEв CSV МОЖЕТ использоваться только тогда, когда разделитель гарантированно не встречается в данных. В остальных случаях СЛЕДУЕТ оставлятьESCAPE. -
Кодировку СЛЕДУЕТ определять требованиями принимающей стороны, а не значением по умолчанию: получатели DBF-файлов обычно ожидают однобайтовую кодировку, отличную от
UTF-8.
Приемник результата
-
Свойство-приемник в
TOСЛЕДУЕТ объявлять локальным для действия экспорта и файлового класса (FILE,RAWFILE,JSONFILE), а не использовать общее свойство: одно свойство, разделяемое несколькими выгрузками, делает результат зависящим от порядка выполнения. -
Умолчание
System.exportFileСЛЕДУЕТ использовать только для отладочных и разовых выгрузок. -
При экспорте формы в плоский формат приемники СЛЕДУЕТ перечислять для всех выгружаемых групп объектов. Группа объектов без имени называется
root. -
Для возврата значения из действия, вызываемого внешней системой, ассистент ОБЯЗАН использовать
RETURN, а неEXPORT:RETURNотдаёт значение из любого места действия, в том числе послеAPPLYи из блокаNEWSESSION, тогда как результатEXPORTостаётся в той сессии, где он выполнен, и ответ приходит пустым.
Передача результата
-
Действие СЛЕДУЕТ разделять на подготовку данных, собственно
EXPORTи передачу файла получателю — записью в файловую систему, отправкой во внешнюю систему или сохранением в свойстве. Такое разделение позволяет повторно использовать выгрузку с разными способами доставки. -
Для регулярных выгрузок формирование файла СЛЕДУЕТ делать в отдельном действии без взаимодействия с пользователем, чтобы его можно было вызывать и с формы, и по расписанию.
Примеры
Первый показывает форму со списком свойств: плоский результат, чья структура
не совпадает ни с одной формой, с алиасами колонок, отбором в WHERE
и явным ORDER. Второй показывает форму с формой: существующая форма
выгружается в иерархический формат, её внешний объект передан через OBJECTS.
exportShipments (Store store) {
LOCAL exportedFile = FILE ();
EXPORT CSV ';' HEADER FROM number = number(Shipment s), date = date(s), sum = sum(s)
WHERE store(s) = store AND shipped(s)
ORDER date(s)
TO exportedFile;
}
FORM exportOrders
OBJECTS st = Store
OBJECTS o = Order
PROPERTIES(o) number, date
FILTERS store(o) = st
;
exportOrders (Store store) {
LOCAL exportedFile = FILE ();
EXPORT exportOrders OBJECTS st = store JSON TO exportedFile;
}