- PVSM.RU - https://www.pvsm.ru -
Всем привет! Меня зовут Таня, я тимлид группы разработки Axapta в компании Lamoda. В этой статье речь пойдет про разработку нашего первого проекта на платформе Microsoft Dynamics 365 For Finance and Operations.

Я расскажу про подходы, которые мы использовали, про ошибки, которые допускали, поделюсь знаниями и приобретенным опытом. Эта статья может быть интересна тем, кто начинает разработку проекта в D365 или только задумывается об этом.
Это вольная расшифровка доклада [1] с митапа Mycrosoft Dynamics 365 & Power Platform Meetup.
Наш филиал в Германии закупает товары и продает их российскому юридическому лицу. Ранее мы использовали систему Tsenit, которая позволяла вести учет только на уровне финансовых данных, но не справлялась с учетом товара и логистическими задачами. Для решения этих задач у нас были дополнительные инструменты. Данные хранились сразу в нескольких базах. Всё это отрицательно влияло на скорость и надежность всей системы.
Мы хотели, чтобы учетная система помогала немецкому филиалу сдавать отчетность, платить налоги и проходить аудиторские проверки. Прошлая ERP с трудом решала эти задачи, поэтому мы решили разработать и запустить собственную учетную систему. Наша ERP должна была объединить в единый контур финансы, бухгалтерию и логистику филиала. В качестве основного программного обеспечения мы выбрали Microsoft Dynamics 365 — бывшую Dynamics AX, она же Axapta.
Бизнесовая составляющая описана в статье “Технологии, аутсорс и менталитет” [2]. Здесь же будем говорить про техническую реализацию. Итак, нам требовалось автоматизировать несколько бизнес-процессов:
В проекте мы решили внедрить облачное решение Microsoft Dynamics 365, поскольку в немецком офисе не было ни IT-инфраструктуры, чтобы развернуть приложение, ни людей, которые бы за нее отвечали. Для небольших удаленных филиалов схема SaaS оптимальна, поскольку позволяет получить все необходимое ПО и среды разработки, чтобы начать внедрение, сразу после подписания договора с провайдером.
У нас были сжатые сроки: необходимо было выполнить всю разработку за 3 месяца. Поскольку в старой системе товарный учет велся в электронных таблицах, перенос всего набора исторических данных был бы неподъемной задачей в середине финансового года. Зато в начале отчетного периода достаточно перенести только балансы. Таким образом, запуск необходимо было произвести либо 1 января 2019 года, либо отложить его еще на год.
Наша команда не имела опыта разработки в D365. Несмотря на все обстоятельства, мы планировали максимально быстро начать этот проект. Дальше я отдельно опишу все этапы разработки. Подробно остановлюсь на каждой итерации: какой опыт мы получили и какие ошибки допустили.
Для того, чтобы быстро приступить к делу, сначала мы разработали простую архитектуру приложений. Она состояла из окружений для разработки – DevBox 1-tier окружения. Все компоненты были установлены на одном сервере/виртуальной машине: Application Object Server (AOS), база данных, Dynamics 365 Retail и Management Reporter.
Для тестирования мы решили использовать SAT окружение – Standard Acceptance Test 2- tier окружение.
2- tier окружение – это Multi-box окружение, компоненты которого устанавливаются в нескольких облачных сервисах и обычно включают в себя более одного Application Object Server (AOS). По сути, оно максимально приближено к продуктивной среде, поэтому мы решили тестировать на нем.
Мы разворачивали первые окружения разработки на имеющейся on-premise инфраструктуре, однако ее мощностей было недостаточно для дальнейшего развития проекта. Поэтому, когда к проекту подключились еще два разработчика, мы быстро и элегантно развернули для них DevBox в облаке.
Управление нашими облачными окружениями происходило через Lifecycle services портал.
Закончив с окружениями, команда приступила к разработке. Мы настроили среды разработки на Visual Studio и подключили их к контролю версий Azure DevOps, предварительно создав ветку для выгрузки кода. Далее мы разработали подход к разработке и переносу изменений на SAT окружение.
В архитектуре D365 нет слоев, весь стандартный код был разложен в модели. Модификации переносились на SAT-окружение через LCS-портал пакетом, содержащим скомпилированную модель.
Модель – это минимальная единица переноса изменений на прод, поэтому мы решили делать одну модель – одну модификацию, чтобы независимо переносить наши модификации для тестирования и далее в прод.
Для начала мы реализовали самую простую и распространенную модификацию – добавление нового поля в стандартную таблицу, его инициализации при создании записи и вывод на стандартную форму.

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

