# ConvertDataConnection

[ConvertDataConnection](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/dataconnections/convert_dc) - преобразующее загружающее соединение с данными, которое получает данные из другого загружающего соединения с данными и позволяет изменить структуру данных. Полный список селекторов для модификации структуры данных можно найти в [статье](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/dataconnections/convert_dc/selectors) справочника по синтаксису платформы WT, а здесь кратко познакомимся с часто используемыми.

{% hint style="success" %}
Пример практического применения ConvertDataConnection рассматривается в [Уроке 26. Работа с JSON на форме](https://wfsys.gitbook.io/wt-practice/advanced/lesson_json_on_form#storing-data-on-form).
{% endhint %}

Работать будем с формой и запросами из раздела [Подготовка](https://wfsys.gitbook.io/wt-practice/main/additionally/..#preparation).

## Добавление новых полей <a href="#adding-new-fields" id="adding-new-fields"></a>

Частым случаем применения ConvertDataConnection является необходимость расширить набор полей исходного DataConnection. Например, добавить поля Added, Updated и Deleted, чтобы при редактировании записи на форме устанавливать статус, который проверять при сохранении изменений в базу данных.

Для этих целей используется [селектор типа Value](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/dataconnections/convert_dc/selectors#selector_value), который добавляет колонку с именем из атрибута `Name` и типом данных из атрибута `DataType`. Для каждой строки в ячейку новой колонки ставиться значение, указанное в качестве значения тэга. Изменить значения полей можно через set-проперти [AddRow](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/dataconnections/primary_dc#set_add_row), [AddRows](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/dataconnections/primary_dc#set_add_rows), [UpdateRow](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/dataconnections/primary_dc#set_update_row), [UpdateRows](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/dataconnections/primary_dc#set_update_rows), [UpdateColumn](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/dataconnections/primary_dc#set_update_column) и [UpdateColumnCellsValues](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/dataconnections/primary_dc#set_update_column_cells_values) в команде типа [ValueSetCommand](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/commands/value_set_command).

```xml
<DataConnection Name="ClientConvertDataConnection" Type="ConvertDataConnection" Assembly="WorkflowServer">
  <SourceDataConnection Name="ClientPrimaryGetDataConnection" />
  <Fields>
    <Field Name="ClientId" />
    <Field Name="Title" />
    <Field Name="CityId" />
    <Field Name="Added" Type="Value" DataType="BooleanDataType">False</Field>
    <Field Name="Updated" Type="Value" DataType="BooleanDataType">False</Field>
    <Field Name="Deleted" Type="Value" DataType="BooleanDataType">False</Field>
  </Fields>
</DataConnection>
```

## Подстановка значений <a href="#substitution-of-values" id="substitution-of-values"></a>

Вторым по частоте использования является [селектор типа Substitution](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/dataconnections/convert_dc/selectors#selector_substitution), который добавляет колонку с именем из атрибута `Name`, а значение для нее берет из матрицы подстановки по ключу из поля, указанному в атрибуте `Field`.

```xml
<DataConnection Name="ClientConvertDataConnection" Type="ConvertDataConnection" Assembly="WorkflowServer">
  <SourceDataConnection Name="ClientPrimaryGetDataConnection" />
  <Fields>
    <Field Name="ClientId" />
    <Field Name="Title" />
    <Field Name="CityId" />
    <Field Name="CityTitle" Type="Substitution" Field="CityId">
      <DataConnection SourceDataConnection="CityPrimaryGetDataConnection">
        <Fields>
          <Field Name="CityId" />
          <Field Name="Title" />
        </Fields>
      </DataConnection>
    </Field>
  </Fields>
</DataConnection>
```

{% hint style="warning" %}
Подстановка сработает только при обновлении ConvertDataConnection, которое будет при загрузки формы и при обновлении источника данных, если не задан элемент [ManualRefresh](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/dataconnections/convert_dc#manual_refresh) со значением True, а так же по команде типа [DataConnectionRefreshCommand](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/commands/dc_refresh_command).

Поэтому при добавлении записи или редактировании колонки с ключом для подстановки нужно задавать значение&#x20;
{% endhint %}

### Замена подстрок

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

В качестве примера в запросе будем формировать строку из фамилии клиента и в круглых скобках указывать идентификатор города. На форме в ConvertDataConnection вместо идентификатора будем подставлять название города.

Скорректируем запрос TestClientSelectSqlQuery, добавив поле TitleWithCity:

```xml
<SqlQuery Name="TestClientSelectSqlQuery">
  <Text>
    SELECT
      client_id AS "ClientId",
      title AS "Title",
      city_id AS "CityId",
      archive AS "Archive",
      title || ' (' || city_id || ')' AS "TitleWithCity"
    FROM
      template.client
    ORDER BY client_id;
  </Text>
</SqlQuery>
```

Добавим в ClientPrimaryGetDataConnection новое поле TitleWithCity, а затем переделаем ClientConvertDataConnection:

```xml
<DataConnection Name="ClientConvertDataConnection" Type="ConvertDataConnection" Assembly="WorkflowServer">
  <SourceDataConnection Name="ClientPrimaryGetDataConnection" />
  <Fields>
    <Field Name="ClientId" />
    <Field Name="TitleWithCity" Type="Replace">
      <DataConnection SourceDataConnection="CityPrimaryGetDataConnection">
        <Fields>
          <Field Name="CityId" />
          <Field Name="Title" />
        </Fields>
      </DataConnection>
    </Field>
  </Fields>
</DataConnection>
```

Для тэга `<Field>` в атрибуте `Name` укажем имя новой колонки, в которой будет происходить замена. А в качестве значения тэга `<Field>` передадим соединение с данными со списком городов. Это соединение будет выступать матрицей замены, где первый столбец - ключ, по которому будет идти замена.

Укажем ClientConvertDataConnection в качестве источника данных в таблице ResultDatabaseTable, и скорректируем ее колонки.

Запустим форму, чтобы проверить результат:

<figure><img src="https://3019442075-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M_eBlWEU4C3o2GVEAAr%2Fuploads%2F2Pntz35JuG5TJHSkk0ju%2Fimage.png?alt=media&#x26;token=29462d02-28c1-4caf-bbcb-4426292f7537" alt=""><figcaption></figcaption></figure>

## Форматирование строки <a href="#formatting-string" id="formatting-string"></a>

Бывает необходимость собрать текстовую строку, содержащую данные из других полей той же строки соединения с данными. Для этого используется [селектор типа Format](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/dataconnections/convert_dc/selectors#selector_format). В качестве значения тэга ожидается строка-шаблон, с указанием в фигурных скобках `{}` имен полей исходного соединения с данными, которые будут источниками значений.

Скорректируем запрос TestClientSelectSqlQuery, добавив поле CityTitle:

```xml
<SqlQuery Name="TestClientSelectSqlQuery">
  <Text>
    SELECT
      client.client_id AS "ClientId",
      client.title AS "Title",
      client.city_id AS "CityId",
      client.archive AS "Archive",
      city.title AS "CityTitle"
    FROM
      template.client
      LEFT JOIN template.city USING(city_id)
    ORDER BY client_id;
  </Text>
</SqlQuery> 
```

Добавим в ClientPrimaryGetDataConnection новое поле CityTitle, а затем переделаем ClientConvertDataConnection:

```xml
<DataConnection Name="ClientConvertDataConnection" Type="ConvertDataConnection" Assembly="WorkflowServer">
  <SourceDataConnection Name="ClientPrimaryGetDataConnection" />
  <Fields>
    <Field Name="ClientId" />
    <Field Name="ClientTitle" Type="Format">{Title} ({CityTitle})</Field>
  </Fields>
</DataConnection>
```

Укажем его в качестве источника данных в таблице ResultDatabaseTable, и скорректируем ее колонки.

Запустим форму, чтобы проверить результат:

<figure><img src="https://3019442075-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M_eBlWEU4C3o2GVEAAr%2Fuploads%2F8K8e8WbOlP2RxHYVRZU5%2Fimage.png?alt=media&#x26;token=1bcc72ee-84ba-4e67-98b7-b4f63eaba8cc" alt=""><figcaption></figcaption></figure>

### Сложные шаблоны

Для форматирования строки по шаблону существует еще один [селектор типа TemplateFormat](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/dataconnections/convert_dc/selectors#selector_template_format), который позволяет использовать в шаблоне условные операторы.

{% hint style="info" %}
В качестве шаблонизатора используется Scriban. Подробнее можно почитать по [ссылке](https://github.com/lunet-io/scriban).
{% endhint %}

Давайте рассмотрим пример, добавления в имя клиента постфикса (арх.), если запись находится в архиве:

```xml
<DataConnection Name="ClientConvertDataConnection" Type="ConvertDataConnection" Assembly="WorkflowServer">
  <SourceDataConnection Name="ClientPrimaryGetDataConnection" />
  <Fields>
    <Field Name="ClientId" />
    <Field Name="Title" Type="TemplateFormat">{{Title}}{{if Archive}} (арх.){{end}}</Field>
    <Field Name="Archive" />
  </Fields>
</DataConnection>
```

Укажем его в качестве источника данных в таблице ResultDatabaseTable, и скорректируем ее колонки.

Запустим форму, чтобы проверить результат:

<figure><img src="https://3019442075-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M_eBlWEU4C3o2GVEAAr%2Fuploads%2FZnymaawy6T5qYzMLfCCz%2Fimage.png?alt=media&#x26;token=598e9677-9e50-46cd-a074-94041f11131b" alt=""><figcaption></figcaption></figure>

## Вложенные массивы

Для обработки вложенных массивов используется [селектор типа Action](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/dataconnections/convert_dc/selectors#selector_action), который поддерживает операций по работе с массивами, перечисленные в статье [Array](https://wfsys.gitbook.io/wt-practice/main/additionally/broken-reference).

Скорректируем запрос TestClientSelectSqlQuery, добавив поля с вложенными массивами:

```xml
<SqlQuery Name="TestClientSelectSqlQuery">
  <Text>
    WITH _material AS (
      SELECT
        O.client_id,
        array_agg(M.title) AS materials,
        array_agg(OP.quantity * OP.unit_price) AS total_price
      FROM
        template.order_position OP
        LEFT JOIN template.order O USING(order_id)
        LEFT JOIN template.material M USING(material_id)
        LEFT JOIN template.material_category MC USING(material_category_id)
        LEFT JOIN template.unit U USING(unit_id)
      GROUP BY O.client_id
    )
    SELECT
      C.client_id AS "ClientId",
      C.title AS "Title",
      C.city_id AS "CityId",
      C.archive AS "Archive",
      M.materials AS "Materials",
      M.total_price AS "TotalPrice"
    FROM
      template.client C
      LEFT JOIN _material M USING(client_id)
    ORDER BY client_id;
  </Text>
</SqlQuery>
```

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

<figure><img src="https://3019442075-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M_eBlWEU4C3o2GVEAAr%2Fuploads%2FkXZo1N9PBM6Gy97N59D7%2Fimage.png?alt=media&#x26;token=dca8802c-1c8c-4ad9-85da-efffb6176692" alt=""><figcaption></figcaption></figure>

Добавим в ClientPrimaryGetDataConnection новые поля Materials и TotalPrice, а затем переделаем ClientConvertDataConnection:

```
<DataConnection Name="ClientConvertDataConnection" Type="ConvertDataConnection" Assembly="WorkflowServer">
  <SourceDataConnection Name="ClientPrimaryGetDataConnection" />
  <Fields>
    <Field Name="ClientId" />
    <Field Name="Title" />
    <Field Name="MaterialsAction" Type="Action" Field="Materials">
      <StringJoin Separator=", " />
    </Field>
    <Field Name="TotalPriceAction" Type="Action" Field="TotalPrice">
      <Sum Type="DecimalDataType" />
    </Field>
  </Fields>
</DataConnection>
```

Укажем его в качестве источника данных в таблице ResultDatabaseTable, и скорректируем ее колонки.

Запустим форму, чтобы проверить результат:

<figure><img src="https://3019442075-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M_eBlWEU4C3o2GVEAAr%2Fuploads%2F42OJJ2Rbhh1LBPFW2oXh%2Fimage.png?alt=media&#x26;token=55d4050c-2fe6-40b1-94a1-dfc0d191fe1c" alt=""><figcaption></figcaption></figure>
