Универсальная обработка переноса данных из основной конфигурации в расширение

Публикация № 1304175 05.10.20

Разработка - Обработки - Универсальные обработки

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

Преамбула

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

Использование расширений позволяет снизить затраты времени на обновление, за счет наличия только конфигурации поставщика и отсутствия основной конфигурации.

Зачастую появляется необходимость переноса уже написанных доработок в расширение. И, в этом случае, возникает задача по переносу данных, так как фактически объекты доработок основной конфигурации и объекты расширения - это разные объекты. Можно в этом случае воспользоваться конвертацией данных, тем более, что сама конвертация не будет сложной, так как структура объектов основной конфигурации и расширения зачастую повторяется. Однако, такую конвертацию придется писать для каждого случая переноса доработок в расширение.

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

 

Как это работает

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

Заполнение дерева метаданных

Далее необходимо каждому объекту метаданных расширения указать соответствующий ему объект основной конфигурации, при этом соответствие реквизитов объектов заполнится автоматически по наименованию реквизита. В случае различия в наименовании можно сопоставить реквизиты вручную.

Выбор объекта метаданных

Соответствие реквизитов

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

 

Резюме

Обработка позволяет без лишних затрат времени и написания правил конвертации перенести данных из объектов основной конфигурации в расширение.

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

 

Обновления

 

1.0.8. Список изменений:

  • Исправлена ошибка переноса реквизитов составного типа.
  • Добавлена возможность сохранение и восстановления данных формы в/из файл(а).

 

1.0.7. Добавлена сортировка в список выбора объектов конфигурации.

 

1.0.6. Список исправлений:

  • Добавлено поле "Тип (Объект расширения)" для отображения типов реквизитов объектов расширения. По двойному щелчку на эту ячейку можно перейти к строке объекта расширения.
  • Добавлено диалоговое окно с подтверждением действия перед переносом данных.
  • Добавлена возможность сопоставления объектов по произвольному алгоритму.

 

1.0.5. Исправлены возможные ошибки при подборе из списка в поле "ОбъектКонфигурации". Исправлены ошибки автоподбора. Добавлен поиск по дереву.

 

1.0.4. Список исправлений:

  • Исправлена ошибка переноса данных подчиненных регистратору регистров.
  • Добавлена возможность сохранения параметров табличной части сопоставления.
  • Добавлена закладка с протоколом переноса данных.
  • Добавлен контроль сопоставления объектов метаданных помеченных для переноса данных непосредственно перед самим переносом.
  • В табличной части соответствия объектов метаданных добавлено поле для пометки определенных объектов расширения для переноса данных.
  • В табличной части соответствия объектов метаданных добавлено поле "Сопоставлено" для отображения состояния сопоставления объектов метаданных.
  • В табличной части соответствия объектов метаданных устранена возможность ручного редактирования текста поля "Объект расширения".
  • В табличной части соответствия объектов метаданных из списка автоподбора в поле "Объект конфигурации" исключены объекты расширения, для которого выполняется сопоставление.

 

1.0.3. Добавлен прогресс бар. Исправлены ошибки переноса перечислений.

 

1.0.2. Добавлено сопоставление перечислений. Исправлены ошибки переноса справочников, регистров сведений, табличных частей.

 

1.0.1. Удалены отладочные комментарии при записи объектов  расширения

Скачать файлы

Наименование Файл Версия Размер
Универсальная обработка переноса данных из основной конфигурации в расширение:

.epf 1,21Mb
53
.epf 1.0.8 1,21Mb 53 Скачать

Специальные предложения

Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. the1 894 06.10.20 09:07 Сейчас в теме
ранее дописанный функционал, необходимо перенести в расширение

обработка осуществляет перенос данных из объектов основной конфигурации в объекты расширения

Так функционал переносит или данные? Из описания следует, что данные.
EliasShy; Hatson; +2 Ответить
2. Hatson 433 06.10.20 11:01 Сейчас в теме
(1)Вот так вот скачаешь, запустишь, а потом окажется: ....не тысячу, а десять тысяч, и не рублей, а долларов, и не в лотерею, а в карты, и не выиграл, а проиграл ))))))))))))
3. biz-intel 827 06.10.20 11:19 Сейчас в теме
Конечно же данные )
Спасибо за замечание, поправил аннотацию.
4. AutomationStock 07.10.20 06:26 Сейчас в теме
Зачем городить этот огород если есть старая добрая КД, при этом очень даже бесплатная.
5. mikl79 114 07.10.20 07:43 Сейчас в теме
6. red80 07.10.20 09:16 Сейчас в теме
(4) Зачем городить этот огород если есть старая добрая типовая "Выгрузка и загрузка данных XML.epf" с ИТС диска. Из доработанной конфигурации добавленные объекты выгружаем, в расширение загружаем. Галочку "Выгружать при необходимости" для всех объектов снимаем. Главное, чтобы порядок объектов метаданных в конфигурации и расширении совпадал.
7. biz-intel 827 07.10.20 12:00 Сейчас в теме
Старая добрая типовая "Выгрузка и загрузка данных XML.epf" работает для полностью идентичных конфигураций. Тут должны совпадать полностью наименования всех объектов. Так же нужно две отдельных базы для переноса данных и проверки. Если работать по такому сценарию, то конечно работаем старой доброй типовой :)

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

