Импорт данных в справочник, содержащий свойство-коллекцию

20 4

Цель данной статьи - поделиться опытом модификации утилиты импорта. Задача - создание записей в справочнике, который содержит свойство-коллекцию.

В качестве примера возьмем справочник "Продолжительности отпусков" (VacationDuration) из модуля HRPro. Данный справочник используется при планировании отпусков в организации. Справочник содержит свойства: сотрудник, год отпуска и свойство-коллекцию AvailableDuration со свойствами вид отпуска и доступное количество дней.

Чтобы по сотруднику можно было запланировать отпуск, по нему должны быть созданы записи в этом справочнике с перечислением доступных дней по видам отпуска. Утилита импорта в своем коробочном варианте не работает с данным справочником и, главное, не имеет примеров реализации кейса с импортом в свойство-коллекцию.

Для решения данной задачи взята за основу реализация работы с версиями в коробке утилиты.

Описание модификаций


Для работы со свойством-коллекцией AvailableDuration необходимо определить класс в папке models IAvailableDurations, содержащий свойства справочника:

using System;
using System.Collections.Generic;
using System.Text;

namespace ImportData.IntegrationServicesClient.Models
{
    public class IAvailableDurations
    {
        public int Id { get; set; }
        public IVacationKinds VacationKind { get; set; }
        public int DaysCount { get; set; }
    }
}

Далее, создаем класс в папке models для нашего справочника IVacationDurations:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace ImportData.IntegrationServicesClient.Models
{
    [EntityName("Продолжительности отпусков")]
    public class IVacationDurations
    {
        public int Id { get; set; }
        public string Status { get; set; }
        public string Name { get; set; }
        public IEmployees Employee { get; set; }
        public DateTime Year { get; set; }
        public string Details { get; set; }
        public IEnumerable<IAvailableDurations> AvailableDuration { get; set; }
        public string TotalDaysInfo { get; set; }
        public int TotalDays { get; set; }

Свойство коллекцию объявляем с типом IEnumerable

public IEnumerable<IAvailableDurations> AvailableDuration { get; set; } 

Далее необходимо в классе справочника IVacationDurations объявить метод CreateAvailableDuration(), который будет добавлять элементы в свойство коллекцию AvailableDuration:

public IAvailableDurations CreateAvailableDuration(IVacationKinds VacationKind, int DaysCount)
        {
            var availableDuration = Client.Instance().For<IVacationDurations>()
            .Key(this.Id)
            .NavigateTo(x => x.AvailableDuration)
            .Set(new IAvailableDurations() { VacationKind = VacationKind, DaysCount = DaysCount })
            .InsertEntryAsync()
            .Result;

            if (availableDuration == null)
                return null;

            return availableDuration;
        }

Далее, в папке Databooks создаем класс VacationDuration для считывания данных из шаблона.
В конце метода SaveToRX(), когда полученные из шаблона данные отправляются в BusinessLogic, вызываем метод CreateAvailableDuration()

  • для добавления элемента в коллекцию той же сущности - перед UpdateEntity(),
  • для создания новой сущности - после метода CreateEntity().
           try
            {
                var vacationDurations = BusinessLogic.GetEntityWithFilter<IVacationDurations>(x =>
                x.Employee.Id == employee.Id && x.Year.Year == year.Year, exceptionList, logger, true);
                if (vacationDurations != null)
                {
                    vacationDurations.CreateAvailableDuration(vacationKind, daysCount);
                    var updateEntity = BusinessLogic.UpdateEntity<IVacationDurations>(vacationDurations, exceptionList, logger);
                    return exceptionList;
                }

                var vacationDuration = new IVacationDurations();
                vacationDuration.Employee = employee;
                vacationDuration.Year = year;
                vacationDuration.Status = BusinessLogic.GetPropertyVacationDurationStatus("Active");

                var vacationDurationEntity = BusinessLogic.CreateEntity<IVacationDurations>(vacationDuration, exceptionList, logger);

                vacationDurationEntity.CreateAvailableDuration(vacationKind, daysCount);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                exceptionList.Add(new Structures.ExceptionsStruct { ErrorType = Constants.ErrorTypes.Error, Message = ex.Message });

                return exceptionList;
            }

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

 

Заключение

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

 

Алексей Дерюшев

Я бы еще упомянул, что если коллекция является обязательным свойством, то такую запись придется импортировать с помощью пакетного запроса (ODataBatch) 

Станислав Егоров

Алексей, Есть какой то пример как это сделать в утилите импорта?

Станислав Егоров

Нашел ли кто способ получать уже существующую коллекцию внутри карточки? а то прилетают по одате только внутренние ID записей.

Станислав Егоров

Станислав, я сделал. написал внутренний Expand. теперь табличную часть он мне возвращает и я могу перед добавлением проверить есть ли там это или нет.

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