На такой простой модификации мы увидели один из основных принципов D365 – не изменение, а расширение стандартных объектов.
Следующей модификацией было создание новой формы. Теперь при создании формы требовалось обязательно указывать её паттерн. Паттерн – это шаблон, который полностью определяет структуру дизайна формы. Пока мы полностью не воспроизведем структуру, заложенную в шаблоне, наша форма не будет компилироваться. Изменить шаблон уже готовой формы невозможно. Поэтому перед началом разработки мы заранее продумывали, как будет выглядеть наша форма.



У нас также сохранялась возможность управлять дизайном формы самостоятельно. Если мы указывали pattern – Custom, то полностью сами отвечали за дизайн формы: какие объекты на ней были и с какой вложенностью.



1. Не изменять стандарт, а только расширять его.
2. Ссылаться на модель, если используем её объекты в другой модели. Это одно из отличий моделей D365 от предыдущих версий: объект существует только в одной модели.
3.В изменении свойств стандартных объектов есть ограничения. Не все свойства стандартных полей можно изменить в своих расширениях стандартных объектов. Например, расширение таблицы PurchTable – поле LineDisc. Мы можем управлять видимостью поля и меткой, а такие свойства, как обязательность и редактируемость, изменить нельзя.

4. В D365 нет джобов, все делается через классы.
5. Мы слишком мелко побили модели, и оказалось, что наш принцип “одна модификация = одна модель” не работает.
В начале второй итерации у нас были две модели, которые ссылались друг на друга. Из-за этого мы уже не могли переносить эти модификации независимо. Поэтому мы решили работать в одной новой модели, в которую потребовалось перенести все существующие модификации.
Модель в D365 – это набор исходных файлов, расположенных в отдельной директории. При компиляции они собираются в отдельную библиотеку, имеющую связь с другими библиотеками.
Поэтому слияние в одну модель на DevBox свелось к перекладыванию файлов из одной директории в другую и удалению старых директорий.
Итак, мы сбилдили новую модель, получили ее последнюю версию на каждом DevBox, после чего продолжили работать в рамках одной модели на окружениях разработки.
Естественно, мы уже перенесли пару моделей для тестирования на SAT-окружение. Поэтому надо было удалить их, и зарелизить одну новую.
Все обновления SAT-окружения делались с помощью пакетов, в том числе и удаление моделей. Мы создали пакет с пустыми моделями, которые нужно удалить, и добавили в него скрипт с названиями этих моделей. Далее собрали пакет с новой моделью и накатили на SAT-окружение. Таким образом, SAT обзавелся новой моделью.
Когда объединяли модели, мы заметили, что каждый разработчик называет расширения объектов по-своему. Договорились о правилах наименования объектов по шаблону: PurchTable.LamodaModelFormExtension, PurchTableTypeLamodaModelClass_Extension.
Также мы договорились в команде, что для одного стандартного объекта мы создаем только одно расширение и все в него вносим изменения.
Я выбрала несколько интересных модификаций, которые мы сделали на этом этапе. Они показывают возможные подходы к разработке в D365.
Задача 1
В разноске накладной по заказу на продажу необходимо было подменить номер накладной на номер из заказа. Для этого мы определили стандартный класс с возможностью расширения, который позволил нам выполнить эту модификацию.