КД в этом случае тоже подошла бы как одноразовый вариант, но, если есть достаточно большое количество разработок, требующих перевода на расширение, то на каждый такой случай писать правила КД, мне лично кажется не оптимально.
8. red80 07.10.20 12:31 Сейчас в теме
(7) Как у вас все сложно :)
Переносим изменения из конфигурации в расширение копи-пастой, у вас получатся полностью идентичные конфигурации. Да, должно быть два открытых конфигуратора - один с измененной конфигурацией, другой с исходной+расширение. Переносим данные и дальше меняем объекты как душе угодно.
Это гораздо проще и быстрее обработок и КД.
9. biz-intel 827 07.10.20 12:56 Сейчас в теме
(8) В случае одного клиента, да. В случае перевода на расширение у большого количество пользователей и при наличии разных решений, это будет слишком трудозатратно.

Да, спасибо за комплимент, у нас все сложно :)
10. VKislitsin 650 07.10.20 14:20 Сейчас в теме
Кирилл, очень полезная штука. Есть конечно ошибки, которые пришлось поправить (например в стандартных реквизитах справочника может быть отключен Код).
У меня вопрос: а есть ли у Вас методика по переносу функционала из конфигурации в расширение? Тоже столкнулись с такой необходимостью. Речь идет о переносе всех добавленных объектов (какие возможно перенести в расширение) - справочники, документы, регистры и т.д. Всё это имеет свои формы и т.д.
11. biz-intel 827 07.10.20 15:17 Сейчас в теме
Спасибо, с отключенным кодом поправим...

Именно методики переноса функционала на настоящий момент нет. Однако что приходилось делать, так это менять тексты модулей по определенному алгоритму скриптом на питоне. В принципе cfe - это zip-архив с файлами xml, и, теоретически можно сделать выгрузку конфигурации в файлы, распаковать cfe в отдельный каталог и как-то перенести туда все добавленные объекты.

Или же нужно смотреть в сторону EDT и написание плагинов, но как-то EDT пока-что мне кажется сыроват, может быть я и ошибаюсь.

Спасибо за идею, возможно и поработаем в этом направлении.
12. biz-intel 827 07.10.20 15:19 Сейчас в теме
(11) Уточнение, архиватором cfe не раскрыть, но можно выгрузить расширение в xml-файлы
13. VKislitsin 650 07.10.20 15:47 Сейчас в теме
(11)
теоретически можно сделать выгрузку конфигурации в файлы, распаковать cfe в отдельный каталог и как-то перенести туда все добавленные объекты.

Не, такой фокус не пройдет. По крайней мере пока соответствующие объекты в Конфигурации не удалить. Потому что все идентификаторы типов будут дублироваться и в Расширении и в Конфе. Если бы работал, можно было бы просто выгрузить конфу в файлы и нужные файлы загрузить в расширение, пакетным режимом с ключем /LoadConfigFromFiles.

Насчет кода в обработке еще ошибки:
Вот в таких конструкциях далеко не всегда метод Метаданные() срабатывает, например если реквизит имеет примитивный тип (скажем "булево")
СправочникРасш[РеквизитИЛИТЧ.ОбъектРасширения].Метаданные().Имя


И запись объектов, думаю стоит раскомментировать, пока не посыпались отзывы что не работает.
//СправочникРасш.Записать();
//ДокументРасш.Записать();
и т.д.


А из удобств не помешало бы сохранение настроек формы и выбор какие объекты переносить, а какие - нет, крыжиками.
14. biz-intel 827 07.10.20 15:57 Сейчас в теме
СправочникРасш[РеквизитИЛИТЧ.ОбъектРасширения].Метаданные().Имя вот это не должно применяться для примитивных типов, но проверим, спасибо.

Запись тоже раскомментируем, это в целях отладки видимо осталось.

