Tutorial №3#

Используем Python#

Введение#

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

Сценарии Python, поддерживаемые платформой Scalaxi, должны использовать Python версии 3.0, как описано здесь: https://docs.python.org/3/. Полное руководство разработчика можно найти в Руководстве разработчика Python.

Версия Python, которую использует Scalaxi Platform, называется Iron Python, которая предоставляет интерфейс для кода C#. Он предоставляет две важные библиотеки, которые необходимо импортировать в начале скрипта — clr и system. Эти библиотеки предоставляют доступ к сущностям платформы Scalaxi, которые можно запрашивать и контролировать из скрипта.

Способы использования скриптов Python на платформе Scalaxi#

Существует несколько способов использования Python на платформе Scalaxi:

  1. Как часть Component Script который существует для каждого Component. Он позволяет контролировать формы приложений, разработанные и выполняемые с помощью платформы Scalaxi, а также предоставлять настраиваемые индексы, которые можно запускать в качестве реакции на какое-либо событие, например нажатие кнопки клиентом. Существует 3 основных способа использования кода Python в Component Script

  2. Основная часть Component Script, которая выполняется каждый раз при отображении формы компонента

  3. Вызов функции внутри Component Script, например, при нажатии кнопки

    1. Для этого вам нужно определить функцию внутри Component Script, а затем перейти к элементу управления пользовательского интерфейса, такому как Button, перейти в раздел «Actions» и установить для параметра «Command Type» значение «Execute Script». Затем вам нужно ввести имя и параметры вызова (если есть) вашего скрипта в предоставленные поля

    2. Использование функции внутри Component Script для событий изменения значения

      1. Для этого вам нужно определить функцию внутри скрипта компонента, а затем перейти к элементу управления пользовательского интерфейса, такому как текстовое поле и т. д., затем перейти в раздел «Events» и ввести имя вашего скрипта в поле «On value change».

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

  4. Подписавшись на изменения данных с помощью метода context.DataModel.Model.Subscribe()

    1. Самый простой способ сделать это — определить функцию перехвата всех изменений (например, def check_all_changes()) в вашем компонентном скрипте, а затем подписаться на нее.

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

  5. В рамках действия DataFlow выполните скрипт для определения логики принятия решений и преобразования данных и установки внутренних переменных, которые будут использоваться как часть сценариев DataFlow. Вы можете увидеть примеры использования скрипта Python для DataFlow в нашем Уроке №2.

Использование Python для доступа к компонентам платформы Scalaxi#

Чтобы получить доступ к компонентам платформы Scalaxi, сначала необходимо импортировать clr библиотеки IronPython, как показано ниже курсивом.

#Add IronPython library that imports system CRL (.NET) names into Python import clr

После импорта к нескольким объектам можно получить доступ изнутри скрипта Python через системную переменную «context».

Использование context.Model & context.DataModel#

context.Model & context.DataModel обеспечивают доступ к различным полям данных модели Scalaxi Platform.

Для context.Model поля данных включают как поля компонента по умолчанию, предоставляемые платформой Scalaxi, так и настраиваемые поля, добавленные разработчиком компонента.

Для context.DataModel доступны только настраиваемые поля, добавленные разработчиками компонентов.

Рекомендуется, чтобы context.DataModel использовался для доступа ко всем настраиваемым полям, а context.Model использовался только для доступа к внутренним полям компонента по умолчанию.

Если мы напишем скрипт компонента, обращающийся к этой модели, следующие переменные системной модели будут доступны в нашем скрипте через context.Model:

  • Id - внутренний идентификатор, автоматически сгенерированный платформой Scalaxi для каждого компонента. Если Id == 0, это означает, что данные компонента еще не были сохранены, это означает, что мы находимся в режиме ввода данных для этого конкретного экземпляра данных компонента, например, добавляем новый счет в наш Tutorial №1

  • createDate - внутренне установленная дата, когда экземпляр данных этого компонента был впервые создан

  • name (String) - системное user-friendly имя которое по умолчанию будет браться для показа ссылок через поля типа Catalog

  • updateDate - внутренне установленная дата последнего обновления экземпляра данных этого компонента.

  • CreatorSubject - данные, которые показывают, какой пользователь добавил экземпляр данных этого конкретного компонента. — changeAuthor — данные, которые показывают, какой пользователь последний раз обновлял данный конкретный компонент

