Разработка в HR Pro 2.1. Часть 2. Услуги

10 0

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

Шаг 1: Заполнение услуги через тип виджета: "facilityShortcuts"

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

Здесь мы будем работать с параметрами заявления. Чтобы упростить работу, рекомендуется создать отдельную папку с файлами услуг в формате JSON. После этого можно будет открыть файлы в любом редакторе, а затем просто скопировать готовый JSON в заявление..

Сначала добавим поле «Водитель». Для этого укажем параметр, который будет содержать «id» сотрудника из RX, а отображать — свойство «name».

Важно следить за регистром: он должен быть соблюдён.

{
    "name": "Driver",
    "type": "FacilityParameterReferenceRecord",
    "defaultValue": null,
    "isRequired": true,
    "isCollection": false,
    "properties": {
        "SystemName": "EssBase",
        "ReferenceName": "IEmployees",
        "DisplayRequisite": "Name",
        "StoreRequisite": "Id",
        "Filter": "Status eq 'Active'",
        "IsUserQuerySupported": "True"
    }
}

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

Параметр добавлен, теперь нужно отобразить его на форме:

"form": {
    "items": [
        {
            "type": "FacilityFormParameter",
            "properties": {
                "ParameterName": "Driver",
                "ShowHeaders": "True",
                "IsReadOnly": "False",
                "IsHidden": "False",
                "Label": "Водитель",
                "ValueChangedHandler": ""
            }
        }
    ]
}

Для отображения необходимо вписать в атрибут "ParameterName" имя параметра, который был создан выше. Описание всех параметров так-же можно посмотреть здесь, а полный список здесь, во второй ссылке описание параметров для стандартного типа услуги, о них позже, но их же можно использовать и сейчас, если вписывать по аналогии, отличается лишь регистр и вид заполнения узлов.

Так выглядит услуга целиком: 

{
    "facilityId": "23fa024d-859c-48b4-85ac-ab5f26b40a34",
    "icon": "documents",
    "title": "Пропуск для транспорта",
    "parameters": [
      {
        "name": "TemplateId",
        "type": "FacilityParameterNumber",
        "defaultValue": "#TEMPLATE_ID",
        "isRequired": false,
        "isCollection": false
      },
      {
        "name": "DocumentKind",
        "type": "FacilityParameterNumber",
        "defaultValue": "#DOCUMENT_KIND_ID",
        "isRequired": false,
        "isCollection": false
      },
      {
        "name": "Driver",
        "type": "FacilityParameterReferenceRecord",
        "defaultValue": null,
        "isRequired": true,
        "isCollection": false,
        "properties": {
            "SystemName": "EssBase",
            "ReferenceName": "IEmployees",
            "DisplayRequisite": "Name",
            "StoreRequisite": "Id",
            "Filter": "Status eq 'Active",
            "IsUserQuerySupported": "True"
        }
    }
   ],
   "form": {
      "items": [
        {
            "type": "FacilityFormParameter",
            "properties": {
                "ParameterName": "Driver",
                "ShowHeaders": "True",
                "IsReadOnly": "False",
                "IsHidden": "False",
                "Label": "Водитель",
                "ValueChangedHandler": ""
            }
        }
      ]
    }
  }

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

Тем самым мы получили возможность выбрать нашего водителя. Далее добавим срок действия пропуска: 

{
    "name": "StartDate",
    "type": "FacilityParameterDateTime",
    "defaultValue": null,
    "isRequired": true,
    "isCollection": false,
    "properties": {
        "ShowTime": "False",
        "ValueChangedHandler": "",
        "MinValue": "2024-01-01"
    }
},
{
    "name": "EndDate",
    "type": "FacilityParameterDateTime",
    "defaultValue": null,
    "isRequired": true,
    "isCollection": false,
    "properties": {
        "ShowTime": "False",
        "ValueChangedHandler": "",
        "MinValue": "2024-01-01",
        "MaxValue": "2034-01-01"
    }
}

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

Это решение служит лишь примером. В реальности лучше регулировать это с помощью кода. Но об этом мы поговорим позже.

Теперь добавим параметры на форму.