Не, такой фокус не пройдет. По крайней мере пока соответствующие объекты в Конфигурации не удалить. Потому что все идентификаторы типов будут дублироваться и в Расширении и в Конфе. Если бы работал, можно было бы просто выгрузить конфу в файлы и нужные файлы загрузить в расширение, пакетным режимом с ключем /LoadConfigFromFiles.


Тут можно попробовать перед загрузкой сгенерировать идентификаторы
17. VKislitsin 650 07.10.20 16:15 Сейчас в теме
(14)
вот это не должно применяться для примитивных типов, но проверим, спасибо.

Здесь мне пришлось исправлять именно потому что применялось.

(14)
Тут можно попробовать перед загрузкой сгенерировать идентификаторы

Мне такая мысль первым делом тоже пришла в голову. Но дело в том, что эти идентификаторы ведь не в одном месте фигурируют. Им нужно искать соответствия в других файлах и там такие же подставлять. И ведь речь идет не только об идентификаторе самого объекта. Их там целая куча - идентификаторы типов, форм, каждого реквизита.
15. biz-intel 827 07.10.20 16:06 Сейчас в теме
Вот, например, справочник номенклатура, при выгрузке файлов находится тут:

Catalogs\Номенклатура.xml

Вот, что внутри:

<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.10">
	<Catalog uuid="fc59acc3-f1f7-4e3f-96da-e580f2c5a88f">
		<InternalInfo>


Нас интересует элемент
<Catalog uuid="fc59acc3-f1f7-4e3f-96da-e580f2c5a88f">


Конечно придется писать скрипт для этого уже вне средств 1С
16. biz-intel 827 07.10.20 16:08 Сейчас в теме
Хотя если совсем уж извратиться, то можно и сделать обработкой на 1С :)
18. JohnyDeath 299 08.10.20 08:31 Сейчас в теме
Обычно наоборот происходит - разрабатывают в расширении и если всё устаканилось, то переносят в основной продукт (конфигурацию)
19. VKislitsin 650 08.10.20 08:41 Сейчас в теме
(18) Евгений, абсолютно согласен. Но "обычно" - это не "всегда" :)
Сейчас вот как раз встала задача вытащить всё в расширение. Слишком трудно стало поддерживать несколько разных конфигураций с внедренным своим блоком.
JohnyDeath; +1 Ответить
22. RocKeR_13 947 12.10.20 12:48 Сейчас в теме
(18) Если основной продукт - это распространяемая конфигурация на поддержке, а расширения - это временные патчи, то да, соглашусь. Если же идет доработка типовой конфигурации и нет конфликтов в применении расширений (когда несколько расширений изменяют, например, одну и ту же процедуру), то не вижу особого смысла переносить функционал из расширения в основную конфигурацию. Разве что, если расширений в базе несколько десятков, а конфигурацию расширениями изменяют несколько сторонних разработчиков, причем не особо согласовывая свои действия между собой. Пока у клиентов встает все-таки вопрос переноса доработок из основной конфигурации в расширения.
biz-intel; +1 Ответить
20. vitek1 10.10.20 18:54 Сейчас в теме
Заменяются ли ссылки в связанных объектах? Т.е. например необходимо перенести один справочник основной конфигурации в расширение. Причем ссылки на элементы этого справочника используются в документах и регистрах. В расширении создан новый справочник с такой же структурой. Обработка перенесет только данные самого справочника? Или также заменит ссылки в документах и регистрах со справочника основной конфигурации на ссылки справочника в расширении?
21. biz-intel 827 12.10.20 12:37 Сейчас в теме
(20) Ссылки заменяются. При переносе данных идет проверка, на различие типов данных в расширении и основной конфигурации.
23. php5 19 15.10.20 12:23 Сейчас в теме
ИМХО, данные лучше хранить в основной конфигурации, а не в расширении. Возможна ситуация, когда расширение отвалится и все данные будут потеряны.
24. biz-intel 827 15.10.20 13:29 Сейчас в теме
(23) Что значит "отвалится"? Не подключится при запуске 1С при проверке, будет отключено пользователем? Или будет удалено вручную в конфигураторе и будет выполнено обновление конфигурации БД? От этого очень сильно зависит "судьба" данных.

По сути расширение - это обычные таблицы реляционной БД, файловой, MS SQL, Postgres, в зависимости от того файловая или серверная база. Если сказать упрощенно, то при отключении расширения платформа просто не использует эти таблицы в работе, и, как только работа расширения будет восстановлена, таблицы снова будут использоваться со всеми данными, которые были в них до отключения.

Можно самому в этом убедиться, создав расширение, добавив туда справочник. Запустить пользовательский режим, добавить в этот справочник несколько элементов и отключить расширение (сняв флаг "Активность"). Перезапустить 1С, этот справочник "пропадет". Затем включить расширение снова (установив флаг "Активность"), перезапустить 1С. Этот справочник снова появится с теми элементами, которые в нем были до отключения расширения.