Кроме того, следующие специфичные для компонента атрибуты будут доступны для компонента нашего руководства №1 через context.DataModel (рекомендуется) или context.Model:

  • InvoiceName - уникальное имя для нашего нового счета

  • InvoiceState - текущий статус нашего нового инвойса

  • InvoiceNumber - уникальный идентификатор номера для нашего счета

  • InvoiceDueDate - срок оплаты нашего счета

  • InvoiceTotalValue - общая стоимость нашего счета

Давайте теперь напишем пример сценария, который предварительно заполнит некоторые поля для нового счета.

#Start of the script
#Add IronPython library that imports system CRL (.NET) names into Python
import clr

#Get Component’s DataModel reference
datamodel = context.DataModel.Model
# context.Model.Id shows internal Id for the component data instance
if (context.Model.Id == 0):
# If context.Model.Id is 0, then the instance has not yet been created,
# That means we are creating a new invoice
# We will then set some fields with default values
# Since this is a new Invoice,
# We’ll set it’s status to Under Review and provide default number and name
datamodel.InvoiceNumber = 11111
datamodel.InvoiceName = 'PLEASE_SET_A_UNIQUE_NAME'
datamodel.InvoiceState = 0
#End of the script

Теперь, если мы откроем приложение Tutorial #1 и нажмем кнопку «Добавить», чтобы добавить новый счет, экран будет выглядеть следующим образом:

Tutorial 3.1


Использование context.Properties#

The way to access a UI control is to use context.Properties the following way:

context.Properties позволяет получить доступ ко всем элементам компонента и использовать, например, функции элементов управления формы пользовательского интерфейса для управления конкретным элементом управления пользовательского интерфейса.

Чтобы получить доступ к элементу управления пользовательского интерфейса, используйте context.Properties следующим образом:

context.Properties.<Internal_UI_Control_Name>.<UIControlProperty> = <Value>

Здесь <Internal_UI_Control_Name> следует заменить именем вашего элемента управления пользовательского интерфейса, который вы настроили во время проектирования. Например, в случае учебника № 1 мы установили внутреннее имя для элемента управления InvoiceState UI, как показано ниже:

Tutorial 3.2


Теперь мы можем использовать это внутреннее имя, чтобы установить следующую логику:

  1. При создании нового счета статус устанавливается на «На рассмотрении».

  2. Изменение поля статуса запрещено, то есть это поле должно быть отключено, но видно

Способ сделать это — использовать свойство Disable нашего элемента управления пользовательского интерфейса, чтобы установить его в True. Это приведет к тому, что поле появится, но не может быть изменено пользователем, который создает новый счет. Это делается путем добавления строки кода, как показано ниже:

context.Properties.UI_InvoiceStatus.Disabled = True

Добавление этого в скрипт нашего компонента приведет к следующим изменениям в нашей новой форме добавления счета.

Tutorial 3.3


Как видите, поле «Статус счета» теперь отключено.

Другим часто используемым полем context.Properties для управления элементами управления пользовательского интерфейса является Visible. Если установлено значение False, этот конкретный элемент управления пользовательского интерфейса не будет отображаться в форме. Затем его можно снова включить, установив для него значение True. Это можно сделать для любого элемента управления пользовательского интерфейса, включая панели, содержащие несколько различных элементов управления пользовательского интерфейса.

Пример того, как его можно использовать в контексте нашего Tutorial № 1 для первоначального скрытия поля «Статус счета», показан ниже.

if (context.Model.Id == 0):
    context.Properties.UI_InvoiceStatus.Visible = False
if (context.Model.Id > 0):
    context.Properties.UI_InvoiceStatus.Visible = True
#End of script

Также есть поле Hidden которое прячет/показывает элементы интерфейса пользователя, аналогично полю Visible.

