# 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>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://wfsys.gitbook.io/wt-practice/main/additionally/convert_dc.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