А вот есть удалить в конфигураторе и сохранить конфигурацию БД, то таблицы будут удалены и данные потеряны. Но это ведь осознанное действие, а не форс-мажор и отключение расширения по каким-либо причинам (например изменился режим совместимости основной конфигурации)
25. php5 19 15.10.20 14:28 Сейчас в теме
(24) Часто при работе с расширениями приходится их удалять из базы физически.
Могу привести 2 примера:

1. Обновление типовой КА 2.4 не смогло примениться при наличии расширения. Пришлось физически удалять (отключение не помогало), чтобы нормально отработали типовые обработчики (первый раз подобная проблема произошла 1.5 года назад.

2. При выгрузке из тестовой базы - объединение в рабочей отрабатывает не корректно, помогает только перезаливка расширения.

Я веду к тому, что если данные хранятся в расширении, и возникнет необходимость удалить расширение и перезалить, то данные потеряются т.е. для себя сделал вывод не хранить данные в расширениях. В любом случае хранение данных в боевой базе предополагает добавление новых объектов в конфигуратор, что не является критичным при обновлении базы.
26. biz-intel 827 15.10.20 14:59 Сейчас в теме
(25) 1. Типовая КА 2.4 без изменений вообще, без основной конфигурации? Какие именно обработчики не смогли отработать и какие были при этом ошибки? Сколько было расширений подключено? Что именно было в расширении заимствовано из конфигурации? Такой пример вызывает еще больше вопросов.

2. Зачем делать объединение из тестовой базы, если можно просто загрузить расширение из файла *.cfe просто в пользовательском режиме, при этом потери данных не будет.

Использование расширений вместо изменения конфигурации дает возможность не использовать основную конфигурацию вообще, при доработке функционала типовых конфигураций. Это как минимум увеличивает скорость обновления раза в 1,5 или даже больше, так как пропускается этап сравнения и объединения. Конечно может понадобится последующая адаптация расширений, но это уже другой вопрос, тут все зависит от того как сделано расширение, сколько и как было заимствовано объектов конфигурации и т.д.
27. biz-intel 827 18.11.20 10:18 Сейчас в теме
Вышло обновление 1.0.2:

Добавлено сопоставление перечислений. Исправлены ошибки переноса справочников, регистров сведений, табличных частей.

Все, кто скачал ранее, могут написать в личку вышлем новую версию.
28. biz-intel 827 20.11.20 17:46 Сейчас в теме
Обновление 1.0.3. Добавлен прогресс бар. Исправлены ошибки переноса перечислений.
29. windows98a 97 25.11.20 10:44 Сейчас в теме
Спасибо, работает!
Нет возможности переносить данные частями, по конкретным объектам метаданных, добавил галочку "выгружатьобъект". Полезно, когда объемы данных большие и выгружаешь не все сразу, что бы можно было контролить. Например нужно выгрузить только регистр сведений, для этого нужно заполнить соответствие документам регистраторам, а документы регистраторы уже были ранее выгружены, но они все равно прогружаются еще раз, потмоу что соответствие выбрано. В таком случае галочка "выгружатьобъект" избаляет от повторной выгрузки тех объектов, которые были выгружены ранее.
И проблема есть, с регистрами сведений(подчиненными регистраторам) точно(регистры накоплений не переносил, но там возможно то же самое). Выборка документов в запросе происходит без группировки по регитсратору. В итоге вместо того, что бы перенести документ 1 раз, он переносится столько раз, сколько записей в регистре по этому регистратору
30. windows98a 97 25.11.20 10:46 Сейчас в теме
(29) из аз последней проблемы у меня перенос не прошел за ночь. После устранения - прошел за 20 минут
31. biz-intel 827 25.11.20 11:43 Сейчас в теме
(30) Здравствуйте!
Благодарим Вас за комментарий. Возможность переноса данных определенных объектов уже включена в разработку и будет обеспечена в ближайших релизах.
Указанная Вами проблема с регистрами, которые подчинены регистраторам, уже учтена и будет исправлена в следующем релизе.
33. windows98a 97 03.12.20 08:12 Сейчас в теме
(31) Можно будет получить новую версию с исправленными ошибками?
34. biz-intel 827 03.12.20 11:20 Сейчас в теме
32. biz-intel 827 30.11.20 10:50 Сейчас в теме
Вышло обновление 1.0.4. Со списком изменений можно ознакомиться в описании публикации
35. allo4kapower 25.02.21 16:14 Сейчас в теме
(32)Данные справочника не переносятся
36. biz-intel 827 25.02.21 16:46 Сейчас в теме
(35) Добрый день! А можете уточнить что именно не переносится? Сами элементы справочника, данные по ссылкам в реквизитах?
37. allo4kapower 02.03.21 12:06 Сейчас в теме
(36) Не переносятся объекты конфигурации, которые дописаны, и соответственно их нет в конфигурации поставщика.
38. allo4kapower 02.03.21 12:10 Сейчас в теме
45. uribur 8 23.03.21 14:46 Сейчас в теме
(38) ))) тоже все в однерках )))
39. allo4kapower 02.03.21 13:58 Сейчас в теме
(36)Отбой, просто при выборе нет в списке , но если вводить название, то подцепляется.
40. biz-intel 827 02.03.21 15:24 Сейчас в теме
но лучше поправить, должно и при выборе подцепляться, спасибо за отзыв
41. biz-intel 827 04.03.21 17:05 Сейчас в теме
Добавили сортировку в список выбора. Теперь искать будет легче. Но вводом названия все равно удобнее.
42. Pim 168 14.03.21 20:33 Сейчас в теме
Косячок: не переносит стандартные реквизиты справочника. Переношу справочник состоящий только из наименования. Элементы созданы, а наименование пустое...
43. biz-intel 827 15.03.21 12:48 Сейчас в теме
Спасибо, проверим, поправим
44. uribur 8 23.03.21 14:41 Сейчас в теме
Прикупил чудо обработку.
В целом все отлично, сэкономил свое время и уже сутки сижу и дописываю обработку под свои нужды.
Из косяков:
1. не переносит и не обновляет стандартные реквизиты.
2. не переносит группу и владельца
3. не создает элемент справочника группа.
4. ломается при попытках обработать табличные части справочников и документов.
В остальном, все вопросы ключевые решила.
Если автору будет интрересно, то могу прислать доработанну обработку, для улучшения своего кода.
В целом все норм! Спасибо.
47. lvk 21.05.21 17:38 Сейчас в теме
(44) Юрий, добрый день! У меня возник вопрос с таб.частями документов. Если есть возможность, поделитесь обработкой с доработками
48. uribur 8 06.06.21 10:37 Сейчас в теме
(47) обратитесь к разработчику, все такие это его интеллектуальная собственность, я не могу передавать неоплаченную разработку.
46. biz-intel 827 23.03.21 15:13 Сейчас в теме
Спасибо за отзыв, будем исправлять
49. Cerberdm 40 21.07.21 12:37 Сейчас в теме
Не сработало, переношу данные независимого, непереодического регистра сведений:
Метод объекта не обнаружен (Метаданные)
{ВнешняяОбработка.УниверсальнаяОбработкаПереносаДанных.Форма.Форма.Форма(689)}: Если ОбъектРасш.Метаданные().Реквизиты[Реквизит.ОбъектРасширения].Тип.СодержитТип(ТипЗнч(ОбъектКонф[Реквизит.ОбъектКонфигурации])) Тогда
{ВнешняяОбработка.УниверсальнаяОбработкаПереносаДанных.Форма.Форма.Форма(665)}: ПеренестиОтдельныйРеквизит(ЗаписьРегистрРасш, ВыборкаРегистрКонф, ДанныеРегистра);
{ВнешняяОбработка.УниверсальнаяОбработкаПереносаДанных.Форма.Форма.Форма(634)}: ЗаполнитьИЗаписатьЗаписиРегистраРасширения(ТекущийОбъект, РодительОбъектаМетаданныхМенеджер, ВыборкаРегистрКонф)
{ВнешняяОбработка.УниверсальнаяОбработкаПереносаДанных.Форма.Форма.Форма(462)}: ПеренестиДанныеНезависимогоРегистраКонфигурации(ТекущийОбъект, РодительОбъектаМетаданныхМенеджер);
{ВнешняяОбработка.УниверсальнаяОбработкаПереносаДанных.Форма.Форма.Форма(1402)}: ПеренестиДанныеОбъектовКонфигурации(ИдентификаторКорневогоЭлементаДерева, ИдентификаторТекущегоОбъекта);
{mngcore/MessageBox.clf(4)}: Close(-100);
50. biz-intel 827 21.07.21 12:43 Сейчас в теме
(49) Отправил вам в личку ссылку на последнюю версию
Оставьте свое сообщение

См. также

Публикаций не найдено

Попробуйте расширить область поиска, проверьте поисковый запрос и повторите попытку.

Или закажите индивидуальную разработку вашего решения.

Создать заказ на разработку