Мы сделали расширение стандартного класса SalesInvoiceJourCreate. В его методе getNumAndVoucher() есть Next – это наш новый super, он говорит о вызове стандартного кода метода. После вызова стандартного кода мы заменили номер накладной нужным значением.
Это один из наших подходов разработки: использование расширений и добавление своего кода до или после (как вариант – и до, и после) исполнения стандартного кода.
Задача 2
Нужно было изменить отображение итогов заказа на покупку: сгруппировать итоги по номеру накладной поставщика из строк заказа на покупку. В этом случае мы не нашли места для расширения без падения производительности в два раза, поэтому сделали свой вариант итогов, не трогая стандартные.

Задача 3
Еще одна интересная модификация: в строки формы заказа на покупку нужно было добавить поля из справочника номенклатуры с возможностью фильтрации. В прошлых версиях модификация была совершенно неинтересной и решалась простым добавлением таблицы как datasource на форму и перекрытием двух методов.
В версии 7.3 мы не могли расширять методы на datasource стандартной формы. Чтобы сделать фильтрацию и не создавать для этого новую форму, мы добавили view как datasource на форму.
Возможность расширять методы на datasource появилась в версии 8.1 D365.

На этом этапе мы разработали основные модификации, необходимые для запуска проекта.
Основную разработку мы сделали в срок. Выход в Go Live состоялся, модель в проде. А перед нами встала проблема релизов только протестированных модификаций в рамках модели. Также нам хотелось облегчить процесс дебага во время тестирования модификаций и ускорить обновление тестового окружения.
В последней итерации мы добавили два окружения: билд и тест. После того как все окружения были настроены и проверены, мы упростили тестирование и научились релизить только протестированные модификации в рамках модели.
Для тестирования мы развернули 1-tier окружение и подключили его к ветке разработки в системе контроля версий. Обновление теперь состояло из получения последней версии самой модели и ее сборки. В этом окружении мы дебажили, как в обычном DevBox.

Сборка пакетов для релиза теперь осуществлялась на новом билд-окружении. Протестированные модификации переносились в новую ветку в системе контроля версий changeset’ами (пакетами изменений, выгруженными в систему контроля версий), по принципу от самых ранних к последнему.
Дальше мы деплоили пакет на SAT-окружение, где проходило пользовательское тестирование, после чего ставили пакет в расписание на LCS-портале для релиза на прод. Так мы наладили процесс релизов с использованием билд-окружения.
А ещё мы решили ревьюить не проекты, а changeset’ы по модификации, выгруженные в контроль версий.
Мы работали на облачной версии, поэтому нам необходимо было регулярно обновляться. Первое обновление было переходом с версии 7.3 на версию 8.0. Оно заняло около двух недель.
Основные проблемы мы, конечно, создали себе сами, но и победили тоже сами:
На сегодня обновление всех наших окружений занимает около 3-4 дней и проходит без привлечения разработчиков. Мы можем даже выпустить релиз одновременно с обновлением, главное, чтобы билд, SAT и прод имели одну версию.
Процесс обновления состоит из скачивания на lcs портале пакета обновления. Первыми обновляются DevBox и тест, далее обновляется билд, последними идут SAT и прод.
Весь этот опыт помог нам развивать дальше проект более продуманно. Теперь мы знаем возможности системы, можем корректнее выстраивать архитектуру, точнее ставить задачи. Выстроенные процессы вокруг проекта позволяют достаточно просто подключать к нему разработчиков, которые впервые пишут под D365.
Автор: TatyanaGorgul
Источник [3]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/erp-sistemy/350853
Ссылки в тексте:
[1] доклада: https://youtu.be/fInAjnCatMM
[2] “Технологии, аутсорс и менталитет”: https://habr.com/ru/company/lamoda/blog/460553/
[3] Источник: https://habr.com/ru/post/492678/?utm_source=habrahabr&utm_medium=rss&utm_campaign=492678
Нажмите здесь для печати.