Другое часто используемое поле context.Properties является обязательным. Если установлено значение true, конкретный элемент управления пользовательского интерфейса станет обязательным (не может быть пустым), а если установлено значение false, он станет необязательным. Обратите внимание, что при этом изменяется только состояние элемента управления пользовательского интерфейса для настраиваемого свойства в текущем экземпляре формы, а не самого настраиваемого свойства, шаблона формы или элементов управления пользовательского интерфейса для этого настраиваемого свойства в других формах.

Дополнительные примеры использования context.Properties для управления элементами пользовательского интерфейса можно найти в Tutorial №2.

Использование context.Form#

context.Form можно использовать для доступа к данным формы (например, для целей проверки во время обработки формы, до того, как данные формы будут сохранены во внутреннем хранилище) или для управления визуальным представлением формы, например, путем настройки сообщения об ошибке.

Для этого следует использовать context.Form.Get() для получения объекта, представляющего конкретное поле. Затем с этим объектом можно использовать следующие функции.

  • context.Form.Get().SetValue() — устанавливает значение для определенного элемента управления пользовательского интерфейса в текущей форме. — context.Form.Get().AddError() — устанавливает сообщение об ошибке, отображаемое под определенным элементом управления пользовательского интерфейса в текущей форме. — context.Form.Get().ClearError() — очищает сообщение об ошибке, показанное под конкретным элементом управления пользовательского интерфейса в текущей форме.

Следующее расширение скрипта показывает, как проверить ситуацию, в которой пользователь не изменил имя счета-фактуры по умолчанию, которое мы установили выше в примерах для Tutorial № 1.

if datamodel.InvoiceName == 'PLEASE_SET_A_UNIQUE_NAME':
    context.Form.Get("InvoiceName").AddError("Please set a unique invoice name")
else:
    context.Form.Get("InvoiceName").ClearError()

Результат будет выглядеть как на следующем снимке экрана в случае, если имя по умолчанию не было изменено:

Tutorial 3.4


Использование context.Commands#

context.Commands можно использовать для управления пользовательским интерфейсом исполняемого в данный момент компонента, изменения содержимого текущей формы, открытия разных страниц, открытия новых компонентов, возврата на предыдущую страницу или даже запуска новых Workflows, Dataflows или Scripts.

Эти команды обычно используются внутри сценариев, вызываемых действием ExecuteScript с помощью кнопок, и в подобных случаях. Например, в нашем Tutorial № 1 кнопка Back to All Invoices может использовать следующий скрипт для Вернуться на предыдущую страницу:

def navigate_back():

    context.Commands.NavigationBack()

Этот скрипт должен быть частью скрипта компонента и быть настроенным для кнопки Back to All Invoices, в разделе Actions -> Command Type: Execute Script -> Method Name:navigate back, как показано на экране внизу:

Tutorial 3.5


Другие доступные функции context.Commands:

  • context.Commands.AddItem(GUID)

    • Добавить элемент управления пользовательским интерфейсом на страницу с помощью GUID.

  • context.Commands.ChangePageAsync(GUID)

    • Открыть страницу, используя ее GUID

  • context.Commands.ChangePageByName(«ИмяСтраницы»)

    • Измените текущую страницу компонента на новую страницу, используя внутреннее имя

  • context.Commands.OpenComponent(GUID ComponentID, GUID PageID)

    • Открыть новый компонент и определенную страницу внутри компонента

  • context.Commands.EditItem(GUID UI_ControlID, EntityId)

    • Смещение фокуса пользовательского интерфейса на конкретный элемент управления пользовательского интерфейса и определенные данные (используя его внутренний идентификатор)

  • context.Commands.ExecuteWorkflow(GUID WorkflowID)

    • Выполнить рабочий процесс, используя его идентификатор

    • Кроме того, при необходимости можно настроить WaitComplete на true или false.

  • context.Commands.ExecuteDataflow(идентификатор потока данных GUID, ContextID)

    • Выполнить поток данных, используя его GUID и указанный контекст данных.

  • context.Commands.ExecuteScript(String ScriptName, StringParams Script)

    • Выполнить скрипт (функцию) из Component Script с некоторыми параметрами