{
    "type": "FacilityFormGroup",
    "name": "DateGroup"
},
{
    "type": "FacilityFormParameter",
    "properties": {
        "ParameterName": "StartDate",
        "GroupName": "DateGroup",
        "ShowHeaders": "True",
        "IsReadOnly": "False",
        "IsHidden": "False",
        "Label": "Дата начала действия",
        "ValueChangedHandler": ""
    }
},
{
    "type": "FacilityFormParameter",
    "properties": {
        "ParameterName": "EndDate",
        "GroupName": "DateGroup",
        "ShowHeaders": "True",
        "IsReadOnly": "False",
        "IsHidden": "False",
        "Label": "Дата окончания действия",
        "ValueChangedHandler": ""
}

Тут добавлена еще группа, чтоб даты отображались на форме в строчку, название группы вписывается в атрибут "GroupName". Смотрим результат:

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

{
    "name": "Brand",
    "type": "FacilityParameterString",
    "defaultValue": null,
    "isRequired": true,
    "isCollection": false,
    "properties": {
        "MaxLength": "250",
        "Multiline": "False"
    }
},
{
    "name": "Model",
    "type": "FacilityParameterString",
    "defaultValue": null,
    "isRequired": true,
    "isCollection": false,
    "properties": {
        "MaxLength": "250",
        "Multiline": "False"
    }
},
{
    "name": "ReleaseDate",
    "type": "FacilityParameterDateTime",
    "defaultValue": null,
    "isRequired": true,
    "isCollection": false,
    "properties": {
        "ShowTime": "False",
        "ValueChangedHandler": "",
        "MinValue": "2024-01-01",
        "MaxValue": "2034-01-01"
    }
},
{
    "name": "RegNum",
    "type": "FacilityParameterString",
    "defaultValue": null,
    "isRequired": true,
    "isCollection": false,
    "properties": {
        "MaxLength": "250",
        "Multiline": "False"
    }
},
{
    "name": "MaxWeight",
    "type": "FacilityParameterNumber",
    "defaultValue": null,
    "isRequired": true,
    "isCollection": false,
    "properties": {
        "IsInteger": "False",
        "MinValue": "0",
        "MaxValue": "38000",
        "Precision": "3"
    }
}

Здесь мы добавили параметры строковых типов для марки, модели и регистрационного номера, а для максимально допустимого веса — числовой тип. Максимальный вес ограничили в диапазоне от 0 до 38 000, также указали, что число может иметь дробную часть с тремя знаками после запятой.

Осталось добавить таблицу на форму и внести в неё эти параметры. 

{
    "type": "FacilityFormTable",
    "hint": "",
    "IsReadOnly": "False",
    "parentName": "",
    "properties": {
        "ItemAddedHandler": "",
        "ItemAddingHandler": "",
        "ItemRemovedHandler": "",
        "ItemRemovingHandler": "",
        "ShowHeaders": "True",
        "Title": "Информация о машинах",
        "Columns": [
            {
                "ParameterName": "Brand",
                "Header": "Марка",
                "IsReadOnly": "False",
                "IsHidden": "False",
                "ValueChangedHandler": "",
                "CalculateFunction": "",
                "Placeholder": ""
            },
            {
                "ParameterName": "Model",
                "Header": "Модель",
                "IsReadOnly": "False",
                "IsHidden": "False",
                "ValueChangedHandler": "",
                "CalculateFunction": "",
                "Placeholder": ""
            },
            {
                "ParameterName": "ReleaseDate",
                "Header": "Дата выпуска",
                "IsReadOnly": "False",
                "IsHidden": "False",
                "ValueChangedHandler": "",
                "CalculateFunction": "",
                "Placeholder": ""
            },
            {
                "ParameterName": "RegNum",
                "Header": "Рег. Номер",
                "IsReadOnly": "False",
                "IsHidden": "False",
                "ValueChangedHandler": "",
                "CalculateFunction": "",
                "Placeholder": ""
            },
            {
                "ParameterName": "MaxWeight",
                "Header": "Максимальный допустимый вес",
                "IsReadOnly": "False",
                "IsHidden": "False",
                "ValueChangedHandler": "",
                "CalculateFunction": "",
                "Placeholder": ""
            }
        ]
    }
}

 Целиком услуга выглядит так: 

{
    "facilityId": "23fa024d-859c-48b4-85ac-ab5f26b40a34",
    "icon": "documents",
    "title": "Пропуск для транспорта",
    "parameters": [
      {
        "name": "TemplateId",
        "type": "FacilityParameterNumber",
        "defaultValue": "#TEMPLATE_ID",
        "isRequired": false,
        "isCollection": false
      },
      {
        "name": "DocumentKind",
        "type": "FacilityParameterNumber",
        "defaultValue": "#DOCUMENT_KIND_ID",
        "isRequired": false,
        "isCollection": false
      },
      {
        "name": "Driver",
        "type": "FacilityParameterReferenceRecord",
        "defaultValue": null,
        "isRequired": true,
        "isCollection": false,
        "properties": {
            "SystemName": "EssBase",
            "ReferenceName": "IEmployees",
            "DisplayRequisite": "Name",
            "StoreRequisite": "Id",
            "Filter": "Status eq 'Active'",
            "IsUserQuerySupported": "True"
        }
    },
    {
        "name": "StartDate",
        "type": "FacilityParameterDateTime",
        "defaultValue": null,
        "isRequired": true,
        "isCollection": false,
        "properties": {
            "ShowTime": "False",
            "ValueChangedHandler": "",
            "MinValue": "2024-01-01"
        }
    },
    {
        "name": "EndDate",
        "type": "FacilityParameterDateTime",
        "defaultValue": null,
        "isRequired": true,
        "isCollection": false,
        "properties": {
            "ShowTime": "False",
            "ValueChangedHandler": "",
            "MinValue": "2024-01-01",
            "MaxValue": "2034-01-01"
        }
    },
    {
        "name": "Brand",
        "type": "FacilityParameterString",
        "defaultValue": null,
        "isRequired": true,
        "isCollection": false,
        "properties": {
            "MaxLength": "250",
            "Multiline": "False"
        }
    },
    {
        "name": "Model",
        "type": "FacilityParameterString",
        "defaultValue": null,
        "isRequired": true,
        "isCollection": false,
        "properties": {
            "MaxLength": "250",
            "Multiline": "False"
        }
    },
    {
        "name": "ReleaseDate",
        "type": "FacilityParameterDateTime",
        "defaultValue": null,
        "isRequired": true,
        "isCollection": false,
        "properties": {
            "ShowTime": "False",
            "ValueChangedHandler": "",
            "MinValue": "2024-01-01",
            "MaxValue": "2034-01-01"
        }
    },
    {
        "name": "RegNum",
        "type": "FacilityParameterString",
        "defaultValue": null,
        "isRequired": true,
        "isCollection": false,
        "properties": {
            "MaxLength": "250",
            "Multiline": "False"
        }
    },
    {
        "name": "MaxWeight",
        "type": "FacilityParameterNumber",
        "defaultValue": null,
        "isRequired": true,
        "isCollection": false,
        "properties": {
            "IsInteger": "False",
            "MinValue": "0",
            "MaxValue": "38000",
            "Precision": "3"
        }
    }
   ],
   "form": {
      "items": [
        {
            "type": "FacilityFormParameter",
            "properties": {
                "ParameterName": "Driver",
                "ShowHeaders": "True",
                "IsReadOnly": "False",
                "IsHidden": "False",
                "Label": "Водитель",
                "ValueChangedHandler": ""
            }
        },
        {
            "type": "FacilityFormGroup",
            "name": "DateGroup"
        },
        {
            "type": "FacilityFormParameter",
            "properties": {
                "ParameterName": "StartDate",
                "GroupName": "DateGroup",
                "ShowHeaders": "True",
                "IsReadOnly": "False",
                "IsHidden": "False",
                "Label": "Дата начала действия",
                "ValueChangedHandler": ""
            }
        },
        {
            "type": "FacilityFormParameter",
            "properties": {
                "ParameterName": "EndDate",
                "GroupName": "DateGroup",
                "ShowHeaders": "True",
                "IsReadOnly": "False",
                "IsHidden": "False",
                "Label": "Дата окончания действия",
                "ValueChangedHandler": ""
            }
        },
        {
            "type": "FacilityFormTable",
            "hint": "",
            "IsReadOnly": "False",
            "parentName": "",
            "properties": {
                "ItemAddedHandler": "",
                "ItemAddingHandler": "",
                "ItemRemovedHandler": "",
                "ItemRemovingHandler": "",
                "ShowHeaders": "True",
                "Title": "Информация о машинах",
                "Columns": [
                    {
                        "ParameterName": "Brand",
                        "Header": "Марка",
                        "IsReadOnly": "False",
                        "IsHidden": "False",
                        "ValueChangedHandler": "",
                        "CalculateFunction": "",
                        "Placeholder": ""
                    },
                    {
                        "ParameterName": "Model",
                        "Header": "Модель",
                        "IsReadOnly": "False",
                        "IsHidden": "False",
                        "ValueChangedHandler": "",
                        "CalculateFunction": "",
                        "Placeholder": ""
                    },
                    {
                        "ParameterName": "ReleaseDate",
                        "Header": "Дата выпуска",
                        "IsReadOnly": "False",
                        "IsHidden": "False",
                        "ValueChangedHandler": "",
                        "CalculateFunction": "",
                        "Placeholder": ""
                    },
                    {
                        "ParameterName": "RegNum",
                        "Header": "Рег. Номер",
                        "IsReadOnly": "False",
                        "IsHidden": "False",
                        "ValueChangedHandler": "",
                        "CalculateFunction": "",
                        "Placeholder": ""
                    },
                    {
                        "ParameterName": "MaxWeight",
                        "Header": "Максимальный допустимый вес",
                        "IsReadOnly": "False",
                        "IsHidden": "False",
                        "ValueChangedHandler": "",
                        "CalculateFunction": "",
                        "Placeholder": ""
                    }
                ]
            }
        }
      ]
    }
  }

Обновляем заявление и смотрим результат:

 

Шаг 2: Передача данных из услуги в RX

Для того, чтоб передать данные услуги в RX нам нужно вернуться к услуге в файле "TransportPass.xml", которую мы создали в шаге 8. Логика, которая происходит после нажатия на кнопку "Отправить", описана с помощью шагов в узле "facilityFlowScheme", о нем здесь. По сути каждый шаг выполняет свою логику, после каждого шага выполняется следующий, порядок определяется с помощью атрибута"NextStepIndex". О всех шагах можно узнать тут. Есть удобные шаги, которые позволяют запустить задачу прямо из ЛК, но т.к у нас есть таблица, то данные необходимо обработать в RX. Воспользуемся шагом типа "ExecuteFunctionStep".

<flowStep index="0" name="SetInfo" title="Создание пропуска и занесение информации в него" type="ExecuteFunctionStep">
  <property name="TargetSystem">CertifySolution</property>
  <property name="NextStepIndex">-1</property>
  <property name="ExecutionMethod">POST</property>
  <property name="FunctionName">Certify.CreateAndFillOutTransportPass</property>
</flowStep>

В этом шаге мы обращаемся к серверной post функции "FillOutTransportPass" из модуля "Certify". Мы бы могли передать каждый параметр из услуги в параметры функции,. но это влечет много ограничений и трудоемкости. Учитывая то, что параметры данной услуги заполняется с помощью "facilityShortcuts", у каждого пропуска могут быть разные параметры. Поэтому добавим js функцию, которая будет сохранять параметры и их значения в формате json. Для этого создадим новый строковый параметр, поместим его в xml файл, т.к. данный параметр будет актуален для всех услуг, укажем, что этот параметр будет передаваться в функцию RX. Получаем следующее:

<?xml version="1.0" encoding="utf-8"?>
<facility id="23fa024d-859c-48b4-85ac-ab5f26b40a34" name="TransportPass">
  <authorization>
    <allowedRoles>Employee</allowedRoles>
  </authorization>
  <title>Создать пропуск для транспорта</title>
  <description></description>
  <facilityParameters>
    <facilityParameter type="FacilityParameterString" name="Values" defaultValue="" isRequired="false" isCollection="false">
      <maxLength>2000</maxLength>
      <multiline>false</multiline>
    </facilityParameter>
  </facilityParameters>
  <facilityFormItems>
  </facilityFormItems>
  <facilityFlowScheme firstStepIndex="0" lastStepIndex="-1">
    <flowSteps>
      <flowStep index="0" name="SetInfo" title="Создание пропуска и занесение информации в него" type="ExecuteFunctionStep">
        <property name="TargetSystem">CertifySolution</property>
        <property name="NextStepIndex">-1</property>
        <property name="ExecutionMethod">POST</property>
        <property name="jsonValue" binding="Values"/>
        <property name="FunctionName">Certify.CreateAndFillOutTransportPass</property>
      </flowStep>
    </flowSteps>
  </facilityFlowScheme>
  <openedEventHandler><![CDATA[]]></openedEventHandler>
</facility>

Теперь нам необходимо как-то заполнять параметр данными. Воспользуемся узлом, в котором обрабатывается событие, которое срабатывает после открытия формы "openedEventHandler". Добавим в этот узел простой код, в котором объявим js функцию: 

<openedEventHandler><![CDATA[

    window.fillValues = function() {
      functions.setValue('Values', '');
      functions.setValue('Values', '[' + JSON.stringify(functions.getValues()) + ']');
    }
]]></openedEventHandler>

В этой функции мы сериализуем все параметры формы и записываем их в параметр "Values", о всех прикладных функциях можно узнать тут.

Нашу функцию будем использовать в другом обработчике: "beforeSubmitEventHandler", событие перед отправкой формы. Просто вызываем функцию и пишем "resolve()", resolve() разрешает отправить форму, без него форма просто зависнет. В итоге услуга будет выглядеть так: 

<?xml version="1.0" encoding="utf-8"?>
<facility id="23fa024d-859c-48b4-85ac-ab5f26b40a34" name="TransportPass">
  <authorization>
    <allowedRoles>Employee</allowedRoles>
  </authorization>
  <title>Создать пропуск для транспорта</title>
  <description></description>
  <facilityParameters>
    <facilityParameter type="FacilityParameterString" name="Values" defaultValue="" isRequired="false" isCollection="false">
      <maxLength>2000</maxLength>
      <multiline>false</multiline>
    </facilityParameter>
  </facilityParameters>
  <facilityFormItems>
  </facilityFormItems>
  <facilityFlowScheme firstStepIndex="0" lastStepIndex="-1">
    <flowSteps>
      <flowStep index="0" name="SetInfo" title="Создание пропуска и занесение информации в него" type="ExecuteFunctionStep">
        <property name="TargetSystem">CertifySolution</property>
        <property name="NextStepIndex">-1</property>
        <property name="ExecutionMethod">POST</property>
        <property name="jsonValue" binding="Values"/>
        <property name="FunctionName">Certify.CreateAndFillOutTransportPass</property>
      </flowStep>
    </flowSteps>
  </facilityFlowScheme>
  <openedEventHandler><![CDATA[
    window.fillValues = function() {
      functions.setValue('Values', '[' + JSON.stringify(functions.getValues()) + ']');
    }
  ]]></openedEventHandler>
  <beforeSubmitEventHandler><![CDATA[
    functions.setValue('Values', '');
    window.fillValues();
    resolve();
  ]]></beforeSubmitEventHandler>
</facility>

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

.

Функция будет выглядеть так:

  /// <summary>
    /// Создает запись в справочнике "TransportPass" и заполняет его данными.
    /// </summary>
    /// <param name="jsonValue">JSON-значение значения</param>
    [Public(WebApiRequestType = RequestType.Post)]
    public void CreateAndFillOutTransportPass(string jsonValue)
    {
      var transportPass = TransportPasses.Create();
      
      var trimChars = new char[] { '[', ']' };
      var valueObjects = Newtonsoft.Json.Linq.JObject.Parse(jsonValue.Trim(trimChars));
      
      if (valueObjects["Driver"] != null)
      {
        long driverId;
        if (long.TryParse(valueObjects["Driver"].ToString(), out driverId))
        {
          var driver = Sungero.Company.Employees.GetAll().Where(x => x.Id == driverId).FirstOrDefault();
          transportPass.Driver = driver;
        }
      }
      
      if (valueObjects["StartDate"] != null)
      {
        System.DateTime startDate;
        if (System.DateTime.TryParse(valueObjects["StartDate"].ToString(), out startDate))
          transportPass.StartDate = startDate;
      }
      
      if (valueObjects["EndDate"] != null)
      {
        System.DateTime endDate;
        if (System.DateTime.TryParse(valueObjects["EndDate"].ToString(), out endDate))
          transportPass.EndDate = endDate;
      }
      
      var carInfo = valueObjects[""];

      if (carInfo == null)
        return;
      
      foreach (var record in carInfo.Children())
      {
        var rowValue = record["rowValues"];
        if (rowValue != null)
        {
          var row = transportPass.CarInfo.AddNew();

          row.Brand = rowValue["Brand"].ToString();
          row.Model= rowValue["Model"].ToString();

          System.DateTime releaseDate;
          if (System.DateTime.TryParse(rowValue["ReleaseDate"].ToString(), out releaseDate))
            row.ReleaseDate = releaseDate;

          row.RegNum = rowValue["RegNum"].ToString();
          
          double maxWeight;
          if (double.TryParse(rowValue["MaxWeight"].ToString(), out maxWeight))
            row.MaxWeight = maxWeight;

        }
      }

      transportPass.Save();
    }

Дополнительно нужно подключить стороннюю библиотеку "Newtonsoft.Json". Это лишь пример реализации, тут можно парсить json любыми способами. Осталось в переменную carInfo присвоить таблицу, чтоб узнать ее название в json можно отправить форму, при этом открыв запросы с помощью F12. Обновим решение через утилиту ess и попробуем отправить:

Сейчас форма отправилась, но данные не сохранились, нам нужно пролистать значения в параметре "Values" и найти там строку подобного вида "Brand&Model&ReleaseDate&RegNum&MaxWeightGrid", это и есть таблица, по аналогии можно писать самостоятельно, но удобнее просто копировать. Вставляем эту строчку в функцию и получаем: 

   /// <summary>
    /// Создает запись в справочнике "TransportPass" и заполняет его данными.
    /// </summary>
    /// <param name="jsonValue">JSON-значение значения</param>
    [Public(WebApiRequestType = RequestType.Post)]
    public void CreateAndFillOutTransportPass(string jsonValue)
    {
      var transportPass = TransportPasses.Create();
      
      var trimChars = new char[] { '[', ']' };
      var valueObjects = Newtonsoft.Json.Linq.JObject.Parse(jsonValue.Trim(trimChars));
      
      if (valueObjects["Driver"] != null)
      {
        long driverId;
        if (long.TryParse(valueObjects["Driver"].ToString(), out driverId))
        {
          var driver = Sungero.Company.Employees.GetAll().Where(x => x.Id == driverId).FirstOrDefault();
          transportPass.Driver = driver;
        }
      }
      
      if (valueObjects["StartDate"] != null)
      {
        System.DateTime startDate;
        if (System.DateTime.TryParse(valueObjects["StartDate"].ToString(), out startDate))
          transportPass.StartDate = startDate;
      }
      
      if (valueObjects["EndDate"] != null)
      {
        System.DateTime endDate;
        if (System.DateTime.TryParse(valueObjects["EndDate"].ToString(), out endDate))
          transportPass.EndDate = endDate;
      }
      
      var carInfo = valueObjects["Brand&Model&ReleaseDate&RegNum&MaxWeightGrid"];

      if (carInfo == null)
        return;
      
      foreach (var record in carInfo.Children())
      {
        var rowValue = record["rowValues"];
        if (rowValue != null)
        {
          var row = transportPass.CarInfo.AddNew();

          row.Brand = rowValue["Brand"].ToString();
          row.Model= rowValue["Model"].ToString();

          System.DateTime releaseDate;
          if (System.DateTime.TryParse(rowValue["ReleaseDate"].ToString(), out releaseDate))
            row.ReleaseDate = releaseDate;

          row.RegNum = rowValue["RegNum"].ToString();
          
          double maxWeight;
          if (double.TryParse(rowValue["MaxWeight"].ToString(), out maxWeight))
            row.MaxWeight = maxWeight;

        }
      }
      
      transportPass.Save();
    }

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

Такая услуга получилась:

Нажимаем отправить и смотрим на новую запись в справочнике:

Все сработало, запись создана.

Шаг 3: Заполнение услуги через xml

Если мы не хотим заполнять услугу в заявлении, то можно это сделать в одном xml файле, поэтому создадим дубликат формы. Он будет выглядеть вот так: 

<?xml version="1.0" encoding="utf-8"?>
<facility id="23fa024d-859c-48b4-85ac-ab5f26b40a34" name="TransportPass">
  <authorization>
    <allowedRoles>Employee</allowedRoles>
  </authorization>
  <title>Создать пропуск для транспорта</title>
  <description></description>
  <facilityParameters>
    <facilityParameter type="FacilityParameterReferenceRecord" name="Driver" isRequired="true" isCollection="false">
      <systemName>EssBase</systemName>
      <referenceName>IEmployees</referenceName>
      <displayRequisite>Name</displayRequisite>
      <storeRequisite>Id</storeRequisite>
      <filter>Status eq 'Active'</filter>
      <isUserQuerySupported>true</isUserQuerySupported>
    </facilityParameter>
    <facilityParameter type="FacilityParameterDateTime" name="StartDate" isRequired="true" isCollection="false">
      <showTime>false</showTime>
    </facilityParameter>
    <facilityParameter type="FacilityParameterDateTime" name="EndDate" isRequired="false" isCollection="false">
      <showTime>false</showTime>
    </facilityParameter>
    <facilityParameter type="FacilityParameterString" name="Brand" defaultValue="" isRequired="true" isCollection="false">
      <maxLength>250</maxLength>
      <multiline>false</multiline>
    </facilityParameter>
    <facilityParameter type="FacilityParameterString" name="Model" defaultValue="" isRequired="true" isCollection="false">
      <maxLength>250</maxLength>
      <multiline>false</multiline>
    </facilityParameter>
    <facilityParameter type="FacilityParameterDateTime" name="ReleaseDate" defaultValue="" isRequired="true" isCollection="false">
      <maxLength>250</maxLength>
      <multiline>false</multiline>
    </facilityParameter>
    <facilityParameter type="FacilityParameterString" name="RegNum" defaultValue="" isRequired="true" isCollection="false">
      <maxLength>250</maxLength>
      <multiline>false</multiline>
    </facilityParameter>
    <facilityParameter type="FacilityParameterString" name="MaxWeight" defaultValue="" isRequired="true" isCollection="false">
      <isInteger>false</isInteger>
      <precision>3</precision>
      <minValue>0</minValue>
      <maxValue>30000</maxValue>
    </facilityParameter>
    <facilityParameter type="FacilityParameterString" name="Values" defaultValue="" isRequired="false" isCollection="false">
      <maxLength>2000</maxLength>
      <multiline>false</multiline>
    </facilityParameter>
  </facilityParameters>
  <facilityFormItems>
    <facilityFormItem type="FacilityFormParameter">
      <parameterName>Driver</parameterName>
      <isHidden>false</isHidden>
      <showHeaders>false</showHeaders>
      <label>Водитель</label>
    </facilityFormItem>
    <facilityFormItem type="FacilityFormGroup" name="DateGroup" />
    <facilityFormItem type="FacilityFormParameter">
      <parameterName>StartDate</parameterName>
      <isHidden>false</isHidden>
      <showHeaders>false</showHeaders>
      <groupName>DateGroup</groupName>
      <label>Дата начала действия</label>
    </facilityFormItem>
    <facilityFormItem type="FacilityFormParameter">
      <parameterName>EndDate</parameterName>
      <isHidden>false</isHidden>
      <showHeaders>false</showHeaders>
      <groupName>DateGroup</groupName>
      <label>Дата окончания действия</label>
    </facilityFormItem>
    <facilityFormItem type="FacilityFormTable">
      <hint />
      <title>Информация о машинах</title>
      <showColumnHeaders>true</showColumnHeaders>
      <itemAddedEventHandler><![CDATA[]]></itemAddedEventHandler>
      <itemRemovedEventHandler> <![CDATA[]]></itemRemovedEventHandler>
      <columns>
      <column type="FacilityFormTableColumn">
          <header>Марка</header>
          <parameterName>Brand</parameterName>
          <valueChangedEventHandler><![CDATA[]]></valueChangedEventHandler>
      </column>
      <column type="FacilityFormTableColumn">
          <header>Модель</header>
          <parameterName>Model</parameterName>
          <valueChangedEventHandler><![CDATA[]]></valueChangedEventHandler>
      </column>
      <column type="FacilityFormTableColumn">
          <header>Дата выпуска</header>
          <parameterName>ReleaseDate</parameterName>
          <valueChangedEventHandler><![CDATA[]]></valueChangedEventHandler>
      </column>
      <column type="FacilityFormTableColumn">
          <header>Рег. Номер</header>
          <parameterName>RegNum</parameterName>
          <valueChangedEventHandler><![CDATA[]]></valueChangedEventHandler>
      </column>
      <column type="FacilityFormTableColumn">
          <header>Максимальный допустимый вес</header>
          <parameterName>MaxWeight</parameterName>
          <valueChangedEventHandler><![CDATA[]]></valueChangedEventHandler>
      </column>
      </columns>
  </facilityFormItem>
  </facilityFormItems>
  <facilityFlowScheme firstStepIndex="0" lastStepIndex="-1">
    <flowSteps>
      <flowStep index="0" name="SetInfo" title="Создание пропуска и занесение информации в него" type="ExecuteFunctionStep">
        <property name="TargetSystem">CertifySolution</property>
        <property name="NextStepIndex">-1</property>
        <property name="ExecutionMethod">POST</property>
        <property name="jsonValue" binding="Values"/>
        <property name="FunctionName">Certify.CreateAndFillOutTransportPass</property>
      </flowStep>
    </flowSteps>
  </facilityFlowScheme>
  <openedEventHandler><![CDATA[
    window.fillValues = function() {
      functions.setValue('Values', '');
      functions.setValue('Values', '[' + JSON.stringify(functions.getValues()) + ']');
    }
  ]]></openedEventHandler>
  <beforeSubmitEventHandler><![CDATA[
    window.fillValues();
    resolve();
  ]]></beforeSubmitEventHandler>
</facility>

А из заявления уберем все параметры и получим такой вид:

{
  "facilityId": "23fa024d-859c-48b4-85ac-ab5f26b40a34",
  "icon": "documents",
  "title": "Кафетерий льгот",
  "parameters": [
    {
      "name": "TemplateId",
      "type": "FacilityParameterNumber",
      "defaultValue": "#TEMPLATE_ID",
      "isRequired": false,
      "isCollection": false
    },
    {
      "name": "DocumentKind",
      "type": "FacilityParameterNumber",
      "defaultValue": "#DOCUMENT_KIND_ID",
      "isRequired": false,
      "isCollection": false
    }
 ],
 "form": {
    "items": [
    ]
  }
}

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

Шаг 4: Дополнительная информация (вложения в услуге)

Отдельно рассмотрим вложения. Для этого добавим новый параметр:

{
    "name": "Attachment",
    "type": "FacilityParameterFile",
    "defaultValue": null,
    "isRequired": true,
    "isCollection": true,
    "properties": {
        "FileTypes": ".doc,.docx,.pdf,.png,.jpg,.tiff,.jpeg"
    }
}

Добавим на форму и получим такую структуру:

{
    "facilityId": "23fa024d-859c-48b4-85ac-ab5f26b40a34",
    "icon": "documents",
    "title": "Пропуск для транспорта",
    "parameters": [
      {
        "name": "TemplateId",
        "type": "FacilityParameterNumber",
        "defaultValue": "#TEMPLATE_ID",
        "isRequired": false,
        "isCollection": false
      },
      {
        "name": "DocumentKind",
        "type": "FacilityParameterNumber",
        "defaultValue": "#DOCUMENT_KIND_ID",
        "isRequired": false,
        "isCollection": false
      },
      {
        "name": "Driver",
        "type": "FacilityParameterReferenceRecord",
        "defaultValue": null,
        "isRequired": true,
        "isCollection": false,
        "properties": {
            "SystemName": "EssBase",
            "ReferenceName": "IEmployees",
            "DisplayRequisite": "Name",
            "StoreRequisite": "Id",
            "Filter": "Status eq 'Active'",
            "IsUserQuerySupported": "True"
        }
    },
    {
        "name": "StartDate",
        "type": "FacilityParameterDateTime",
        "defaultValue": null,
        "isRequired": true,
        "isCollection": false,
        "properties": {
            "ShowTime": "False",
            "ValueChangedHandler": "",
            "MinValue": "2024-01-01"
        }
    },
    {
        "name": "EndDate",
        "type": "FacilityParameterDateTime",
        "defaultValue": null,
        "isRequired": true,
        "isCollection": false,
        "properties": {
            "ShowTime": "False",
            "ValueChangedHandler": "",
            "MinValue": "2024-01-01",
            "MaxValue": "2034-01-01"
        }
    },
    {
        "name": "Brand",
        "type": "FacilityParameterString",
        "defaultValue": null,
        "isRequired": true,
        "isCollection": false,
        "properties": {
            "MaxLength": "250",
            "Multiline": "False"
        }
    },
    {
        "name": "Model",
        "type": "FacilityParameterString",
        "defaultValue": null,
        "isRequired": true,
        "isCollection": false,
        "properties": {
            "MaxLength": "250",
            "Multiline": "False"
        }
    },
    {
        "name": "ReleaseDate",
        "type": "FacilityParameterDateTime",
        "defaultValue": null,
        "isRequired": true,
        "isCollection": false,
        "properties": {
            "ShowTime": "False",
            "ValueChangedHandler": "",
            "MinValue": "2024-01-01",
            "MaxValue": "2034-01-01"
        }
    },
    {
        "name": "RegNum",
        "type": "FacilityParameterString",
        "defaultValue": null,
        "isRequired": true,
        "isCollection": false,
        "properties": {
            "MaxLength": "250",
            "Multiline": "False"
        }
    },
    {
        "name": "MaxWeight",
        "type": "FacilityParameterNumber",
        "defaultValue": null,
        "isRequired": true,
        "isCollection": false,
        "properties": {
            "IsInteger": "False",
            "MinValue": "0",
            "MaxValue": "38000",
            "Precision": "3"
        }
    },
    {
        "name": "Attachment",
        "type": "FacilityParameterFile",
        "defaultValue": null,
        "isRequired": false,
        "isCollection": true,
        "properties": {
            "FileTypes": ".doc,.docx,.pdf,.png,.jpg,.tiff,.jpeg"
        }
    }
   ],
   "form": {
      "items": [
        {
            "type": "FacilityFormParameter",
            "properties": {
                "ParameterName": "Driver",
                "ShowHeaders": "True",
                "IsReadOnly": "False",
                "IsHidden": "False",
                "Label": "Водитель",
                "ValueChangedHandler": ""
            }
        },
        {
            "type": "FacilityFormGroup",
            "name": "DateGroup"
        },
        {
            "type": "FacilityFormParameter",
            "properties": {
                "ParameterName": "StartDate",
                "GroupName": "DateGroup",
                "ShowHeaders": "True",
                "IsReadOnly": "False",
                "IsHidden": "False",
                "Label": "Дата начала действия",
                "ValueChangedHandler": ""
            }
        },
        {
            "type": "FacilityFormParameter",
            "properties": {
                "ParameterName": "EndDate",
                "GroupName": "DateGroup",
                "ShowHeaders": "True",
                "IsReadOnly": "False",
                "IsHidden": "False",
                "Label": "Дата окончания действия",
                "ValueChangedHandler": ""
            }
        },
        {
            "type": "FacilityFormTable",
            "hint": "",
            "IsReadOnly": "False",
            "parentName": "",
            "properties": {
                "ItemAddedHandler": "",
                "ItemAddingHandler": "",
                "ItemRemovedHandler": "",
                "ItemRemovingHandler": "",
                "ShowHeaders": "True",
                "Title": "Информация о машинах",
                "Columns": [
                    {
                        "ParameterName": "Brand",
                        "Header": "Марка",
                        "IsReadOnly": "False",
                        "IsHidden": "False",
                        "ValueChangedHandler": "",
                        "CalculateFunction": "",
                        "Placeholder": ""
                    },
                    {
                        "ParameterName": "Model",
                        "Header": "Модель",
                        "IsReadOnly": "False",
                        "IsHidden": "False",
                        "ValueChangedHandler": "",
                        "CalculateFunction": "",
                        "Placeholder": ""
                    },
                    {
                        "ParameterName": "ReleaseDate",
                        "Header": "Дата выпуска",
                        "IsReadOnly": "False",
                        "IsHidden": "False",
                        "ValueChangedHandler": "",
                        "CalculateFunction": "",
                        "Placeholder": ""
                    },
                    {
                        "ParameterName": "RegNum",
                        "Header": "Рег. Номер",
                        "IsReadOnly": "False",
                        "IsHidden": "False",
                        "ValueChangedHandler": "",
                        "CalculateFunction": "",
                        "Placeholder": ""
                    },
                    {
                        "ParameterName": "MaxWeight",
                        "Header": "Максимальный допустимый вес",
                        "IsReadOnly": "False",
                        "IsHidden": "False",
                        "ValueChangedHandler": "",
                        "CalculateFunction": "",
                        "Placeholder": ""
                    }
                ]
            }
        },
        {
            "type": "FacilityFormParameter",
            "properties": {
            "ParameterName": "Attachment",
            "ShowHeaders": "True",
            "IsReadOnly": "False",
            "IsHidden": "False",
            "Label": "Дополнительные документы",
            "ValueChangedHandler": ""
            }
        }
      ]
    }
  }

Теперь форма выглядит так:

Один из способов по передаче документа в RX. Требуется вернуться к услуге в xml, добавим туда следующий вспомогательный параметр:

<facilityParameter type="FacilityParameterString" name="ImportedApplicationLinks" isRequired="false" isCollection="false">
  <maxLength>1000</maxLength>
  <multiline>true</multiline>
</facilityParameter>

В него мы поместим параметр с id, импортированных документов в RX.

Теперь добавим шаги, в которых импортируем документы в rx и получим их id:

<flowStep index="1" name="ImportApplicationRX" title="Импортировать приложение в RX" type="ImportDocumentGroupStep">
  <property name="NextStepIndex">2</property>
  <property name="TargetSystem">CertifySolution</property>
  <property name="ImportingDocuments" binding="Attachment" type="StoredDocument[]" />
  <property name="DocumentGroup">ISimpleDocuments</property>
  <property name="ImportedDocuments" binding="ImportedApplicationLinks,Mode=PropertyToParameter" />
</flowStep>
<flowStep index="3" name="SetInfo" title="Занесение подтверждающих документов в отчет" type="ExecuteFunctionStep">
  <property name="TargetSystem">CertifySolution</property>
  <property name="NextStepIndex">-1</property>
  <property name="ExecutionMethod">POST</property>
  <property name="importedDocumentLinks" binding="ImportedDocumentLinks"></property>
  <property name="FunctionName">Certify.SetAttachments</property>
</flowStep>

В итоге xml выглядит так:

<?xml version="1.0" encoding="utf-8"?>
<facility id="23fa024d-859c-48b4-85ac-ab5f26b40a34" name="TransportPass">
  <authorization>
    <allowedRoles>Employee</allowedRoles>
  </authorization>
  <title>Создать пропуск для транспорта</title>
  <description></description>
  <facilityParameters>
    <facilityParameter type="FacilityParameterString" name="Values" defaultValue="" isRequired="false" isCollection="false">
      <maxLength>2000</maxLength>
      <multiline>false</multiline>
    </facilityParameter>
    <facilityParameter type="FacilityParameterString" name="ImportedApplicationLinks" isRequired="false" isCollection="false">
      <maxLength>1000</maxLength>
      <multiline>true</multiline>
    </facilityParameter>
  </facilityParameters>
  <facilityFormItems>
  </facilityFormItems>
  <facilityFlowScheme firstStepIndex="0" lastStepIndex="-1">
    <flowSteps>
      <flowStep index="0" name="SetInfo" title="Создание пропуска и занесение информации в него" type="ExecuteFunctionStep">
        <property name="TargetSystem">CertifySolution</property>
        <property name="NextStepIndex">1</property>
        <property name="ExecutionMethod">POST</property>
        <property name="jsonValue" binding="Values"/>
        <property name="FunctionName">Certify.CreateAndFillOutTransportPass</property>
      </flowStep>
      <flowStep index="1" name="ImportApplicationRX" title="Импортировать приложение в RX" type="ImportDocumentGroupStep">
        <property name="NextStepIndex">2</property>
        <property name="TargetSystem">CertifySolution</property>
        <property name="ImportingDocuments" binding="Attachment" type="StoredDocument[]" />
        <property name="DocumentGroup">ISimpleDocuments</property>
        <property name="ImportedDocuments" binding="ImportedApplicationLinks,Mode=PropertyToParameter" />
      </flowStep>
      <flowStep index="2" name="SetInfo" title="Занесение подтверждающих документов в отчет" type="ExecuteFunctionStep">
        <property name="TargetSystem">CertifySolution</property>
        <property name="NextStepIndex">-1</property>
        <property name="ExecutionMethod">POST</property>
        <property name="importedDocumentLinks" binding="ImportedDocumentLinks"></property>
        <property name="FunctionName">Certify.SetAttachments</property>
      </flowStep>
  </flowSteps>
  </facilityFlowScheme>
  <openedEventHandler><![CDATA[
    window.fillValues = function() {
      functions.setValue('Values', '');
      functions.setValue('Values', '[' + JSON.stringify(functions.getValues()) + ']');
    }
  ]]></openedEventHandler>
  <beforeSubmitEventHandler><![CDATA[
    window.fillValues();
    resolve();
  ]]></beforeSubmitEventHandler>
</facility>

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

/// <summary>
/// Преобразует строку JSON с ссылками на документы в список их идентификаторов.
/// </summary>
/// <param name="jsonDocLinks">Строка JSON с данными о ссылках на документы.</param>
/// <returns>Список идентификаторов документов.</returns>
public List<long> GetIdsByDocumentLinks(string importedDocumentLinks)
{
  if (string.IsNullOrWhiteSpace(importedDocumentLinks))
    return new List<long>();
  
  List<Dictionary<string, string>> datas = JsonConvert.DeserializeObject<List<Dictionary<string, string>>>(importedDocumentLinks);

  return datas.Select(data => long.Parse(data["Id"])).ToList();
}

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

Пока комментариев нет.

Авторизуйтесь, чтобы написать комментарий