// Модуль описания функций, использующихся только для импорта
uses
  { чтобы не вписывать модуль в каждый скрипт, пусть он будет загружаться
    отсюда, ходя это не лучший вариант.}
  'Un_Imp_ChildDoc74',   // exchange #3062 - перенос функционала
  'Un_Imp_ChildDoc25';   // exchange #3057


//описание доп. атрибутов необходимых при загрузке
//Line
//F_CHANGEDKBK - True, кбк заменен при загрузке
//F_PRIMARYKBK - содержит КБК из файла до замены нулями в случае его отсутсвия.
//F_CREATE_DOP - True - создаем доп. документ при загрузке, иначе не создаем.

procedure Default_F_Line(Line: Variant);
begin
  //менялся ли КБК (флаг)
  Line.setAttribute('F_CHANGEDKBK', 'False');
  //Содержит КБК не измененный(снимок КБК из файла)
  Line.setAttribute('F_PRIMARYKBK', '');
  //Не содержит тип КБК или нет значения КБК в строке
  Line.setAttribute('F_EMPTYKBK', 'False');
end;


{~GetPermissionRashUseGroupBuh
//Возвращает данные разрешения. Либо null в случае если не найдено разрешение.
//Хотя бы одна строка разрешения должна принадлежать той же группе
//по бухгалтерии, что и строка найденная в той же группе по КБК(Exchange #1997)
Exchange #2389
  Внести изменение в работу параметра в части поиска бюджетной строки по кбк,
  а именно поиск осуществлять по кбк и  «Коду цели».
  если в строке ЭД - Doc код цели не будет указан (пустая строка), будет
  подставлен код цели =0 (по бюджету ЭД в HeadChildDoc)ю
  функция перенесена из модуля QueryWork.}
function GetPermissionRashUseGroupBuh(HeadChildDoc, Doc: Variant;
  Flag: Boolean = False): Variant;
var
  sql: String;
  Xml: Variant;
  i: Integer;
  Groups: String;
  GroupsValue: array of string;
  xPurposefulgrantID: string;
begin

    try
      Result := null;
      //ищет разрешение и группы, в которые входят строки разрешения
      sql := 'Select P.Id, PL.Fundsource_Id, PL.Id PermissionLine_Id, E.Memgroup_Code' +
        ' From Permission P' +
        ' Join PermissionLine PL on P.Id = PL.Permission_Id' +
        ' Join Expbudget E on PL.Kfsr_Code = E.Kfsr_code' +
        '   and PL.Kcsr_Code = E.Kcsr_Code and PL.Kvr_Code = E.Kvr_Code' +
        '   and PL.Kesr_Code = E.Kesr_Code and PL.Kadmr_Code = E.Kadmr_Code'
       +'   and PL.purposefulgrant_id=E.purposefulgrant_id'
       +' Where P.Budget_Id = ? and P.Org_Id = ? and P.OrgAccount_Id = ?' +
        '   and P.Dispstatus_Id = 1 and P.Start_Date <= ? and P.End_Date >= ?' +
        '   and E.Estimate_Id = ? and E.Memgroup_Code <> 0';
      Query.AddStr(HeadChildDoc.getAttribute('BUDGET_ID'));

      //Flag используется для загрузки IK файлов
      if Flag
        then Query.AddStr(HeadChildDoc.getAttribute('ORG_ID'))
        else Query.AddStr(Doc.parentNode.parentNode.getAttribute('ORG_ID'));

      Query.AddStr(HeadChildDoc.getAttribute('ORGACCOUNT_ID'));
      Query.AddDate(XmlToDateTime(HeadChildDoc.getAttribute('DOC_DATE')));
      Query.AddDate(XmlToDateTime(HeadChildDoc.getAttribute('DOC_DATE')));
      Query.AddStr(HeadChildDoc.getAttribute('ESTIMATE_ID'));
      Xml := CreateOleObject('Microsoft.XmlDom');
      Xml.LoadXml(Query.Run(sql));
      Xml := Xml.documentElement;
      //либо не нашли разрешение, либо строки разрешения не входят ни в одну группу
      if Xml.childNodes.Length = 0 then
        Exit;
      Groups := '';
      for i := 0 to Xml.childNodes.Length - 1 do
      begin
        //проверка на всяк. случай не выбралось ли несколько разрешений по счету.
        if (Xml.childNodes.Item[0].getAttribute('ID') <>
          Xml.childNodes.Item[i].getAttribute('ID')) then Exit;
        //накапливаем группы, участвующие в строках разрешения
        if Groups = '' then
          Groups := Xml.childNodes.Item[i].getAttribute('MEMGROUP_CODE') + ', '
        else
          if Pos(Xml.childNodes.Item[i].getAttribute('MEMGROUP_CODE') + ', ',
            Groups) = 0 then
            Groups := Groups + Xml.childNodes.Item[i].getAttribute('MEMGROUP_CODE') + ', ';
      end;
      //удаляем лишнее из groups;
      Delete(Groups, Length(Groups) - 1, 2);

      // exchange #2389
      xPurposefulgrantID:= Doc.getAttribute('PURPOSEFULGRANT_ID');

      if (LENGTH( xPurposefulgrantID) <= 0)
        then xPurposefulgrantID := Exch2389_GetPURPOSEFULGRANT_ID_NULL_ByBudget(
                                            HeadChildDoc.getAttribute('BUDGET_ID'));

        {
        Exch2389_GetPURPOSEFULGRANT_ID_R(
                                            Doc,
                                            HeadChildDoc.getAttribute('BUDGET_ID'),
                                            HeadChildDoc.getAttribute('ESTIMATE_ID'));
    }

      // excanhe #2389 - доработка запроса
      sql := 'Select E.Kdf_Code, E.Kdr_Code, E.Kde_Code, E.Recipient_Id, E.Fsr_Id,' +
        // exchange #3062 - косгу возвращается как доп код
        '   E.Memgroup_Code,E.purposefulgrant_id, E.Kesr_Code' +
        ' From Expbudget E' +
        ' Where E.Budget_Id = ? and E.Estimate_Id = ? and E.Kfsr_Code = ?' +
        // exchange #3062 - убран косгу
        '   and E.Kvr_Code = ?'// and E.Kesr_Code = ?
       +' and E.Kcsr_Code = ?' +
        '   and E.Kadmr_Code = ? and E.Memgroup_code in (' +
          QueryGetParamsFromValue(Groups, GroupsValue) + ')'
       +' and E.purposefulgrant_id=?'
       +' Group by E.Kdf_Code, E.Kdr_Code, E.Kde_Code, E.Recipient_Id, E.Fsr_Id,' +
        '   E.Memgroup_Code,E.purposefulgrant_id';
      Result := QueryXml( sql,
                          [ HeadChildDoc.getAttribute('BUDGET_ID'),
                            HeadChildDoc.getAttribute('ESTIMATE_ID'),
                            Doc.getAttribute('KFSR_CODE'),
                            Doc.getAttribute('KVR_CODE'),
                            //Doc.getAttribute('KESR_CODE'),
                            Doc.getAttribute('KCSR_CODE'),
                            Doc.getAttribute('KADMR_CODE'),
                            GroupsValue,
                            xPurposefulgrantID]);
      Result := Result.documentElement;
      if Result.childNodes.Length = 0 then
      begin
        Result := null;
        Exit;
      end;
      if Result.childNodes.Length > 1 then
      begin
        //проверка бюджетополучателей
        for i := 0 to Result.childNodes.Length - 1 do
          if (Result.childNodes.Item[0].getAttribute('RECIPIENT_ID') <>
            Result.childNodes.Item[i].getAttribute('RECIPIENT_ID')) then
          begin
            //обнуляем recipient_id. При обработке такого дока будет стрелятся СП,
            //однако АО настаивает на стрельбе.
            Result.childNodes.Item[0].setAttribute('RECIPIENT_ID', '');
            break;
          end;
        Result := Result.childNodes.Item[0];
        //обнуляем доп.коды
        Result.setAttribute('KDF_CODE', 0);
        Result.setAttribute('KDR_CODE', 0);
        Result.setAttribute('KDE_CODE', 0);
        Result := Result.ownerDocument.documentElement;
      end;
      Result := Result.childNodes.Item[0];
      //выбираем нужную группу в строке разрешения
      Xml := Xml.selectNodes('//ROW[@MEMGROUP_CODE=' +
        Result.getAttribute('MEMGROUP_CODE') + ']');
      Xml := Xml.Item[0];
      //копируем атрибуты xml первого нода в Result
      for i := 0 to Xml.Attributes.Length - 1 do
        Result.setAttribute(Xml.Attributes[i].nodeName, Xml.Attributes[i].nodeValue);
      except
        ExceptionLog( 'Сбой Un_Import.GetPermissionRashUseGroupBuh');
    end;

end;



{~PayKindSetAsAzk
Функция устанавливает соответсвие поля вида платежа м/у АЦК и форматом FK.
exchange #2604
  в тфф10 значение вида платежа в поле VID_PL (BDPD) =3 есть, в ТФФ11 есть,
  а ТФФ11.2 уже нет и дальше тоже не будет.
  ТФФ11.2 это дополнение к ТФФ11, поэтому значение =3 по ТФФ11 тоже уже
  не должно быть.
  в функции значение 3 из файла заменяем на пусто, поскольку АЦК-Ф
  ругается на значение =3.}
function PayKindSetAsAzk(PayKind: String): String;
begin
  case PayKind of
    '1': Result := '2'; //почтой
    '2': Result := '3'; //телеграфом
//    '3': Result := '1'; //электронно - отменено exchange #2604 без проверки ТФФ
    '4': Result := '4'; // срочно
  else
    Result := '';
  end
end;

//Возвращает ID cтатуса лица оформившего платеж, если есть в справочнике, и пустую строку иначе, поле "101"
function Get_Author_Id(Author_Id: String): String;
begin
  Result := '';
  if Trim(Author_Id) <> '' then
    if Author_IdExists(Author_Id) then
      Result := Trim(Author_Id);
end;

//Берем последних 3 знака КБК.
//И на основе них мы возвращаем PI_ANAL_KIND
//ANAL_KIND=0 - нет
//ANAL_KIND=1 - доходы
//ANAL_KIND=2 - расходы
//ANAL_KIND=3 - источники
function GetPi_Anal_Kind(Kes: String): String;
begin
  Result := '1';
  if Trim(Kes) <> '' then
    Result := QueryField('Select Anal_Kind From Kes Where Code = ?', [Kes],
      'ANAL_KIND');
  if Result = '0' then
    Result := '1';
end;

{~AddReplaceAttrVal
  копирует атрибуты или заменяет значение существующих атрибутов в ноде
  Dest из нода Source}
procedure AddReplaceAttrVal(Source, Dest: Variant);
var
  i: Integer;
begin

    try
      for i := 0 to Source.Attributes.Length - 1
        do Dest.setAttribute(Source.Attributes[i].nodeName, Source.Attributes[i].nodeValue);

      except
        ExceptionLog( 'Сбой Un_Import.AddReplaceAttrVal');
    end;

end;


{~UpdateExtStatusED
  вынесена отдельная часть изменения статуса выгрузки из подпрограммы
  Documents_Answer для доработки exchange #2930.
  это необходимо из за того, что поиск эд 114 для загрузки по IK.UF
  реализован по exchange #2931, и если эд найден - то меняем статус выгрузки.
  замена статуса выгрузки не меняется. }
procedure UpdateExtStatusED( aDocID: string; aDoc: Variant);
var
  xExstatus_Id: String;
begin

    try
      xExstatus_Id := IfThen(StrToBool(aDoc.getAttribute('DECLINE')), '3', '4');

      // для обработки операции update_extstatus добавлено поле FROM, описывающее
      // что операция выполняется из azk-exchange. это связано с обработкой
      // поля даты утверждения закона в методе fill_date УиБН, вложенных в ЭД.
      try
        WriteLog( FORMAT( 'Смена внешнего статуса документа/%s',
                          [ IfThen( xExstatus_Id = '4',
                                    '"Проверен"',
                                    '"Ошибка проверки"')]));


        if VarIsNull( aDoc.getAttribute('REMARK'))
          then ExecProc(  'DOCUMENT',
                          [ 'action', 'update_extstatus',
                            'class', aDoc.getAttribute('class'),
                            'ID', aDocID,
                            'EXTSTATUS_ID', xExstatus_Id,
                            'CARRY_DATE', aDoc.getAttribute('CARRY_DATE'),
                            'FROM', 'AZK_Exchange'],
                          aDoc.getAttribute('F_BUDGET_ID'))
          else ExecProc(  'DOCUMENT',
                          [ 'action', 'update_extstatus',
                            'class', aDoc.getAttribute('class'),
                            'ID', aDocID,
                            'EXTSTATUS_ID', xExstatus_Id,
                            'CARRY_DATE', aDoc.getAttribute('CARRY_DATE'),
                            'FROM', 'AZK_Exchange',
                            'REMARK', aDoc.getAttribute('REMARK')],
                          aDoc.getAttribute('F_BUDGET_ID'));
        except
          WriteInfo('Ошибка при переводе внешнего статуса: ' + LastException.Message);
      end
      except
        ExceptionLog( 'Сбой UpdateExtStatusED');
    end;

end;


{~Documents_Answer
  процедура для поиска документов и линковки ответных документов.
  Не подавать сюда линковку ПП.
  в Doc - должны быть атрибуты как в документе АЦК. (DOC_DATE и т.п.),
  а также class (содержащий класс документа)

  exchange #2638
  добавлен маркер файлов.
  доп.поиск ЭД 114х классов реализован только для файлов VA,VB.}
procedure Documents_Answer(Doc: Variant; aFileMarker: string = '');
var
  Doc_Id: String;
begin

    try
      case Doc.getAttribute('class') of
        '148': Doc_Id := GetAnswerDocIdRR(Doc);
        '198': Doc_Id := GetAnswerDocIdBu(Doc);
        // exchange #2638 - доп.поиск для ЭД 114го класса:
        // Уведомление об уточнении вида и принадлежности платежа
        '114': if (aFileMarker in ['VA','VB'])
                 then Doc_Id := GetAnswerDocId_2638_114(Doc)
                 else Doc_Id := GetAnswerDocId(Doc);
        else   Doc_Id := GetAnswerDocId(Doc);
      end;//case//
      if Doc_Id <> ''
        then UpdateExtStatusED( Doc_Id, Doc)
        else WriteInfo('Документ не найден');
      except
        ExceptionLog( 'Сбой Un_Import.Documents_Answer');
    end;

end;

{~UpdateExtStatusDoc
  изменение статуса выгрузки документа или другой операции (aAction).
  в журнале Info делается пометка aLogInfo.
  при сбое ничего не логируется и сбой выносится наружу (raise).
  вынесено в отдельную подпрограмму для унификации операции и удобства отладки.

  если указан параметр aCarryDateByUpdateDoc=true или aRemarkByUpdateDoc=true,
  то после выполнения основной операции aAction выполняется операция update
  с обновлением полей carrydate и/или remark в ЭД.

  параметры
    aAction - операция
        например:
        'update_extstatus' - изменение внешнего статуса ЭД
    aLogInfo - запись в журнал LogInfo
        например:
        FORMAT( 'Смена внешнего статуса документа на "%s"',
                          [ ExtStatusCaptionByID( aExtStatusID)])
    aBudgetID - бюджет
    aDocID - ид.ЭД
    aClassID - ид.класса ЭД
    aExStatusID - ид.статуса выгрузки
    aCarryDate - дата исполнения
    aRemark - примечание
    aCarryDateByUpdateDoc - обновление поля aCarryDate методом update в отдельной операции.
    aRemarkByUpdateDoc - обновление поля aRemark методом update в отдельной операции.
  результат
    -}
procedure UpdateExtStatusDoc( aAction: string;
                              aLogInfo: string;
                              aBudgetID: string;
                              aDocID: string;
                              aClassID: string;
                              aExtStatusID: string;
                              aCarryDate: string;
                              aCarryDateByUpdateDoc: boolean;
                              aRemark: string;
                              aRemarkByUpdateDoc: boolean);
var
  xXml: Variant;
  xXmlDoc: Variant;
begin

    try
      ExecProc( 'DOCUMENT',
                [ 'action', aAction,
                  'class', aClassID,
                  'ID', aDocID,
                  'EXTSTATUS_ID', aExtStatusID,
                  'CARRY_DATE', aCarryDate,
                  'REMARK', aRemark],
                aBudgetID);


      // если основная операция aAction не выполнена, менять поля ЭД не имеет
      // смысла, хотя этот
      if (aRemarkByUpdateDoc OR aCarryDateByUpdateDoc) then begin
        xXml := CreateOleObject('Microsoft.XmlDom');
        xXmlDoc := xXml.appendChild( xXml.createElement('DOCUMENT'));
        xXmlDoc.SetAttribute('action', 'update');
        xXmlDoc.SetAttribute('class', aClassID);
        xXmlDoc.SetAttribute('ID', aDocID);
        if aCarryDateByUpdateDoc
          then xXmlDoc.SetAttribute('CARRY_DATE', aCarryDate);
        if aRemarkByUpdateDoc
          then xXmlDoc.SetAttribute('REMARK', aRemark);

        ExecXml( xXml.xml, aBudgetID);
      end;

      WriteInfo( aLogInfo);
      except
        // особенность описания сбоя в том, что при отладке сохраняется
        // описание сбоя с учетом названия этой подпрограммы,
        // а в клиентской сборке логируется только описания сбоя без
        // названия подпрограммы, где вызван сбой.
        ExceptionLog( ''

             );
    end;

end;


{~Documents_Decline
  процедура для поиска отказанных в протоколе документов.
  в Doc - должны быть атрибуты как в документе АЦК. (DOC_DATE и т.п.),
  а также class (содержащий класс документа);

  exchange #2462 - доработка:
  aStatusDocEx - проверка нужного статуса ЭД.
    по умолчанию - как в запросах: проверка жесткого статуса, но если параметр
    <>'', то производится проверка состояния ЭД по этому статусу.

  exchange #2531 - доработка:
  1.2) при поиске ЭД 11го и 75го классов, если будет определен атрибут FIMP_PT_ZN_MODE
      в Doc = 1, то в результате, если нужный ЭД найден, в XML Doc формируется
      узел FIMP_PT_ZN_FOUND с идентификатором найденного ЭД.
      если документ не найден - атрибут не формируется.
      так же, атрибут FIMP_PT_ZN_MODE=1 указывает, что требуется перевод
      состояния ЭД 11 и 75го классов по заданию #2531 отлично от старого варианта.
  2.2) изменение статуса для ЭД 221го класса аналогично ЭД 222го класса.}
procedure Documents_Decline(Doc: Variant; aStatusDocEx: string = '');
var
  Doc_Id, Exstatus_Id: String;
  DocLoad: Variant;
  xClassID: string;
begin

    try
      DocLoad := CreateOleObject('Microsoft.XmlDom');
      Exstatus_Id := Doc.getAttribute('DECLINE');
      Class_id := -1;
      //изврат какой то, есть же функции проще!
      // exchange #2462 - добавлен доп.код статуса
      Doc_Id := GetDeclineDocId(Doc, aStatusDocEx);

      if Doc_Id <> '' then begin
        xClassID := Doc.getAttribute('class');

        // exchange #2531
        if (xClassID in [ '11', '75']) then
          // для ЭД классов 11 и 75 проверяем атрибут специального поиска.
          // это нужно для того, что если не будет найден ЭД одного класса,
          // искать ЭД другого класса
          if (VarToStr( Doc.GetAttribute( 'FIMP_PT_ZN_MODE')) = '1') then begin
            // возвращаем ид.найденного ЭД как новый атрибут в XML Doc.
            Doc.SetAttribute( 'FIMP_PT_ZN_FOUND', Doc_Id);
            // в разных ЭД вызываются разные методы отказа банком
            if (xClassID = '11')
              then
                // для ЭД 11-го класса вызывается decline со статуса 6 или 13
                try
                  UpdateExtStatusDoc(
                          'decline',
                          'Смена статуса документа на "Отказан банком"',
                          Doc.getAttribute('F_BUDGET_ID'),
                          Doc_Id,
                          xClassID,
                          Exstatus_Id,
                          Doc.getAttribute('CARRY_DATE'), FALSE,
                          Doc.getAttribute('REMARK'), FALSE);
                  except
                    WriteInfo('Ошибка при переводе внешнего статуса: ' + LastException.Message);
                end
              else
                // для ЭД 75-го класса вызывается user_decline со статуса 13
                try
                  UpdateExtStatusDoc(
                          'user_decline',
                          'Смена статуса документа на "Отказан банком"',
                          Doc.getAttribute('F_BUDGET_ID'),
                          Doc_Id,
                          xClassID,
                          Exstatus_Id,
                          Doc.getAttribute('CARRY_DATE'), FALSE,
                          Doc.getAttribute('REMARK'), FALSE);
                  except
                    WriteInfo('Ошибка при переводе внешнего статуса: ' + LastException.Message);
                end;
            EXIT;
          end;

        case xClassID of
          // exchange #2528
          // для ЭД 195го класса переводим ЭД на "отказан банком", если указана
          // спец.опция в Doc (атрибут F195_PAYDOC_CODE=PP)
          // decline работает только с версии АЦК-финансы 2.30!
          // операцей decline пользоваться уже нельзя.
          // для перевода статуса нужно пользоваться update_extstatus.
          '195':
              if (VarToStr( Doc.GetAttribute( 'F195_PAYDOC_CODE')) = 'PP') then begin
                try
                  UpdateExtStatusDoc(
                          'update_extstatus',
                          'Смена статуса документа на "Отказан банком"',
                          Doc.getAttribute('F_BUDGET_ID'),
                          Doc_Id,
                          xClassID,
                          Exstatus_Id,
                          Doc.getAttribute('CARRY_DATE'), FALSE,
                          Doc.getAttribute('REMARK'), FALSE);
                  except
                    WriteInfo('Ошибка при переводе внешнего статуса: ' + LastException.Message);
                end;
                EXIT;
              end;

          // exchange #2751
          // ЭД "Платежное поручение" (13 класс) переходит со статуса
          // "отправлен (выгружен)" на статус Отказан при импорте из PT
          // с типом PP.
          // старая логика (ниже) не меняется. это сделано на случай, если
          // эта функция применяется еще где нибудь.
          '13':
              if (VarToStr( Doc.GetAttribute( 'F13_PAYDOC_CODE')) = 'PP') then begin
                try
                  DocLoad.LoadXml(
                        ExecProc( 'DOCUMENT',
                                  [ 'action', 'simple_decline',
                                    'class', Doc.getAttribute('class'),
                                    'ID', Doc_Id,
                                    'REMARK', VarToStr( Doc.getAttribute('REMARK'))],
                                  Doc.getAttribute('F_BUDGET_ID')));
                  WriteInfo('Статус "Отказан"');
                  except
                    WriteInfo('Ошибка при переводе статуса: ' + LastException.Message);
                end;
                EXIT;
              end;
        end;//case//

        case xClassID of
          '13': try
                  DocLoad.LoadXml(ExecProc('DOCUMENT',
                    ['action', 'spawn_decline', 'class', Doc.getAttribute('class'), 'ID', Doc_Id],
                    Doc.getAttribute('F_BUDGET_ID')));
                  DocLoad := DocLoad.documentElement;
                    updateDoc5(Doc.getAttribute('F_BUDGET_ID'),
                      DocLoad.getAttribute('DOCUMENT_ID'), Doc.getAttribute('CARRY_DATE'),
                        Doc.getAttribute('FOREIGN_KEY'), Doc.getAttribute('REMARK'), True);
                    WriteInfo('Слинкован/Статус "Отказан банком"');
                  except
                    WriteInfo('Ошибка при переводе внешнего статуса: ' + LastException.Message);
                end;

          // класс 221 по exchange #2531 аналогичен классу 222.
          // после изменения БЛ по АЦК-Ф-Р 3876, вызывать action=decline нельзя.
          // для изменения состояния нужно поменять статус выгрузки update_extstatus.
          // при этом будет изменен статус ЭД в зависимости от системной настройки
          // "Автоматически обрабатывать Расшифровку сумм неиспользованных средств БУ/АУ"
          // / "Расшифровку сумм неиспользованных средств".
           '222',
           '221':
                try
                  UpdateExtStatusDoc(
                          'update_extstatus',
                          FORMAT( 'Смена внешнего статуса документа на "%s"',
                                  [ ExtStatusCaptionByID( Exstatus_Id)]),
                          Doc.getAttribute('F_BUDGET_ID'),
                          Doc_Id,
                          xClassID,
                          Exstatus_Id,
                          Doc.getAttribute('CARRY_DATE'), FALSE,
                          Doc.getAttribute('REMARK'), FALSE);
                  except
                    WriteInfo('Ошибка при переводе внешнего статуса: ' + LastException.Message);
                end;

          else
            try
              // exchange #2530
              // тут есть проблема. поле CARRY_DATE может отсутствовать во
              // входном ЭД, поэтому тут проверяем, если атрибут даты утверждения
              // не указан в ЭД, то в задании изменения статуса его тоже не передаем.
              // то же и с полем REMARK.
              // поэтому тут 4 варианта задания.

              if ( LENGTH( VarToStr( Doc.getAttribute('CARRY_DATE'))) <= 0)
                then
                  if VarIsNull( Doc.getAttribute('REMARK'))
                    then ExecProc( 'DOCUMENT',
                                  [ 'action', 'update_extstatus',
                                    'class', IfThen( class_id > 0,
                                                      class_id,
                                                      Doc.getAttribute('class')),
                                    'ID', Doc_Id,
                                    'EXTSTATUS_ID', Exstatus_Id],
                                  Doc.getAttribute('F_BUDGET_ID'))
                    else ExecProc( 'DOCUMENT',
                                  [ 'action', 'update_extstatus',
                                    'class', IfThen( class_id > 0,
                                                      class_id,
                                                      Doc.getAttribute('class')),
                                    'ID', Doc_Id,
                                    'EXTSTATUS_ID', Exstatus_Id,
                                    'REMARK', Doc.getAttribute('REMARK')],
                                  Doc.getAttribute('F_BUDGET_ID'))
                else
                  if VarIsNull( Doc.getAttribute('REMARK'))
                    then ExecProc( 'DOCUMENT',
                                  [ 'action', 'update_extstatus',
                                    'class', IfThen( class_id > 0,
                                                      class_id,
                                                      Doc.getAttribute('class')),
                                    'ID', Doc_Id,
                                    'EXTSTATUS_ID', Exstatus_Id,
                                    'CARRY_DATE', Doc.getAttribute('CARRY_DATE')],
                                  Doc.getAttribute('F_BUDGET_ID'))
                    else ExecProc( 'DOCUMENT',
                                  [ 'action', 'update_extstatus',
                                    'class', IfThen( class_id > 0,
                                                      class_id,
                                                      Doc.getAttribute('class')),
                                    'ID', Doc_Id,
                                    'EXTSTATUS_ID', Exstatus_Id,
                                    'CARRY_DATE', Doc.getAttribute('CARRY_DATE'),
                                    'REMARK', Doc.getAttribute('REMARK')],
                                  Doc.getAttribute('F_BUDGET_ID'));
              WriteInfo( FORMAT( 'Смена внешнего статуса документа на "%s".',
                                  [ QueryField( 'select CAPTION from EXTSTATUS '
                                               +' where id=?',
                                                [ Exstatus_Id],
                                                'CAPTION')]));
            except
              WriteInfo('Ошибка при переводе внешнего статуса: ' + LastException.Message);
            end;
        end;//case//
      end
      else
        WriteInfo('Документ не найден');
      except
        ExceptionLog( 'Сбой Un_Import.Documents_Decline');
    end;

end;




{~UpdateStatusEDEx
  изменение статуса эд указанного класса.
  aText - описание операции (в журнал)
  aAction - операция. если не указана - не выполняется.
  aExtStatusID - изменение внешнего статуса.
                  если указан, выполняется update_extstatus.}
procedure UpdateStatusEDEx( aBudgetID, aID, aClass, aAction: string;
                            aText: string = '';
                            aExtStatusID: string = '';
                            aLogInfo: boolean = TRUE);
begin

    try
      if (LENGTH( aText) > 0) then
        if aLogInfo
          then WriteInfo( aText)
          else WriteLog( aText);

      if (LENGTH( aAction) > 0) then begin

        ExecProc( 'DOCUMENT',
                  [ 'action', aAction,
                    'class', aClass,
                    'ID', aID],
                  aBudgetId);
      end;

      if (LENGTH( aExtStatusID) > 0) then begin

        ExecProc( 'DOCUMENT',
                  [ 'action', 'update_extstatus',
                    'class', aClass,
                    'ID', aID,
                    'EXTSTATUS_ID', aExtStatusID],
                  aBudgetId);
      end;
      except
        ExceptionLog( 'Сбой UpdateStatusEDEx');
    end;

end;

{~Create_193_From_24
  создание ЭД 193го класса из ЭД 24го класса.
  созданный 193й обрабатывать до конечного статуса обработка завершена (10)
  если параметр aStateTo10=true.}
procedure Create_193_From_24( aDocBudget, aDoc24ID: string;
                              aStateTo10: boolean = FALSE);
var
  xDoc193ID: string;
  xStatusED: string;
begin

    try
      WriteInfo('Формирование документа для линковки');
      WriteInfo('АЦК: "Распоряжение на зачисление средств на л/с"', True);

      //процедура создания доп доков из 24 класса
      try
        UpdateStatusEDEx( aDocBudget,
                          aDoc24ID,
                          '24',
                          'spawn_money_transfer_order');
{
        ExecProc( 'DOCUMENT',
                  [ 'action', 'spawn_money_transfer_order',
                    'class', '24',
                    'ID', aDoc24ID],
                  aDocBudget);
}
        WriteInfo('Создан', True);
        // менять статус созданного 193го надо ?
        if aStateTo10 then begin
          // ищем id созданного эд 193го из 24го
          xDoc193ID := QueryField(  ' select m.id ID from moneytransferorder m'
                                   +' join document d on d.id=m.document_id'
                                   +' join payorder p on p.document_id=d.parent_id'
                                   +' where p.ID = ? and d.documentclass_id=193',
                                    [ aDoc24ID],
                                    'ID');

          repeat
            xStatusED := QueryField(
                              ' select a.DISPSTATUS_ID S'
                             +' from moneytransferorder a where a.ID = ?',
                              [ xDoc193ID],
                              'S',
                              FALSE);
            case xStatusED of
              '1': begin
                      WriteInfo('Статус ЭД: В обработке');
                      try
                        UpdateStatusEDEx(
                              aDocBudget,
                              xDoc193ID,
                              '193',
                              'finalize',
                              'Выполняется "Обработка"...',
                              '',
                              TRUE);
                        except
                          WriteInfo('Ошибка при обработке ЭД: '
                                    + LastException.Message);
                          BREAK;
                      end;
                    end;

              '10': begin
                      WriteInfo( 'Статус ЭД: Обработан.');
                      BREAK;
                    end;

              else begin
                      WriteInfo( FORMAT( 'Статус ЭД %s не соответствует дальнейшей обработке.',
                                          [ xStatusED]));
                      BREAK;
                    end;
            end;//case//
          until FALSE;
        end;
        except
          WriteInfo('Ошибка при создании документа: ' + LastException.Message);
      end
      except
        ExceptionLog( 'Сбой Un_Import.Create_193_From_24');
    end;

end;


{~Create_193_From_24_ByIK_BDPD
  создание ЭД 193го класса из ЭД 24го класса, который создан из IK.BDPD.
  exchange #2600
  пп. 2.9.2.4 добавлено создание ЭД 193го класса из 24го из IK.BDPD
  для этого проверяем вариант с созданием из IK и наличием доп.атрибута.
  exchange #2831
  также требуется создавать ЭД из 24го при счете, начинающимся на 30.
  exchange #2850
  созданный 193й обрабатывать до конечного статуса (обработка завершена).}
function Create_193_From_24_ByIK_BDPD( aDoc: Variant; aDoc24ID: string): boolean;
begin

    try
      Result := FALSE;
      if (aDoc.getAttribute('F_ORIGINAL_TYPE') = 'IK') then
        if ( VarToStr( aDoc.GetAttribute( '__IK_MODE__')) = '2600_2.9.2.4')
          then begin
            Create_193_From_24( aDoc.getAttribute('F_BUDGET_ID'), aDoc24ID, TRUE);
            Result := TRUE;
          end;
      except
        ExceptionLog( 'Сбой Un_Import.Create_193_From_24_ByIK_BDPD');
    end;

end;


//проверка повторной загрузки + вставка
procedure Documents_DebCred(Doc: Variant);
var
  i: Integer;
begin

    try
      //класс документа не проверяем т.к. атрибут F_CRASH24
      //должен присутствовать только в 24 классе
      if (not VarIsNull(Doc.getAttribute('F_CRUSH24'))) and
            (Doc.childNodes.Item[0].childNodes.Length > 1) and
            (StrToBool(Doc.getAttribute('F_CRUSH24'))) then
      begin
    
        //eсли загружали первый раз без дробления доков, потом поставили дробить,
        //т.к. FOREIGN_KEY для раздробленных документов будет уже другим, то надо
        //проверить снесли ли не раздробленный документ из базы, чтобы не было дублей
        if IsLoaded(Doc.getAttribute('F_BUDGET_ID'), Doc.getAttribute('class'),
          Doc.getAttribute('FOREIGN_KEY'), Doc) then
        begin
          WriteInfo('Повторная загрузка документа - пропущен', True);
          Exit;
        end;
        // разбиваем документ
        Doc := CrushDoc(Doc);
        Doc := Doc.documentElement;
        WriteInfo('Внимание: Многострочное приложение к выписке кредитовое разделено' +
          ' на однострочные. См. параметр "Схема загрузки кредитового приложения"', True);
        for i := 0 to Doc.childNodes.Length - 1 do
        begin
          Doc := Doc.childNodes.Item[i];
          ProcessDocument_DebCred(Doc);
          Doc := Doc.parentNode;
        end;
      end
      // не разбивали
      else
        ProcessDocument_DebCred(Doc);
      except
        ExceptionLog( 'Сбой Un_Import.Documents_DebCred');
    end;

end;


{~DoProcessDocument_ED5_
  перенесено в подпрограмму с целью удаления дубля кода}
procedure DoProcessDocument_ED5_( aDoc, aDocLoad: Variant);
var
  xXmlChildDoc: Variant;
  xChildDoc: Variant;
  xDOC_DECLINE: boolean;
  xDOCUMENT_ID: string;
begin

    try
      xDOC_DECLINE := AttrToBoolean( aDoc, 'DECLINE');

      xXmlChildDoc := CreateOleObject('Microsoft.XmlDom');
      try

        xXmlChildDoc.LoadXml(
            ExecProc( 'DOCUMENT',
                      [ 'action', IfThen( xDOC_DECLINE,
                                          'mark_decline',
                                          'mark_finish'),
                        'class', '5',
                        'ID', GetNodeAttributeEx( aDocLoad.documentElement, 'ID')],
                        aDoc.getAttribute('F_BUDGET_ID')));

        xDOCUMENT_ID := GetNodeAttributeEx( xXmlChildDoc.documentElement,
                                            'DOCUMENT_ID');

        if xDOC_DECLINE
          then WriteLog( 'Неслинкован/Статус "Отказан банком"')
          else WriteLog( 'Неслинкован/Статус "Выполнен"');

        if AttrToBoolean( aDoc, 'F_CREATE11') then begin
          xXmlChildDoc.LoadXml('');
          if CreateChildDoc11( aDoc, xXmlChildDoc) then begin
            xChildDoc := xXmlChildDoc.documentElement;

            Exec_ChildDoc( xChildDoc.GetAttribute('BUDGET_ID'),
                           xDOCUMENT_ID,
                           xChildDoc);
          end;
        end;
        finally
          xXmlChildDoc.LoadXml('');
      end;
      except
        ExceptionProc( 'DoProcessDocument_ED5_');
    end;

end;


procedure ProcessDocument_DebCred(Doc: Variant);
var
  DocLoad, ChildDoc: Variant;
  Link_Id: String;
  i: Integer;
  xDoc_F_BUDGET_ID: string;
begin

    try
      Link_Id := '';
      xDoc_F_BUDGET_ID := Doc.getAttribute('F_BUDGET_ID');

      // проверка на повторную загрузку
      if IsLoaded( xDoc_F_BUDGET_ID,
                   Doc.getAttribute('class'),
                   Doc.getAttribute('FOREIGN_KEY'), Doc)
        then begin
          WriteInfo('Повторная загрузка документа - пропущен', True);
          EXIT;
        end;

      DocLoad := CreateOleObject('Microsoft.XmlDom');
      Doc.setAttribute( 'DOC_DATE',
                        DateTimeToXml(StrToDate(Doc.getAttribute('DOC_DATE'))));

      if Doc.getAttribute('class') = 5 then begin

        if not LinkDoc(Doc) then
{          if (not VarIsNull(Doc.getAttribute('F_CRUSH5')))
            and (Doc.childNodes.Item[0].childNodes.Length > 1)
            and (StrToBool(Doc.getAttribute('F_CRUSH5'))) then
          begin}
          if (AttrToBoolean( Doc, 'F_CRUSH5')
              and (Doc.childNodes.Item[0].childNodes.Length > 1)) then begin
            // разбиваем документ
            Doc := CrushDoc(Doc);
            Doc := Doc.documentElement;
            WriteInfo(
                'Внимание: Многострочное приложение к выписке дебетовое разделено'
               +' на однострочные. См. параметр "Схема загрузки дебетового приложения"',
                True);
            for i := 0 to Doc.childNodes.Length - 1 do begin
              Doc := Doc.childNodes.Item[i];
              // вставка
              WriteInfo('АЦК: "Приложение к выписке дебетовое" № ' +
                Doc.getAttribute('DOC_NUMBER') + ' Дата: ' +
                Doc.getAttribute('DOC_DATE') + ' Сумма: ' +
                Doc.getAttribute('AMOUNT'), True);

              // exchange #2450
              // блокируем изменение номера ЭД "приложение к выписке дебитовое"
              Doc.SetAttribute( 'num_gen_type', 'ignore');
              DocLoad.LoadXml(ExecXML(Doc.xml, xDoc_F_BUDGET_ID));

              //обработка
              DoProcessDocument_ED5_( Doc, DocLoad);
              (*
              DocLoad.LoadXml(
                  ExecProc( 'DOCUMENT',
                            [ 'action', IfThen( StrToBool(
                                                  Doc.getAttribute('DECLINE')),
                                                  'mark_decline',
                                                  'mark_finish'),
                              'class', '5',
                              'ID', DocLoad.documentElement.getAttribute ('ID')],
                              xDoc_F_BUDGET_ID));

              WriteInfo('Неслинкован/Статус ' +
                IfThen(StrToBool(Doc.getAttribute('DECLINE')), '"Отказан банком"', '"Выполнен"'));
{                if (not VarIsNull(Doc.getAttribute('F_CREATE11')))
                  and (StrToBool(Doc.getAttribute('F_CREATE11'))) then
                begin }
                if AttrToBoolean( Doc, 'F_CREATE11') then begin
                  ChildDoc := CreateOleObject('Microsoft.XmlDom');
                  if CreateChildDoc11(Doc, ChildDoc) then begin
                    Exec_ChildDoc(
                          ChildDoc.documentElement.getAttribute('BUDGET_ID'),
                          DocLoad.documentElement.getAttribute('DOCUMENT_ID'),
                          ChildDoc.documentElement);
                    ChildDoc.LoadXml('');
                  end;
                end;
                *)
              Doc := Doc.parentNode;
            end;//for//
          end else begin
              // вставка

            DocLoad.LoadXml(ExecXML(Doc.xml, Doc.getAttribute('F_BUDGET_ID')));
            //обработка
            DoProcessDocument_ED5_( Doc, DocLoad);
              (*
              DocLoad.LoadXml(
                    ExecProc(
                        'DOCUMENT',
                        [ 'action', IfThen( StrToBool(Doc.getAttribute('DECLINE')),
                                            'mark_decline',
                                            'mark_finish'),
                          'class', '5',
                          'ID', DocLoad.documentElement.getAttribute ('ID')],
                        Doc.getAttribute('F_BUDGET_ID')));

              WriteInfo( 'Неслинкован/Статус ' +
                          IfThen( StrToBool(Doc.getAttribute('DECLINE')),
                                  '"Отказан банком"',
                                  '"Выполнен"'));
{              if (not VarIsNull(Doc.getAttribute('F_CREATE11')))
                and (StrToBool(Doc.getAttribute('F_CREATE11'))) then
              begin}
              if AttrToBoolean( Doc, 'F_CREATE11') then begin
                ChildDoc := CreateOleObject('Microsoft.XmlDom');
                if CreateChildDoc11(Doc, ChildDoc) then begin
                  Exec_ChildDoc(
                          ChildDoc.documentElement.getAttribute('BUDGET_ID'),
                          DocLoad.documentElement.getAttribute('DOCUMENT_ID'),
                          ChildDoc.documentElement);
                  ChildDoc.LoadXml('');
                end;
              end;
              *)
            Doc := Doc.parentNode;
          end;
        EXIT;
      end;


      DocLoad.LoadXml(ExecXml(Doc.xml, xDoc_F_BUDGET_ID));
      DocLoad := DocLoad.documentElement;


      // Обработка
      ExecProc( 'DOCUMENT',
                [ 'action', 'process',
                  'class', '24',
                  'ID', DocLoad.getAttribute('ID')],
                xDoc_F_BUDGET_ID);
      WriteInfo('Загружен', True);

      // если загрузка из 'VJ', 'VI', 'VK', 'VS' - так же создается
      // ЭД 193го класса из 24го

      if (Doc.getAttribute('F_ORIGINAL_TYPE') in ['VJ', 'VI', 'VK', 'VS'])
        then begin
          // приходят только выписки по 'VJ', 'VI', 'VK', 'VS'
          // тогда проверяем флаг F_AUTOPARSING - опция из конфига должна быть
          // "Автоматический разбор"=Да + версия АЦК-Ф не ниже определенной.
          // exchange #2883
          // поправлена ошибка проверки флага "Автоматический разбор"=Да
          // + версии АЦК-Ф. ошибка была введена при доработке #2600
          if (StrToBool(Doc.getAttribute('F_AUTOPARSING'))
                  and (AzkCompareVersion('2.26.317.33') >= 0))
            then Create_193_From_24( xDoc_F_BUDGET_ID,
                                     DocLoad.getAttribute('ID'));
          EXIT;
        end;

      // exchange #2600
      // пп. 2.9.2.4 добавлено создание ЭД 193го класса из 24го из IK.BDPD
      // для этого проверяем вариант с созданием из IK и наличием
      // доп.атрибута.
      if Create_193_From_24_ByIK_BDPD( Doc, DocLoad.getAttribute('ID'))
        then begin

          EXIT;
        end;

      WriteInfo('Формирование документа для линковки');



      //процедура создания доп доков из 24 класса
      CreateChildDocFromCred(Doc, DocLoad);
      except
        ExceptionLog( 'Сбой Un_Import.ProcessDocument_DebCred');
    end;

end;


{~GetDoc5ByLinkedBudgorderDoc
  возвращает список прилинкованных документов (п
  рилжений к выписке дебитовых)
  на статусе 11 или 9, и слинкованных с документом Budgorder (11,75,118,80)
  с идентификатором aDocID.}
function GetDoc5ByLinkedBudgorderDoc( aBudgetId, aDocID: string): variant;
begin

    try
      // exchange #2443
      // исправлена ошибка в списке параметров
      Result := QueryXml(  'Select P.Id From Document D '
                          +'Join Payorder P on P.Document_Id = D.Id '
                          +'join Budgorder BO on BO.Id=? '
                          +'Where D.Budget_Id = ? '
                          +'and D.Parent_Id = BO.DOCUMENT_ID '
                          +'and D.DocumentClass_Id = 5 '
                          +'and ((D.DispStatus_Id = 9) or (D.DispStatus_Id = 11))',
                          [ aDocID, aBudgetId]);

      except
        ExceptionLog( 'Сбой Un_Import.GetDoc5ByLinkedBudgorderDoc');
    end;

end;

{~GetDoc5ByLinkedBudgorderDocCount
  возвращает количество прилинкованных документов (прилжений к выписке дебитовых)
  на статусе 11 или 9, и слинкованных с документом Budgorder (11,75,118,80)
  с идентификатором aDocID.}
function GetDoc5ByLinkedBudgorderDocCount( aBudgetId, aDocID: string): integer;
var
  xXml: variant;
begin

    try
      xXml := GetDoc5ByLinkedBudgorderDoc( aBudgetId, aDocID);
      Result := xXml.documentElement.childNodes.Length;

      except
        ExceptionLog( 'Сбой Un_Import.GetDoc5ByLinkedBudgorderDocCount');
    end;

end;

function SearchDoc5Linked11( aBudgetId, aParent_Document_Id: string): variant;
begin

    try
      // exchange #2443
      // исправлена ошибка в списке параметров
      Result := QueryXml(  'Select P.Id'
                          +' From Document D'
                          +' Join Payorder P on P.Document_Id = D.Id'
                          +' Where D.Budget_Id = ? and D.Parent_Id = ? and D.DocumentClass_Id = 5'
                          +' and ((D.DispStatus_Id = 9) or (D.DispStatus_Id = 11))',
                          [ aBudgetId,
                            aParent_Document_Id]);

      except
        ExceptionLog( 'Сбой Un_Import.SearchDoc5Linked11');
    end;

end;

// процедура для квитовки пп
procedure updateDoc5(BudgetId, Parent_Document_Id, Carry_Date, Foreign_Key: String;
  Remark: String = ''; Decline: Boolean = False);
var
  Xml: Variant;
  Id: String;
begin

    try
      // exchange #2443
      // запрос вынесен в отдельную функцию.
      Xml := SearchDoc5Linked11( BudgetId, Parent_Document_Id);
      if Xml.documentElement.childNodes.Length = 1 then
      begin
        Id := Xml.documentElement.childNodes.Item[0].getAttribute('ID');
        Xml.LoadXml('');
        Xml.appendChild(Xml.createElement('DOCUMENT'));
        Xml.documentElement.setAttribute('action', 'update');
        Xml.documentElement.setAttribute('class', 5);
        Xml.documentElement.setAttribute('ID', Id);
        Xml.documentElement.setAttribute('CARRY_DATE', Carry_Date);
        Xml.documentElement.setAttribute('FOREIGN_KEY', Foreign_Key);
        //отказанные
        if Decline then
          Xml.documentElement.setAttribute('REMARK', Remark);

        ExecXml(Xml.xml, BudgetId);
      end;
      except
        ExceptionLog( 'Сбой Un_Import.updateDoc5');
    end;

end;

{~UpdateDoc5Ex
  выполняет обновление документа "приложение к выписке кредитовок" после
  линковки с ЗОР методом spawn_finish. это когда к ЗОР линкуется
  созданием "приложение к выпискекредитовое" (которое порождается при вызове
  метода spawn_finish. посде этого у созданного приложения нужно поменять
  Foreign_Key и номер документа (exchange #2450) и др.атрибуты.}
procedure updateDoc5Ex( BudgetId: String;
                        Parent_Document_Id: String;
                        Carry_Date: String;
                        Foreign_Key: String;
                        aDocNumber: String);
var
  Xml: Variant;
  Id: String;
begin

    try
      // exchange #2443
      // запрос вынесен в отдельную функцию.
      Xml := SearchDoc5Linked11( BudgetId, Parent_Document_Id);
      if Xml.documentElement.childNodes.Length = 1 then
      begin
        Id := Xml.documentElement.childNodes.Item[0].getAttribute('ID');
        Xml.LoadXml('');
        Xml.appendChild(Xml.createElement('DOCUMENT'));
        Xml.documentElement.setAttribute('action', 'update');
        Xml.documentElement.setAttribute('class', 5);
        Xml.documentElement.setAttribute('ID', Id);
        Xml.documentElement.setAttribute('CARRY_DATE', Carry_Date);
        Xml.documentElement.setAttribute('FOREIGN_KEY', Foreign_Key);
        Xml.documentElement.setAttribute('DOC_NUMBER', aDocNumber);

        ExecXml(Xml.xml, BudgetId);
      end;
      except
        ExceptionLog( 'Сбой Un_Import.updateDoc5Ex');
    end;

end;

//функция разбивает многострочный документ на однострочные
function CrushDoc(Doc: Variant): Variant;
var
  i: Integer;
  s: string;
  xIncludePurposefullgrant: boolean;
  xResultDoc: Variant;
begin

    try
      // exchange 2526
      { определяем тип ЭД
          При загрузке выписки VB с включенным режимом "разбивать многострочный
        документ" параметра "Схема загрузки кредитового приложения";
          Аналогично в IK, SP, IP (и для параметра "Схема загрузки кредитового
        приложения"),
          IV (только для параметра "Схема загрузки дебетового приложения"),
          SB (только для параметра "Схема загрузки дебетового приложения").}
      if (Doc.GetAttribute('F_ORIGINAL_TYPE') in [ 'VB','IK','SP','IP','IV','SB'])
        then xIncludePurposefullgrant := TRUE
        else xIncludePurposefullgrant := FALSE;


      Result := CreateOleObject('Microsoft.XmlDom');
      xResultDoc := Result;
      Result.appendChild(Result.createElement('ROOT'));
      for i := 0 to Doc.childNodes.Item[0].childNodes.Length - 1 do begin

        //клонируем шапку
        Result := Result.documentElement.appendChild(Doc.cloneNode(False));
        //создаем payorderline
        Result := Result.appendChild(Result.ownerDocument.createElement('PAYORDERLINE'));
        //клонируем строку
        Doc := Doc.childNodes.Item[0].childNodes.Item[i];
        Result := Result.appendChild(Result.ownerDocument.documentElement.appendChild(Doc.cloneNode(False)));
        Result.parentNode.parentNode.setAttribute('AMOUNT', Result.getAttribute('AMOUNT'));
        //Формируем ForeignKey для раздробленных доков:
        //к существующему ForeignKey добавляем KBK из файла + сумма строки + тип КБК в MD5
        // exchange 2526
        // Необходимо добавить в правило также "Код цели" строки:
        // ГУИД многострочного ЭД + 20 значное КБК + Код цели + тип КБК + сумма.
        // код цели будем брать исходя из того, что указано без определения
        // типа КБК, т.е. какое из трех полей кодов цели для доходов,
        // или расходов или источников заполнено, оттуда и возьмем код цели.
        if xIncludePurposefullgrant
          then s := Result.getAttribute('F_PRIMARYKBK')
                    + TRIM( VarToStr( Result.getAttribute('PURPOSEFULGRANT_ID')))
                    + TRIM( VarToStr( Result.getAttribute('PURPOSEFULGRANTD_ID')))
                    + TRIM( VarToStr( Result.getAttribute('PURPOSEFULGRANTI_ID')))
                    + Result.getAttribute('AMOUNT')
                    + Result.getAttribute('TYPE_KBK')
          else s := Result.getAttribute('F_PRIMARYKBK')
                    + Result.getAttribute('AMOUNT')
                    + Result.getAttribute('TYPE_KBK');

        Result.parentNode.parentNode.setAttribute(
              'FOREIGN_KEY',
              Result.parentNode.parentNode.getAttribute('FOREIGN_KEY')
                  + Copy(MD5String(s), 1, 14));

        Result.parentNode.parentNode.setAttribute('F_CRUSHED', 'True');
        Doc := Doc.parentNode.parentNode;
        Result := Result.ownerDocument;

      end;//for//

      except
        ExceptionLog( 'Сбой Un_Import.CrushDoc');
    end;

end;


{ ExistsDocument
  проверка существования документа aDoc по атрибутам документа:
  ид.бюджета (F_BUDGET_ID), номер класса (class) и ключа (FOREIGN_KEY).
  результат:
    =true - документ уже существует.}
function ExistsDocument( aDoc: Variant): boolean;
begin
  Result := IsLoaded( aDoc.getAttribute('F_BUDGET_ID'),
                      aDoc.getAttribute('class'),
                      aDoc.getAttribute('FOREIGN_KEY'),
                      aDoc);
end;

//процедура проверки на повторную загрузку и вставку документов произв. классов
//на "отложен"
procedure InsDoc(Doc: Variant);
begin
  if IsLoaded(Doc.getAttribute('F_BUDGET_ID'), Doc.getAttribute('class'),
    Doc.getAttribute('FOREIGN_KEY')) then
    WriteInfo('Повторная загрузка документа - пропущен', True)
  else begin
    ExecXml(Doc.xml, Doc.getAttribute('F_BUDGET_ID'));
    WriteInfo('Создан на статусе "Отложен"');
  end;
end;

//вставляет документы 5 и 24 классов без строк. Доводит их до статуса 9(выполнен)
procedure InsertDebCred(Doc: Variant);
var
  DocLoad: Variant;
  i,n: integer;
  xNode: variant;
begin

    try
      if IsLoaded(Doc.getAttribute('F_BUDGET_ID'), Doc.getAttribute('class'),
        Doc.getAttribute('FOREIGN_KEY'), Doc) then
        WriteInfo('Повторная загрузка документа - пропущен', True)
      else begin
        DocLoad := CreateOleObject('Microsoft.XmlDom');
        Doc.setAttribute('DOC_DATE',
          DateTimeToXml(StrToDate(Doc.getAttribute('DOC_DATE'))));
        if Doc.getAttribute('class') = 5 then
        begin
          if not LinkDoc(Doc) then
          begin
            //вставка

            DocLoad.LoadXml(ExecXML(Doc.xml, Doc.getAttribute('F_BUDGET_ID')));
            //обработка

            DocLoad.LoadXml(ExecProc('DOCUMENT',
              ['action', IfThen(StrToBool(Doc.getAttribute('DECLINE')), 'mark_decline', 'mark_finish'),
              'class', '5', 'ID', DocLoad.documentElement.getAttribute ('ID')],
              Doc.getAttribute('F_BUDGET_ID')));
            WriteInfo('Неслинкован/Статус ' +
              IfThen(StrToBool(Doc.getAttribute('DECLINE')), '"Отказан банком"', '"Выполнен"'));
           end;
        end else begin
          //загрузка 24 класса

          DocLoad.LoadXml(ExecXml(Doc.xml, Doc.getAttribute('F_BUDGET_ID')));
          DocLoad := DocLoad.documentElement;
          // Обработка

          ExecProc( 'DOCUMENT',
                    [ 'action', 'process',
                      'class', '24',
                      'ID', DocLoad.getAttribute('ID')],
                    Doc.getAttribute('F_BUDGET_ID'));
          WriteInfo('Загружен', True);

          // если загрузка из 'VJ', 'VI', 'VK', 'VS' - ЭД 193го класса из 24го
          // не создается. ранее такого функционала небыло.
          // 193й не создается, поскольку непонятно как заполнять строки
          // на основании безстрокового 24го.
          // exchange #2883
          // вместо создания 193го эд в журнал пишем почему такой эд не создаем
          if ( VarToStr( Doc.getAttribute('F_ORIGINAL_TYPE'))
                                                  in ['VJ', 'VI', 'VK', 'VS'])
            then begin
              // exchange #3124
              // исправлена ошибка, допущенная по доработке exchange #2883:
              // если авторазбор выключен - эд 193й не создаем
              if NOT AttrToBoolean( Doc, 'F_AUTOPARSING') then EXIT;
              if (AzkCompareVersion('2.26.317.33') < 0) then EXIT;
              // exchange #3124
              // проверяем, есть ли строки в эд 24м. для однострочных эд
              // эд 193й не создаем.
              n := 0;
              for i := 0 to Doc.childNodes.Length - 1 do begin
                xNode := Doc.childNodes.Item[i];
                if (xNode.NodeName = 'PAYORDERLINE') then begin
                  n := xNode.childNodes.Length;
                  BREAK;
                end;
              end;//for//
              if (n <= 0) then begin
                WriteInfo(
                        FORMAT(  'Распоряжение на зачисление средств на л/с не'
                                +' создано из Приложения к выписке кредитовго'
                                +' № %s Дата: %s Сумма: %s, не указан КБК.',
                                 [ VarToStr( Doc.GetAttribute( 'DOC_NUMBER')),
                                   VarToStr( Doc.GetAttribute( 'DOC_DATE')),
                                   VarToStr( Doc.GetAttribute( 'AMOUNT'))]));
              end else begin
                Create_193_From_24( Doc.getAttribute('F_BUDGET_ID'),
                                    DocLoad.getAttribute('ID'),
                                    TRUE);
              end;
              EXIT;
            end;

          // exchange #2600
          // пп. 2.9.2.4 добавлено создание ЭД 193го класса из 24го из IK.BDPD
          // для этого проверяем вариант с созданием из IK и наличием
          // доп.атрибута.
          // exchange #2831
          // также требуется создавать ЭД из 24го
          Create_193_From_24_ByIK_BDPD( Doc, DocLoad.getAttribute('ID'));
        end;
      end;
      except
        ExceptionLog( 'Сбой Un_Import.InsertDebCred');
    end;

end;

{~CreateChildDocFromCred
//устанавливаем класс создаваемого дочернего документа в аттрибут строки F_CHILD_CLASS
//Если F_CHILD_CLASS = '0' в шапке, то доп. документ не создаем.}
procedure CreateChildDocFromCred(Doc, DocLoad: Variant);
var
  ChildDoc, NewDoc: Variant;
  i, j: Integer;
  xLines79: variant;    // exchange #2405
  i2: integer;
  xNewDocXml: Variant;
  xNewDocItemXml: Variant;
  xNewDocItemLinesXml: Variant;
  xNewDocItemLineXml: Variant;

begin

    try
    //устанавливаем класс создаваемого дочернего документа в аттрибут строки F_CHILD_CLASS
    //или F_CHILD_CLASS = '0' в шапку, если не создаем доп. документ

      setClassChildDoc(Doc);

      if Doc.getAttribute('F_CHILD_CLASS') = '0' then EXIT;
      NewDoc := CreateOleObject('Microsoft.XmlDom');
      // переформируем xml в зависимости от класса дочерних документов
      Rearrange(Doc, NewDoc);
      ChildDoc := CreateOleObject('Microsoft.XmlDom');
      for i := 0 to NewDoc.documentElement.childNodes.Length - 1 do begin

        xNewDocXml     := NewDoc.documentElement.childNodes.item[i];
        xNewDocItemXml := xNewDocXml.childNodes.item[0];


        // Exchange #2062
try
        if (Doc.getAttribute('F_ORIGINAL_TYPE') = 'VB')
            and (Doc.getAttribute('F_SPECSR') <> '')
            and (xNewDocItemXml.getAttribute('F_CHILD_CLASS') <> '74')
          then xNewDocItemXml.setAttribute('F_SS', False);
except
ExceptionLog( 'Сбой Exchange #2062');
end;

        case xNewDocItemXml.getAttribute('F_CHILD_CLASS') of
          '7': begin
              xNewDocItemLinesXml := xNewDocItemXml.childNodes.Item[0];
//              NewDoc := NewDoc.documentElement.childNodes.item[i].childNodes.item[0];

              // exchange #2687
              // формируем столько однострочных ЭД 7го класса, сколько строк
              // в ЭД 24го класса, по которому создаются ЭД 7х классов.
              for i2 := 0 to xNewDocItemLinesXml.childNodes.length - 1 do
                try
                  xNewDocItemLineXml := xNewDocItemLinesXml.childNodes.Item[ i2];

                  WriteInfo( FORMAT( 'АЦК: "Внутренний кредитовый документ"'
                                    +' № %s Дата: %s Сумма: %s',
                                     [ xNewDocItemXml.getAttribute('DOC_NUMBER'),
                                       DateToStr(XmlToDateTime(xNewDocItemXml.getAttribute('DOC_DATE'))),
                                       // сумма из строки ЭД 24го класса
                                       xNewDocItemLineXml.getAttribute('AMOUNT')]),
                             True);

                  if CreateChildDoc7( xNewDocItemXml, ChildDoc, i2)
                    then Exec_ChildDoc( ChildDoc.documentElement.getAttribute('BUDGET_ID'),
                                         DocLoad.getAttribute('DOCUMENT_ID'),
                                         ChildDoc.documentElement)
                    else WriteInfo('Не создан');

                  ChildDoc.LoadXml('');
                  except
                    ExceptionLog( 'Сбой формирования ЭД 7го класса по строке ЭД 24го класса');
                end;//for//
//              NewDoc := NewDoc.ownerDocument;
            end;

          '19': begin
              NewDoc := NewDoc.documentElement.childNodes.item[i].childNodes.item[0];
              WriteInfo('АЦК: "Распоряжение на зачисление в доходы" № ' +
                NewDoc.getAttribute('DOC_NUMBER') + ' Дата: ' +
                  DateToStr(XmlToDateTime(NewDoc.getAttribute('DOC_DATE'))) +
                ' Сумма: ' + NewDoc.getAttribute('AMOUNT'), True);
              if CreateChildDoc19(NewDoc, ChildDoc) then begin
                for j := 0 to ChildDoc.documentElement.childNodes.length -1 do
                begin
                  ChildDoc := ChildDoc.documentElement.childNodes.item[j].childNodes.item[0];
                  Exec_ChildDoc(ChildDoc.getAttribute('BUDGET_ID'),
                    DocLoad.getAttribute('DOCUMENT_ID'), ChildDoc);
                  ChildDoc := ChildDoc.ownerDocument;
                end;
                NewDoc := NewDoc.ownerDocument;
                ChildDoc.LoadXml('');
              end
              else begin
                WriteInfo('Не создан');
                NewDoc := NewDoc.ownerDocument;
                ChildDoc.LoadXml('');
              end;
            end;

          '25': begin
              NewDoc := NewDoc.documentElement.childNodes.item[i].childNodes.item[0];
              WriteInfo('АЦК: "Уведомление о возврате средств в бюджет" № ' +
                NewDoc.getAttribute('DOC_NUMBER') + ' Дата: ' +
                  DateToStr(XmlToDateTime(NewDoc.getAttribute('DOC_DATE'))) +
                  ' Сумма: ' + NewDoc.getAttribute('AMOUNT'), True);
              if CreateChildDoc25(NewDoc, ChildDoc) then begin
                Exec_ChildDoc(ChildDoc.documentElement.getAttribute('BUDGET_ID'),
                  DocLoad.getAttribute('DOCUMENT_ID'), ChildDoc.documentElement);
                NewDoc := NewDoc.ownerDocument;
                ChildDoc.LoadXml('');
              end
              else begin
                WriteInfo('Не создан');
                NewDoc := NewDoc.ownerDocument;
                ChildDoc.LoadXml('');
              end;
            end;

          '74': begin
              NewDoc := NewDoc.documentElement.childNodes.item[i].childNodes.item[0];
              WriteInfo('АЦК: "Распоряжение на зачисление специальных средств" № ' +
                NewDoc.getAttribute('DOC_NUMBER') + ' Дата: ' +
                  DateToStr(XmlToDateTime(NewDoc.getAttribute('DOC_DATE'))) +
                  ' Сумма: ' + NewDoc.getAttribute('AMOUNT'), True);
              if CreateChildDoc74(NewDoc, ChildDoc) then begin
                Exec_ChildDoc(ChildDoc.documentElement.getAttribute('BUDGET_ID'),
                  DocLoad.getAttribute('DOCUMENT_ID'), ChildDoc.documentElement);
                NewDoc := NewDoc.ownerDocument;
                ChildDoc.LoadXml('');
              end
              else begin
                WriteInfo('Не создан');
                NewDoc := NewDoc.ownerDocument;
                ChildDoc.LoadXml('');
              end;
            end;

          '79': begin
              if (not VarIsNull(NewDoc.documentElement.childNodes.item[i].
                childNodes.item[0].getAttribute('F_SS'))) and
                (StrToBool(NewDoc.documentElement.childNodes.item[i].
                  childNodes.item[0].getAttribute('F_SS'))) then
              begin
                WriteInfo('Распоряжение на зачисление средств по источникам по' +
                  ' внебюджету не создается.', True);
                Exit;
              end;
              NewDoc := NewDoc.documentElement.childNodes.item[i].childNodes.item[0];
              try
                // exchange #2405
                xLines79 := NULL;       // инициализация переменной
                if NOT Exch2405_LinkDoc203( NewDoc,
                                            DocLoad.getAttribute('DOCUMENT_ID'),
                                            xLines79)
                  then begin
                    WriteInfo('АЦК: "Распоряжение на зачисление средств по источникам" № ' +
                      NewDoc.getAttribute('DOC_NUMBER') + ' Дата: ' +
                        DateToStr(XmlToDateTime(NewDoc.getAttribute('DOC_DATE'))) +
                        ' Сумма: ' + NewDoc.getAttribute('AMOUNT'), True);
                    // изменено для exchange #2405
                    if NOT CreateChildDoc79(NewDoc, ChildDoc, xLines79)
                      then WriteInfo('Не создан')
                      else begin
                        for j := 0 to ChildDoc.documentElement.childNodes.length -1
                          do begin
                            ChildDoc := ChildDoc.documentElement.childNodes.item[j].childNodes.item[0];
                            Exec_ChildDoc(ChildDoc.getAttribute('BUDGET_ID'),
                              DocLoad.getAttribute('DOCUMENT_ID'), ChildDoc);
                            ChildDoc := ChildDoc.ownerDocument;
                          end;
                      end;
                  end;
                finally
                  // exchange #2405 - сбрасываем переменные
                  xLines79 := NULL;
                  NewDoc := NewDoc.ownerDocument;
                  ChildDoc.LoadXml('');
              end;
            end;
        end;//case//
      end;//for//
      except
        ExceptionLog( 'Сбой Un_Import.CreateChildDocFromCred');
    end;


end;

{~setClassChildDoc
устанавливаем классы создаваемых дочерних документов в аттрибут строки F_CHILD_CLASS}
procedure setClassChildDoc(Doc: Variant);
var
  i: Integer;
  Anal_Kind, Kif, OperType, Kdt_Code, OperType_Id: String; // хранит тип классификации 1-ой строки 24 класса
  List, List2, List3, List4, List5, List6, List7: TStringList;
  List8: TStringList;
  Org, Permission: Variant;
  xFlag2522: boolean;      // exchange #2522
  xF_ORIGINAL_TYPE: string;

begin

    try

      Doc.setAttribute('F_CHILD_CLASS', '');
      Doc.setAttribute('F_OPERTYPE_ID', '0');
      //нет строк у 24 класса
      if Doc.childNodes.Length = 0 then Exit;
      // exchange #2714
      // сохраняем параметр - из какого файла выполнено создание ЭД.
      // это делаем для того, что при изменении переменной Doc (переход
      // на дочерний узел), не искать корневой узел ЭД, а использовать
      // локальную переменную.
      xF_ORIGINAL_TYPE := Doc.getAttribute('F_ORIGINAL_TYPE');
      //для 24 класса из 'VJ', 'VI', 'VK', 'VS' стандартные доп.документы не создаются
      // exchange 2510
      // для 24го класса из VC 5.	Доп.документы из Приложения к выписке
      // кредитового не создавать, парный документ для квитовки с Приложением
      // к выписке дебетовым не искать
      if (xF_ORIGINAL_TYPE in ['VJ', 'VI', 'VK', 'VS', 'VC'])
        then Exit;
      //настройка игнорирования создания доп документов, если ИНН плательщика
      //совпадает с данными, указанами в настройке Ignore_PayINN.set

      List := LoadSettings(DirIni + 'Settings\Ignore_PayINN.set');
      try
        if FindSettingsType1(Doc.getAttribute('PAY_TAXCODE'), List) then
        begin
          WriteInfo('Не создан, т.к. ИНН плательщика указан в настройке Ignore_PayINN.set');
          Doc.setAttribute('F_CHILD_CLASS', '0');
          Exit;
        end;
      finally
        List.Free;
      end;
      //проставление соответсвия типа операции по ИНН

      List := LoadSettings(DirIni + 'Settings\OperType_PayINN.set');
      try
        if (not VarIsNull(Doc.getAttribute('PAY_TAXCODE'))) then
        begin
          OperType := FindSettingsType2(Doc.getAttribute('PAY_TAXCODE'), List);
          Doc.setAttribute('F_OPERTYPE_ID', IfThen(OperType <> '', OperType, '0'));
        end;
      finally
        List.Free;
      end;
      Doc := Doc.childNodes.Item[0];
      //настройка игнорирования создания доп документов, если КБК в строках
      //совпадает c КБК в настройке Ignore_KBK.set

      List := LoadSettings(DirIni + 'Settings\Ignore_KBK.set');
      //настройка проставляет значение киф, если КБК совпало с заданными

      List2 := LoadSettings(DirIni + 'Settings\KIF_KBK.set');
      //настройка проставляет значение кода типа дохода для 19 класса,
      //если КБК совпало с заданными

      List3 := LoadSettings(DirIni + 'Settings\KDType_KBK.set');
      //проверка на постановку на некласифицированные

      List4 := LoadSettings(DirIni + 'Settings\UknownIncome_KBK.set');
      //проверяем создавать ли 25 класс по особому правилу (Exchange #1621)

      List5 := LoadSettings(DirIni + 'Settings\RealMoneyAccounts.set');
      //Проставление соответсвия между КБК и типом операции для 19 класса

      List6 := LoadSettings(DirIni + 'Settings\OperType_KBK.set');
      //Проверяем создавать ли 19 класс по доходной классификации при загрузке VB

      List7 := LoadSettings(DirIni + 'Settings\Ignore_Account.set');
      // exchange #2714
      //проверка на постановку на некласифицированные при загрузке VT

      List8 := LoadSettings(DirIni + 'Settings\UknownIncome_KBK_VT.set');
      try
        // exchange #2522
        // ловим сообщение 'Не создан, т.к. счет плательщика указан в настройке
        // Ignore_Account.set' для отображения его только один раз.
        // при загрузке VB проверка счета выполняется только для шапки ЭД.
        xFlag2522 := FALSE;
        for i := 0 to Doc.childNodes.Length - 1 do
        begin
          //ушли в строки
          Doc := Doc.childNodes.Item[i];

          //заменили КБК (доп документ не создаем)
          if StrToBool(Doc.getAttribute('F_CHANGEDKBK')) then
          begin
            WriteInfo('Не создан, т.к. есть строки в документе заменеными КБК на 0');
            Doc.parentNode.parentNode.setAttribute('F_CHILD_CLASS', '0');

            Exit;
          end;

          if (Doc.getAttribute('ANAL_KIND') = '0') then // возврат - 25 класс
          begin
            Doc.setAttribute('F_CHILD_CLASS', 25);
            Doc.setAttribute('FSR_ID', KifExists(FindSettingsType2(
              Doc.getAttribute('F_PRIMARYKBK'), List2), Doc.getAttribute('FSR_ID')));
          end
          else if (Doc.getAttribute('ANAL_KIND') = '1') then // доход - 19 класс
          if (Doc.parentNode.parentNode.getAttribute('F_ORIGINAL_TYPE') = 'VB') and
            (FindSettingsType1(Doc.parentNode.parentNode.getAttribute('PAY_ACCOUNT'), List7)) then
          begin
            // exchange #2522
            // сообщение отображаем один раз, но для всех строк выставляем
            // атрибут F_CHILD_CLASS как и раньше.
            if NOT xFlag2522 then begin
              xFlag2522 := TRUE;
              WriteInfo('Не создан, т.к. счет плательщика указан в настройке Ignore_Account.set');
            end;
            Doc.setAttribute('F_CHILD_CLASS', '');
          end
          else begin
            Doc.setAttribute('F_CHILD_CLASS', 19);
            Doc.setAttribute('FSD_ID', KifExists(FindSettingsType2(
              Doc.getAttribute('F_PRIMARYKBK'), List2), Doc.getAttribute('FSD_ID')));
            Kdt_Code := FindSettingsType2(Doc.getAttribute('F_PRIMARYKBK'), List3);
            Doc.setAttribute('KDT_CODE', IfThen((Kdt_Code <> ''), Kdt_Code, '0'));
            OperType_Id := FindSettingsType2(Doc.getAttribute('F_PRIMARYKBK'), List6);
            Doc.setAttribute('OPERTYPE_ID', OperType_Id);
          end
          else begin// источники - 79 класс
            Doc.setAttribute('F_CHILD_CLASS', 79);
            Doc.setAttribute('FSI_ID', KifExists(FindSettingsType2(
              Doc.getAttribute('F_PRIMARYKBK'), List2), Doc.getAttribute('FSI_ID')));
            OperType_Id := FindSettingsType2(Doc.getAttribute('F_PRIMARYKBK'), List6);
            Doc.setAttribute('OPERTYPE_ID', OperType_Id);
          end;

          //для внебюджета подменяем 19 класс на 74
          if (not VarIsNull(Doc.parentNode.parentNode.getAttribute('F_SS')))
            and (StrToBool(Doc.parentNode.parentNode.getAttribute('F_SS')))
              and (Doc.getAttribute('F_CHILD_CLASS') = '19') then begin
            Doc.setAttribute('F_CHILD_CLASS', 74);
            if (not VarIsNull(Doc.parentNode.parentNode.getAttribute('F_SPECSR'))) and
              (Doc.parentNode.parentNode.getAttribute('F_SPECSR') = '') then
              Doc.setAttribute('OPERTYPE_ID', '');
          end;

          //Правило Иркутска для создания 74 или 19 класса
          if (Doc.getAttribute('F_CHILD_CLASS') = '74') and
            (not VarIsNull(Doc.parentNode.parentNode.getAttribute('F_SPECSR'))) and
            (Doc.parentNode.parentNode.getAttribute('F_SPECSR') = 'по правилу Иркутск') then
          begin
            //закладываемся под то что с лета могут прийти буквы в КБК.
            try //except случится только при попытке сконвертить строку в число(StrToInt)
              if ((Copy(Doc.getAttribute('F_PRIMARYKBK'), 4, 10) = '1130302002') or
                (Copy(Doc.getAttribute('F_PRIMARYKBK'), 4, 10) = '2070200002')) and
                (not(StrToInt(Copy(Doc.getAttribute('F_PRIMARYKBK'), 14, 4)) in [0..14]))
              then begin
                //Exchange2084
                Permission := GetPermissionIrk(Doc);
                if not VarIsNull(Permission) then
                  Doc.setAttribute('F_CHILD_CLASS', 74)
                else
                  Doc.setAttribute('F_CHILD_CLASS', 19);
              end else
                Doc.setAttribute('F_CHILD_CLASS', 19);
            except
              Doc.setAttribute('F_CHILD_CLASS', 19);
            end;
          end;

          //Правило ЛенОбласти для создания 74 или 19 класса
          //проверяем на условие для создания 74 класса, если подходит, создаем его,
          //не подходит, тогда 19 классс.
          if (Doc.getAttribute('F_CHILD_CLASS') = '74') and
            (not VarIsNull(Doc.parentNode.parentNode.getAttribute('F_SPECSR')))
            and (Doc.parentNode.parentNode.getAttribute('F_SPECSR') = 'по правилу ЛенОбласти') then
          begin
            //проверка четвертого разряда КБК, если =1 создаем 74, не равен - 19 класс
            if (Copy(Doc.getAttribute('F_PRIMARYKBK'), 4, 1) = '1')
              and (Copy(Doc.getAttribute('F_PRIMARYKBK'), 15, 3) <> '000') then
            begin
              Org := GetOrgByCode(Doc.parentNode.parentNode.getAttribute('F_BUDGET_ID'),
                (Copy(Doc.getAttribute('F_PRIMARYKBK'), 15, 3)));
              if Org.documentElement.childNodes.length = 1 then
              begin
              //нашли организацию
                Doc.setAttribute('ORG_ID', Org.documentElement.childNodes.item[0].getAttribute('ID'));
                Doc.setAttribute('KD_CODE', Copy(Doc.getAttribute('F_PRIMARYKBK'), 4, 11) + '000');
              end
              //не нашли органинизацию
              else begin
                WriteInfo('Не создан - не определен Id получателя');
                Doc.setAttribute('F_CHILD_CLASS', '');
              end;
            end
            else
              Doc.setAttribute('F_CHILD_CLASS', 19);
          end;

          //Правило Читы для создания 74 или 19 класса
          //проверяем на условие для создания 74 класса, если подходит, создаем его,
          //не подходит, тогда 19 классс.
          if (Doc.getAttribute('F_CHILD_CLASS') = '74') and
            (not VarIsNull(Doc.parentNode.parentNode.getAttribute('F_SPECSR')))
            and (Doc.parentNode.parentNode.getAttribute('F_SPECSR') = 'по правилу Чита') then
          begin
            //проверка четвертого разряда КБК, если =1 создаем 74, не равен - 19 класс
            if (Copy(Doc.getAttribute('F_PRIMARYKBK'), 4, 1) = '1')
              and (Copy(Doc.getAttribute('F_PRIMARYKBK'), 14, 3) <> '000') then
            begin
              Org := GetOrgByCode(Doc.parentNode.parentNode.getAttribute('F_BUDGET_ID'),
                (Copy(Doc.getAttribute('F_PRIMARYKBK'), 14, 3)), True);
              if (Org.documentElement.childNodes.length = 1) and
                IsActual(Org.documentElement.childNodes.item[0].getAttribute('ID'),
                  Doc.parentNode.parentNode.getAttribute('F_BUDGET_ID')) then
              //нашли организацию
                  Doc.setAttribute('ORG_ID', Org.documentElement.childNodes.item[0].getAttribute('ID'))
              //не нашли органинизацию
              else begin
                WriteInfo('Не создан - не определен Id получателя');
                Doc.setAttribute('F_CHILD_CLASS', '');
              end;
            end
            else
              Doc.setAttribute('F_CHILD_CLASS', 19);
          end;

          //проверяем F_PRIMARYKBK, т.к. если меняли КБК при загрузке, то выйдем из
          //процедуры при проверке if StrToBool(Doc.getAttribute('F_CHANGEDKBK')) then
          if FindSettingsType1(Doc.getAttribute('F_PRIMARYKBK'), List) then
          begin
            WriteInfo('Не создан, т.к. КБК указан в настройке Ignore_KBK.set');
            Doc.setAttribute('F_CHILD_CLASS', '');
          end;

          // exchange #2714
          // при загрузке VT вместо проверки по файлу UknownIncome_KBK.set,
          // проверяем по файлу UknownIncome_KBK_VT.set
          if Doc.getAttribute('F_CHILD_CLASS') in ['19', '74', '79'] then
            if (xF_ORIGINAL_TYPE = 'VT') then begin
              if FindSettingsType1(Doc.getAttribute('F_PRIMARYKBK'), List8)
                then Doc.setAttribute('F_CHILD_CLASS', 7);
            end else begin
              if FindSettingsType1(Doc.getAttribute('F_PRIMARYKBK'), List4)
                then Doc.setAttribute('F_CHILD_CLASS', 7);
            end;

          if (Doc.getAttribute('F_CHILD_CLASS') = '25') and
            (not VarIsNull(Doc.parentNode.parentNode.getAttribute('F_SS')))
              and (StrToBool(Doc.parentNode.parentNode.getAttribute('F_SS')))
                and (Doc.parentNode.parentNode.getAttribute('PAY_ACCOUNT') <> '') then
          begin
            if FindSettingsType1(Doc.parentNode.parentNode.getAttribute('PAY_ACCOUNT'), List5) then
              Doc.parentNode.parentNode.setAttribute('RULE_1621', 'True')
            else
              Doc.parentNode.parentNode.setAttribute('RULE_1621', 'False');
          end;

            Doc := Doc.parentNode;
        end; //end for
        Doc := Doc.parentNode;
      finally
        List.Free;
        List2.Free;
        List3.Free;
        List4.Free;
        List5.Free;
        List6.Free;
        List7.Free;
        List8.Free;    // exchange #2714
      end;

      except
        ExceptionLog( 'Сбой Un_Import.setClassChildDoc');
    end;

end;

function CreateChildDoc7(Doc, ChildDoc: Variant; aLineIndex: integer): Boolean;

  function GetUnknownAttr(BudgetId: String; Line, Spec, aSpecLineXml: Variant): Boolean;
  var
    sql: string;
    Xml: Variant;
    xStrSearch: string;
  begin
  
      try
        Result := False;

        // exchange #3062 - оптимизация кода + параметризация запроса
        // искомое слово в бд хранится без кавычек!
        if AttrToBoolean( Doc, 'F_SS')
          then xStrSearch := 'НЕВЫЯСНЕННЫЕПОСТУПЛЕНИЯВНЕБЮДЖЕТ'
          else xStrSearch := 'НЕВЫЯСНЕННЫЕПОСТУПЛЕНИЯ';
        Xml := QueryXml( ' Select * from carrykbk'
                        +' where budget_id = ? and Upper(Name) = ?',
                          [ BudgetId,
                            xStrSearch]);
        {
        if (not VarIsNull(Doc.getAttribute('F_SS'))) and (StrToBool(Doc.getAttribute('F_SS'))) then
          sql := 'Select * from carrykbk ' +
            ' where budget_id = ? and Upper(Name) = ''НЕВЫЯСНЕННЫЕПОСТУПЛЕНИЯВНЕБЮДЖЕТ'''
        else
          sql := 'Select * from carrykbk ' +
            ' where budget_id = ? and Upper(Name) = ''НЕВЫЯСНЕННЫЕПОСТУПЛЕНИЯ''';
        Xml := QueryXml(sql, [BudgetId]);
        }
        // Exchange#2079
        if (AzkCompareVersion('2.24.10.35') >= 0) and IsSysparamOn('asset.unclassified_from_payorder') and
          (aSpecLineXml.getAttribute('ANAL_KIND') = '1') and
          (Xml.documentElement.childNodes.Length <> 0) and
          (aSpecLineXml.getAttribute('KADMD_CODE') <>
           KadmCodeFormat(Xml.documentElement.childNodes.Item[0].getAttribute('KADMD_CODE'), BudgetId)) then
        begin
          // новый механизм
          Spec := aSpecLineXml;

          // проверку на непустоту аттрибута не делаем, т.к если есть аттрибут, то он заполнен
          // Exchange#2079
          if not VarIsNull(Spec.getAttribute('RECEIVER_ID')) then
            Line.setAttribute('RECEIVER_ID', Spec.getAttribute('RECEIVER_ID'));
          if not VarIsNull(Spec.getAttribute('PAYER_ID')) then
            Line.setAttribute('PAYER_ID', Spec.getAttribute('PAYER_ID'));
          Line.setAttribute('KADMD_CODE', Spec.getAttribute('KADMD_CODE'));
          Line.setAttribute('KD_CODE', Spec.getAttribute('KD_CODE'));
          // exchange #3062 - отмена косгу
          //Line.setAttribute('KESD_CODE', Spec.getAttribute('KESD_CODE'));
          Line.setAttribute('KDT_CODE', Spec.getAttribute('KDT_CODE'));
          Line.setAttribute('FSD_ID', Spec.getAttribute('FSD_ID'));
          Line.setAttribute('KDD_CODE', Spec.getAttribute('KDD_CODE'));
          // exchange #2389 - доходы
          // поле колда цели тянем из главного ЭД
          Line.setAttribute( 'PURPOSEFULGRANTD_ID',
                              Spec.getAttribute('PURPOSEFULGRANTD_ID'));

          //Территорию пока не проставляем
          //Line.setAttribute('TERRITORY_ID', Spec.getAttribute('TERRITORY_ID'));
        end
        else begin
          // старый механизм

          if Xml.documentElement.childNodes.Length = 0 then
          begin
            WriteInfo(' Не создан - бюджетная классификация для настройки проводок' +
              ' с именем' + IfThen(((not VarIsNull(Doc.getAttribute('F_SS')))
                and (StrToBool(Doc.getAttribute('F_SS')))), ' "НевыясненныеПоступленияВнебюджет"',
              ' "НевыясненныеПоступления"') + ' не найдена');
            Exit;
          end
          else begin
            Xml := Xml.documentElement.childNodes.Item[0];

            Line.setAttribute('RECEIVER_ID', Xml.getAttribute('RECEIVER_ID'));
            Line.setAttribute('PAYER_ID', Xml.getAttribute('PAYER_ID'));
            Line.setAttribute('KADMD_CODE', Xml.getAttribute('KADMD_CODE'));
            Line.setAttribute('KD_CODE', Xml.getAttribute('KD_CODE'));
            Line.setAttribute('KESD_CODE', Xml.getAttribute('KESD_CODE'));
            Line.setAttribute('KDT_CODE', Xml.getAttribute('KDT_CODE'));
            Line.setAttribute('FSD_ID', Xml.getAttribute('FSD_ID'));
            Line.setAttribute('KDD_CODE', Xml.getAttribute('KDD_CODE'));
            Line.setAttribute('TERRITORY_ID', Xml.getAttribute('TERRITORY_ID'));
            // exchange #2389 - доходы
            // поле колда цели тянем из главного ЭД
            Line.setAttribute( 'PURPOSEFULGRANTD_ID',
                                Xml.getAttribute('PURPOSEFULGRANTD_ID'));
          end;
        end;

        Exch2389_Update_PURPOSEFULGRANT_ID(
               // Line,   // доп.ЭД
                Line,   // строка
                '20',
                Line.parentNode.parentNode.GetAttribute('BUDGET_ID'),
                'PURPOSEFULGRANTD_ID',
                Line.parentNode.parentNode.GetAttribute('class'),
                VarToStr( Line.GetAttribute('KDT_CODE')));
        Result := True;
        except
          ExceptionLog( 'Сбой Un_Import.CreateChildDoc7.GetUnknownAttr');
      end;
  
  end;
var
  i: Integer;
  List: TStringList;
  xDocLineXml: Variant;
begin

    try
      Result := False;
      List := LoadSettings(DirIni + 'Settings\UknownIncome_NotPayINN.set');
      try
        if FindSettingsType1(Doc.getAttribute('PAY_TAXCODE'), List) then
        begin
          WriteInfo('Не создан, т.к. ИНН плательщика указан в настройке ' +
            'UknownIncome_NotPayINN.set');
          Exit;
        end;
      finally
        List.Free;
      end;

      xDocLineXml := Doc.childNodes.Item[0].childNodes.Item[ aLineIndex];


      ChildDoc := ChildDoc.appendChild(Doc.cloneNode(false));
      ChildDoc.setAttribute('action', 'insert');
      ChildDoc.setAttribute('class', 7);
      ChildDoc.setAttribute('BUDGET_ID', Doc.getAttribute('F_BUDGET_ID'));
      ChildDoc.setAttribute('OPERTYPE_ID', '-1');
      ChildDoc.setAttribute('ASSETKIND_ID', 0); //Тип актива
      //Вид классификации из первой строки
      ChildDoc.setAttribute('ANAL_KIND', xDocLineXml.getAttribute('ANAL_KIND'));

      // сумма шапки
      // exchange #2687 - сумма из первой строки
      ChildDoc.setAttribute( 'AMOUNT', xDocLineXml.getAttribute('AMOUNT'));
//      ChildDoc.setAttribute('AMOUNT', Doc.getAttribute('AMOUNT'));

      ChildDoc.setAttribute('DOC_DATE', Doc.getAttribute('CARRY_DATE'));
      ChildDoc := ChildDoc.appendChild(ChildDoc.ownerDocument.createElement('ASSETACTLINE'));
      ChildDoc := ChildDoc.appendChild(ChildDoc.ownerDocument.createElement('ASSETACTLINE'));

      //сумма строки всегда совпадет с суммой шапки, т.к. 7 класс создаем однострочный
      // сумма из первой строки
      ChildDoc.setAttribute('AMOUNT', xDocLineXml.getAttribute('AMOUNT'));
//      ChildDoc.setAttribute('AMOUNT', Doc.getAttribute('AMOUNT'));

      Result := GetUnknownAttr( Doc.getAttribute('F_BUDGET_ID'),
                                ChildDoc,
                                Doc,
                                xDocLineXml);
      except
        ExceptionLog( 'Сбой Un_Import.CreateChildDoc7');
    end;

end;

//создает документ 19 класса на основе загруженного 24
function CreateChildDoc19(Doc: Variant; var ChildDoc: Variant): Boolean;
var
  List, List2: TStringList;
  i: Integer;
  Kdd_Code: String;
  New: Variant;
  xKDD_ZERO: string;
begin

    try
      // exchange 3013
      // получаем нулевой доп.код с учетом маски.
      // определяем его один раз ко всем строкам, чтобы его не искать
      // в каждой строке.
      xKDD_ZERO := FormatKbk( 'KDD', '0', Doc.getAttribute('F_BUDGET_ID'));


      Result := False;
      New := CreateOleObject('Microsoft.XmlDom');
      //Проставление соответсвия между КБК и Доп кодом дохода
      List := LoadSettings(DirIni + 'Settings\KDDCode_KBK.set');
      try
        ChildDoc := ChildDoc.appendChild(ChildDoc.createElement('DOCUMENT'));
        ChildDoc.setAttribute('action', 'insert');
        ChildDoc.setAttribute('class', 19);
        ChildDoc.setAttribute('BUDGET_ID', Doc.getAttribute('F_BUDGET_ID'));
        ChildDoc.setAttribute('DOC_NUMBER', Doc.getAttribute('DOC_NUMBER'));
        ChildDoc.setAttribute('DOC_DATE', Doc.getAttribute('CARRY_DATE'));
        ChildDoc.setAttribute('OPERTYPE_ID', Doc.getAttribute('F_OPERTYPE_ID'));
        //настройка работает по лайнам, по умолчанию пишем 0 - не указано
        ChildDoc.setAttribute('KDT_CODE', 0);
        ChildDoc.setAttribute('DESCRIPTION', Doc.getAttribute('DESCRIPTION'));
        ChildDoc.setAttribute('AMOUNT', Doc.getAttribute('AMOUNT'));
        ChildDoc := ChildDoc.appendChild(ChildDoc.ownerDocument.createElement('LINES'));
        Doc := Doc.ChildNodes.Item[0];
        for i := 0 to Doc.ChildNodes.Length - 1 do
        begin
          Doc := Doc.ChildNodes.Item[i];

          ChildDoc := ChildDoc.appendChild(ChildDoc.ownerDocument.createElement('LINE'));
          ChildDoc.setAttribute('DESCRIPTION',
            Doc.parentNode.parentNode.getAttribute('DESCRIPTION'));
          ChildDoc.setAttribute('AMOUNT', Doc.getAttribute('AMOUNT'));
          ChildDoc.setAttribute('RECEIVER_ID',
            Doc.parentNode.parentNode.getAttribute('F_INCRECORGID'));
          ChildDoc.setAttribute('ORGACCOUNT_ID',
            Doc.parentNode.parentNode.getAttribute('F_INCRECACCID'));
          ChildDoc.setAttribute('KADMD_CODE', GetNodeAttributeEx( Doc, 'KADMD_CODE'));
          ChildDoc.setAttribute('KD_CODE', GetNodeAttributeEx( Doc, 'KD_CODE'));
          // exchange #3062 - отмена косгу
          //ChildDoc.setAttribute('KESD_CODE', Doc.getAttribute('KESD_CODE'));
          //устанавливаем Доп.КД по настройке.
          Kdd_Code := FindSettingsType2(Doc.getAttribute('F_PRIMARYKBK'), List);
          // exchange 3013
          // проблема в том, что здесь нужно учитывать доп код с учетом маски.
          // в старом коде это небыло учтено.
          ChildDoc.setAttribute(
                'KDD_CODE',
                IfThen( KbkExists(
                          Doc.parentNode.parentNode.getAttribute('F_BUDGET_ID'),
                          Kdd_Code,
                          'KDD'),
                        Kdd_Code,
                        xKDD_ZERO {'0'}));

          //Exchange #191 (киф всегда 1)
          ChildDoc.setAttribute('FSD_ID', 1);
          ChildDoc.parentNode.parentNode.setAttribute(
                                          'KDT_CODE',
                                          GetNodeAttributeEx( Doc, 'KDT_CODE'));
          ChildDoc.setAttribute( 'KDT_CODE',
                                 GetNodeAttributeEx( Doc, 'KDT_CODE'));
          // exchange #2411
          // в доп.ЭД код цели указывается в поле PURPOSEFULGRANT_ID, а в 24-м
          // в поле PURPOSEFULGRANTD_ID
    //      ChildDoc.setAttribute('PURPOSEFULGRANT_ID', Doc.getAttribute('PURPOSEFULGRANT_ID'));
          ChildDoc.setAttribute( 'PURPOSEFULGRANT_ID',
                                 GetNodeAttributeEx( Doc, 'PURPOSEFULGRANTD_ID'));

    

          //Настройка типа операции
          ChildDoc.setAttribute('OPERTYPE_ID', GetNodeAttributeEx( Doc, 'OPERTYPE_ID'));
          if (not VarIsNull(Doc.getAttribute('TERRITORY_ID'))) and
            (GetNodeAttributeEx( Doc, 'TERRITORY_ID') <> '') then
            ChildDoc.setAttribute('TERRITORY_ID', GetNodeAttributeEx( Doc, 'TERRITORY_ID'))
          else if Trim(Doc.parentNode.parentNode.getAttribute('PAY_ID')) <> '' then
            ChildDoc.setAttribute('TERRITORY_ID', QueryField(sqlOrgId,
              Doc.parentNode.parentNode.getAttribute('PAY_ID'), 'TERRITORY_ID'));
          Doc := Doc.parentNode.parentNode;
          if (not VarIsNull(Doc.getAttribute('PAY_NAME'))) then
            ChildDoc.setAttribute('PAYER_NAME', Doc.getAttribute('PAY_NAME'));
          if (not VarIsNull(Doc.getAttribute('PAY_TAXCODE'))) then
            ChildDoc.setAttribute('PAYER_TAXCODE', Doc.getAttribute('PAY_TAXCODE'));
          if (not VarIsNull(Doc.getAttribute('PAY_KPP'))) then
            ChildDoc.setAttribute('PAYER_KPP', Doc.getAttribute('PAY_KPP'));
          if (not VarIsNull(Doc.getAttribute('PAY_ID'))) then
            ChildDoc.setAttribute('PAYER_ID', Doc.getAttribute('PAY_ID'));

          // exchange #2389 - доходы
          Exch2389_Update_PURPOSEFULGRANT_ID(
                    //ChildDoc.parentNode.parentNode,
                    ChildDoc,
                    '20',
                    ChildDoc.parentNode.parentNode.getAttribute('BUDGET_ID'),
                    'PURPOSEFULGRANT_ID',
                    ChildDoc.parentNode.parentNode.getAttribute('class'),
                    VarToStr( ChildDoc.GetAttribute('KDT_CODE')));


          Doc := Doc.ChildNodes.Item[0].ChildNodes.Item[i];
          ChildDoc := ChildDoc.parentNode;
          Doc := Doc.parentNode;
        end;
      finally
        List.Free;
      end;
      Doc := Doc.ownerDocument.documentElement;
      ChildDoc := ChildDoc.ownerDocument;

    // переформируем xml в зависимости от типа операции
      RearrangeByLine(ChildDoc, New);
      ChildDoc := New;

      Result := True;
      except
        ExceptionProc( 'CreateChildDoc19');
    end;

end;

{~CreateChildDoc79
//создает документ 79 класса на основе загруженного 24.
  exchange #2405
  в связи с тем, что не все строки должны попадать в доп.ЭД, в параметре
  aLines79 передается массив boolean. для строки, которая должна входить
  в доп.ЭД значение элемента массива будет =TRUE. для исключаемых строк =FALSE.
  если aLines79=NULL, все должно работать как прежде.}
function CreateChildDoc79(  Doc: Variant;
                            var ChildDoc: Variant;
                            aLines79: variant): Boolean;
var
  i: Integer;
  New: Variant;
  xFlag: boolean;
begin

    try
      Result := False;
      New := CreateOleObject('Microsoft.XmlDom');
      try
        ChildDoc := ChildDoc.appendChild(ChildDoc.createElement('DOCUMENT'));
        ChildDoc.setAttribute('action', 'insert');
        ChildDoc.setAttribute('class', 79);
        ChildDoc.setAttribute('BUDGET_ID', Doc.getAttribute('F_BUDGET_ID'));
        ChildDoc.setAttribute('DOC_NUMBER', Doc.getAttribute('DOC_NUMBER'));
        ChildDoc.setAttribute('DOC_DATE', Doc.getAttribute('CARRY_DATE'));
        ChildDoc.setAttribute('OPERTYPE_ID', Doc.getAttribute('F_OPERTYPE_ID'));
        ChildDoc.setAttribute('DESCRIPTION', Doc.getAttribute('DESCRIPTION'));
        ChildDoc.setAttribute('AMOUNT', Doc.getAttribute('AMOUNT'));
        ChildDoc.setAttribute('ORG_ID', Doc.getAttribute('ORG_ID'));
        ChildDoc.setAttribute('ORG_TAXCODE', Doc.getAttribute('ORG_TAXCODE'));
        ChildDoc.setAttribute('ORG_KPP', Doc.getAttribute('ORG_KPP'));
        ChildDoc.setAttribute('ORG_NAME', Doc.getAttribute('ORG_NAME'));
        ChildDoc := ChildDoc.appendChild(ChildDoc.ownerDocument.createElement('LINES'));
        Doc := Doc.ChildNodes.Item[0];
        for i := 0 to Doc.ChildNodes.Length - 1 do begin
          // exchange #2405
          // если строка разрешена в доп.ЭД - добавляем ее в доп.ЭД
          if VarIsNull( aLines79)
            then xFlag := TRUE
            else xFlag := aLines79[i];
          if xFlag then begin
            Doc := Doc.ChildNodes.Item[i];
            ChildDoc := ChildDoc.appendChild(ChildDoc.ownerDocument.createElement('LINE'));
            //Настройка типа операции
            ChildDoc.setAttribute('OPERTYPE_ID', GetNodeAttributeEx( Doc, 'OPERTYPE_ID'));
            ChildDoc.setAttribute('AMOUNT', GetNodeAttributeEx( Doc, 'AMOUNT'));
            ChildDoc.setAttribute('KADMI_CODE', GetNodeAttributeEx( Doc, 'KADMI_CODE'));
            ChildDoc.setAttribute('KI_CODE', GetNodeAttributeEx( Doc, 'KI_CODE'));
            // exchange #3062 - отмена косгу
            //ChildDoc.setAttribute('KESI_CODE', Doc.getAttribute('KESI_CODE'));
            ChildDoc.setAttribute('KDI_CODE', GetNodeAttributeEx( Doc, 'KDI_CODE'));
            ChildDoc.setAttribute('FSI_ID', GetNodeAttributeEx( Doc, 'FSI_ID'));
            ChildDoc.setAttribute('COUNTERAGENT_ID',
              Doc.parentNode.parentNode.getAttribute('PAY_ID'));

            // exchange #2411
            // поле кода цели тянем из главного ЭД из 24-го ЭД
            // PURPOSEFULGRANTD_ID, а в доп.эд код цели в поле PURPOSEFULGRANT_ID
            ChildDoc.setAttribute( 'PURPOSEFULGRANT_ID',
                                    GetNodeAttributeEx( Doc, 'PURPOSEFULGRANTI_ID'));

            // exchange #2389 - источники
            Exch2389_Update_PURPOSEFULGRANT_ID(
                  //ChildDoc.parentNode.parentNode,
                  ChildDoc,
                  '31',
                  ChildDoc.parentNode.parentNode.getAttribute('BUDGET_ID'),
                  'PURPOSEFULGRANT_ID',
                  ChildDoc.parentNode.parentNode.getAttribute('class'),
                  '');  // для источников тип дохода не указывается

            ChildDoc := ChildDoc.parentNode;
            Doc := Doc.parentNode;
          end;
        end;//for//
      finally
      end;
      Doc := Doc.ownerDocument.documentElement;
      ChildDoc := ChildDoc.ownerDocument;
      // переформируем xml в зависимости от типа операции
      RearrangeByLine(ChildDoc, New);
      ChildDoc := New;
      Result := True;
      except
        ExceptionLog( 'Сбой Un_Import.CreateChildDoc79');
    end;

end;

//Val - значение, которое надо найти
//L - List со значениями в формате <Val>
//Возвращает TRUE, если значение найдено
function FindSettingsType1(Val: String; L: TStringList): Boolean;
var
  i: Integer;
begin
  Result := False;
  if Val <> '' then
  begin
    for i := 0 to L.Count - 1 do
      if MatchesMask(Val, L.Strings[i]) then
      begin
        Result := True;
        Break;
      end;
  end;
end;

//Val - значение, которое надо найти
//L - List со значениями в формате <Result>:<Val>
//Возвращает значение перед <:>
function FindSettingsType2(Val: String; L: TStringList): String;
var
  i: Integer;
begin

    try
      Result := '';
      if Val <> '' then
      begin
        for i := 0 to L.Count - 1 do
        begin
          if MatchesMask(Val, Copy(L.Strings[i], Pos(':', L.Strings[i]) + 1, 20)) then
          begin
            Result := Copy(L.Strings[i], 1, Pos(':', L.Strings[i]) - 1);
            break;
          end;
        end;
      end;
      except
        ExceptionProc( 'FindSettingsType2');
    end;

end;

{~GetCaptionStatusED
  возвращает название состояния ЭД по коду aStatusED }
function GetCaptionStatusED( aStatusED: string): string;
begin

    try
      Result := QueryField( ' select caption S from dispstatus where ID = ?',
                            [ TRIM( aStatusED)],
                            'S');

      except
        ExceptionLog( 'Сбой GetCaptionStatusED');
    end;

end;


{~EDMoveToStatus
  выполняет перевод статусов эд aDocID (таблица aDocTable)
  в конечный статус aEndStatus по цепочке aChain.
  цепочка указывается в виде набора строк через запятую:
    тек_статус=action
  например:
    0=process,88=finalize
  допускается указание в виде набора строк:
    0=process
    88=finalize
  символ <CR><LF> (перевод строки) равноценен символу ","

  результат:
    =true - достигнуто конечное состояние (статус).
    =false - текущее состояние эд не распознано.}
function EDMoveToStatus( aBudgetID, aDocID, aDocClass, aEndStatus, aChain: string): boolean;
var
  xStatusED: string;
  SL: TStringList;
  xAction: string;
  xFound: boolean;
  xActionName: string;
  xNewStatus: string;
  xSQL_DispStatus: string;
begin

    try

      Result := FALSE;
      // получаем название таблицы эд в бд по номеру класса и
      // формируем запрос определения статуса эд
      xSQL_DispStatus := ' select DISPSTATUS_ID S from '
                          + TableForClass( aDocClass) + ' where ID = ?';
      SL:= TStringList.Create;
      try
        // выполняем разбор цепочки перевода статусов
        SL.Text := StringReplace( TRIM( aChain), ',', #13#10);
        repeat
          // запрос статуса эд
          // здесь кеш использовать нельзя !!!
          xStatusED := QueryField( xSQL_DispStatus, [ aDocID], 'S', FALSE);
          WriteLog( FORMAT( 'ЭД находится на статусе "%s" (%s).',
                            [ GetCaptionStatusED( xStatusED),
                              xStatusED]));

          // проверяем: это требуемый конечный статус эд ?
          if (xStatusED = aEndStatus) then begin
            Result := TRUE;
            BREAK;
          end;

          // ищем строку, описывающую выполнение операции над эд
          // относительно текущего статуса.
          // если такой нет - значит выполнен переход на статус
          // не соответствующий дальнейшей обработке.
          // поскольку с него не сойдем - завершаем обработку эд.
          xAction := SL.Values[ xStatusED];
          if (LENGTH( xAction) <= 0) then begin
            WriteInfo( FORMAT( 'Статус ЭД %s не соответствует дальнейшей обработке.',
                                [ xStatusED]));
            EXIT;
          end;

          // получаем наименование операции
          xActionName:= QueryField( ' select de.caption S from docevent de'
                                   +' left join docstatus ds on de.docstatus_id = ds.id'
                                   +' left join docflowtree dft on dft.id = ds.flow_id and dft.parallel = 0'
                                   +' where dft.documentclass_id=?'
                                   +' and ds.dispstatus_id=? and de.name=?',
                                    [ aDocClass,
                                      xStatusED,
                                      xAction],
                                    'S');
          try
            WriteLog( FORMAT( 'Выполняется "%s"...', [ xActionName]));

            ExecProc( 'DOCUMENT',
                      [ 'action', xAction,
                        'class', aDocClass,
                        'ID', aDocID],
                      aBudgetID);
            except
              WriteInfo(
                  FORMAT( 'Ошибка при выполнении "%s" на статусе %s: %s',
                          [ xActionName,
                            GetCaptionStatusED( xStatusED),
                            LastException.Message]));
              EXIT;
          end;
        until FALSE;
        finally
          SL.Free;
      end;
      except
        ExceptionProc( 'EDMoveToStatus');
    end;

end;


{~DoExecuteAction_spawn_finish
  выполняется экшен spawn_finish

  exchange #3055
  если указан парметр aParamDate3055, то значение строки передается
  в параметре REAL_DATE.
  Если передан resDoc - в него запишется результат выполнения операции}
function DoExecuteAction_spawn_finish( aBudgetId, aDocID, aDocClass: string;
                                       aParamDate3055: string;
                                       var aTextError: string;
                                       var resDoc: Variant = Null): boolean;
var
  resStr: String;
begin

    try
      try

        if (LENGTH( aParamDate3055) > 0)
          then resStr := ExecProc( 'DOCUMENT',
                          [ 'action', 'spawn_finish',
                            'class', aDocClass,
                            'ID', aDocID,
                            'REAL_DATE', aParamDate3055],
                          aBudgetId)
          else resStr := ExecProc( 'DOCUMENT',
                          [ 'action', 'spawn_finish',
                            'class', aDocClass,
                            'ID', aDocID],
                          aBudgetId);
        if not varIsNull(resDoc) then
          resDoc.LoadXml(resStr);
        aTextError := '';
        Result := TRUE;
        except
          aTextError := LastException.Message;
          Result := FALSE;
      end;
      except
        ExceptionProc( 'DoExecuteAction_spawn_finish');
    end;

end;



{~CreateAndLinkDoc5_spawn_finish
  exchange #2866
  создание и линковка эд 5го класса из эд (aDocID/aDocClass...)
  методом spawn_finish.
  параметры:
    aDoc... - описание эд от которого порождается эд 5го класса.
  результат:
    =true - эд 5го класса создан и слинкован с указанным эд (aDoc...)
    =false - ошибка выполнения операции.
  все операции фиксируются в журнале Info.

  exchange #3055
  если указан парметр aParamDate3055, то значение строки передается
  в параметре REAL_DATE.}
function CreateAndLinkDoc5_spawn_finish( aBudgetId, aDocID, aDocClass: string;
                                        aDocNum, aDocDate, aDocSumm: string;
                                        aParamDate3055: string = ''): boolean;
var
  xErrorText: string;
begin

    try
      Result := DoExecuteAction_spawn_finish(
                                     aBudgetId, aDocID, aDocClass,
                                     aParamDate3055,
                                     xErrorText);
      if Result then begin
        WriteLog(
          FORMAT( 'АЦК: Создано "Приложение к выписке дебетовое" № %s Дата: %s Сумма: %s',
                  [ aDocNum,
                    aDocDate,
                    aDocSumm]),
          True);
        WriteLog('Слинкован');
      end else begin
        WriteInfo( 'Ошибка при создании дебетового приложения: '
                    + xErrorText);
      end;
      except
        ExceptionLog( 'Сбой CreateAndLinkDoc5_spawn_finish');
    end;

end;


{~CreateAndLinkDoc193_spawn_moneytransfer
  exchange #2952
  создание и линковка эд 193го класса из эд 195го(aDocID/aDocClass...)
  методом spawn_moneytransfer со статуса 86.
  параметры:
    aDoc... - описание эд от которого порождается эд 193го класса.
  результат:
    =true - эд 193го класса создан и слинкован с указанным эд (aDoc...)
    =false - ошибка выполнения операции.
  все операции фиксируются в журнале Info.}
function CreateAndLinkDoc193_spawn_moneytransfer( aBudgetId, aDocID, aDocClass: string;
                                                  aDocNum, aDocDate, aDocSumm: string): boolean;
begin

    try
      try

        ExecProc( 'DOCUMENT',
                  [ 'action', 'spawn_moneytransfer',
                    'class', aDocClass,
                    'ID', aDocID],
                  aBudgetId);
        WriteLog(
          FORMAT( 'АЦК: Создано "Распоряжения на зачисление средств на л/с" № %s Дата: %s Сумма: %s',
                  [ aDocNum,
                    aDocDate,
                    aDocSumm]),
          True);
        WriteLog('Слинкован');
        Result := TRUE;
        except
          WriteInfo( 'Ошибка при создании ЭД "Распоряжения на зачисление средств на л/с": '
                      + LastException.Message);
          Result := FALSE;
      end;

      except
        ExceptionLog( 'Сбой CreateAndLinkDoc193_spawn_moneytransfer');
    end;

end;


{~CreateAndLinkDoc5_user_commit
  exchange #2866
  создание и линковка эд 5го класса из эд (aDocID/aDocClass...)
  методом user_commit.
  параметры:
    aDoc... - описание эд от которого порождается эд 5го класса.
  результат:
    =true - эд 5го класса создан и слинкован с указанным эд (aDoc...)
    =false - ошибка выполнения операции.
  все операции фиксируются в журнале Info.}
function CreateAndLinkDoc5_user_commit( aBudgetId, aDocID, aDocClass: string;
                                        ChildDoc: Variant;
                                        aShowMsgCreate5: boolean = TRUE): boolean;
var
  aDocNum, aDocDate, aDocSumm: string;
begin

    try
      try
        aDocNum := ChildDoc.getAttribute('DOC_NUMBER');
        aDocDate := ChildDoc.getAttribute('DOC_DATE');
        aDocSumm := ChildDoc.getAttribute('AMOUNT');

        if (not VarIsNull(ChildDoc.getAttribute('_DATAEXCH3055_'))) then
        begin
          ExecProc( 'DOCUMENT',
            [ 'action', 'user_commit',
            'class', aDocClass,
            'ID', aDocID,
            'REAL_DATE', ChildDoc.getAttribute('_DATAEXCH3055_')
            ], aBudgetId);
        end else
          begin
            ExecProc( 'DOCUMENT',
              [ 'action', 'user_commit',
              'class', aDocClass,
              'ID', aDocID
              ], aBudgetId);
          end;
        if aShowMsgCreate5
          then WriteLog(
                  FORMAT( 'АЦК: Создано "Приложение к выписке дебетовое" № %s Дата: %s Сумма: %s',
                          [ aDocNum,
                            aDocDate,
                            aDocSumm]),
                  True)
          else WriteLog(
                  FORMAT( 'АЦК: "Приложение к выписке дебетовое" № %s Дата: %s Сумма: %s',
                          [ aDocNum,
                            aDocDate,
                            aDocSumm]),
                  True);
        WriteLog('Сквитован');
        Result := TRUE;
        except
          WriteInfo( 'Ошибка при создании дебетового приложения: '
                      + LastException.Message);
          Result := FALSE;
      end;
      except
        ExceptionProc( 'CreateAndLinkDoc5_user_commit');
    end;

end;


{~Exec_ChildDoc
  Обработчик дочернего документа для 24 и 5 класса (загрузка линковка)
  а также обработка созданных документов.

  exchange #2826
    по записи #2600 пропущен пункт обработки ЭД 194 и 195.
    по #2826 требуется добавить логику обработки:
      при создании 195, 194 класса запускаем его в обработку и проводим по
      статусам:
          Черновик Завершить подготовку
          Подготовлен Отпправить в обработку
          Средства есть Готов к сиполнению
          Готов к исполнению.

      Если со статуса Подготовлен по действию "Отправить в обработку"
      попала на статус Нет средств, то не обрабатываем дальше Заявку.

      Есть особенность в ексче, что при возникнвении первого сообщения
      при обработке, в т.ч. игнорируемого, это сообщение записыватся в лог
      и обработка документа прекращается. Автоматически ошибка не игнорируется.

    для этого добавлен параметр aEDExecute (по умолчанию =false):
      если =true, то для эд 194 и 195х классов будет добавлена логика
      обработки по #2826.
      если =false - доп.логика не работает.

   exchange #2866
    если параметр aEDExecute=TRUE и aCfgCreateDoc5=TRUE, и создаваемый эд ChildDoc
    = '11', '75', '80', '118' классов, то создаваемые эд ChildDoc
    доводятся до необходимого статуса и по ним создается эд 5го класса
    методом АЦК-Ф.
    при этом здесь не проверяется, по какому файлу выполняется загрузка.
    если параметр:
      aEDExecute=TRUE и aCfgCreateDoc5=false
      или
      aEDExecute=FALSE (при этом aCfgCreateDoc5 вообще не проверяется)
    то все работает по старому: эд создаются на статусе отложен,
    по разным настройкам обрабатываются, и если эд найден в бд на определенном
    статусе - создается эд 5го класса (загрузка по IK для классов
    '11', '75', '80', '118').

   exchange #2952
     добавлен параметр aExtMode.
     туда можно добавлять все что угодно в качестве дополнительных параметров.
     фактически этот параметр импортируется в переменную xExtMode StringList
     как text.
     в данном случае при создании эд 194/195 будет проверяться этот параметр
     на значение: "Create193=1".
     если будет такая подстрока, то для эд 194/195, доведенного до 86го
     статуса будет соднан и слинкован эд 193й.}
procedure Exec_ChildDoc( BudgetId, IdDoc: String; ChildDoc: Variant;
                         aEDExecute: boolean = FALSE;
                         aCfgCreateDoc5: boolean = FALSE;
                         aExtMode: string = '');
var
  //ответное Xml-задание СП АЦК на вставку документа
  xAnswerAzkOnChildXml: Variant;
  AnswerAzkOnChildDoc: Variant;
  xClass: string;
  xFlag: boolean;
  xID: string;
  xStatusED: string;
  xOldChangeStatus: boolean;
  xExtMode: TStringList;
  xDataExch3055: string;


  {~UpdateStatusED_
    изменение статуса эд 194/195/199 класса.
    aText - описание операции (в журнал)
    aAction - операция. если не указана - не выполняется.
    aExtStatusID - изменение внешнего статуса.
                    если указан, выполняется update_extstatus.}
  procedure UpdateStatusED_( aText, aAction: string;
                                     aExtStatusID: string = '');
  begin

      try
        WriteLog( aText);
        if (LENGTH( aAction) > 0) then begin
          ExecProc( 'DOCUMENT',
                    [ 'action', aAction,
                      'class', xClass,
                      'ID', xID],
                    BudgetId);
        end;
        if (LENGTH( aExtStatusID) > 0) then begin
          ExecProc( 'DOCUMENT',
                    [ 'action', 'update_extstatus',
                      'class', xClass,
                      'ID', xID,
                      'EXTSTATUS_ID', aExtStatusID],
                    BudgetId);
        end;
        except
          ExceptionLog( 'Сбой UpdateStatusED_');
      end;

  end;


  {~CreateAndLinkDoc5ByDoc_
    создание эд 5го из созданного эд ChildDoc если параметр
    aCfgCreateDoc5=TRUE.}
  procedure CreateAndLinkDoc5ByDoc_;
  begin

      try

        if aCfgCreateDoc5 then
          // exchange #3045
          // ФТ-3: 2.3.	Если ЭД класса 5 сформирован в системе посредством
          // метода «Создать приложение к выписке исполненное» успешно,
          // то вызывать из родительского ЭД класса 194, 195 метод «Сквитовать».
          if CreateAndLinkDoc5_spawn_finish( BudgetId,
                                             xID,
                                             xClass,
                                             ChildDoc.getAttribute('DOC_NUMBER'),
                                             ChildDoc.getAttribute('DOC_DATE'),
                                             ChildDoc.getAttribute('AMOUNT'),
                                             xDataExch3055)
            then CreateAndLinkDoc5_user_commit(  BudgetId,
                                                 xID,
                                                 xClass,
                                                 ChildDoc,
                                                 FALSE);
        except
          ExceptionLog( 'Сбой CreateAndLinkDoc5ByDoc_');
      end;

  end;


  {~CreateAndLinkDoc5_user_commit_
    создание эд 5го из созданного эд ChildDoc.}
  procedure CreateAndLinkDoc5_user_commit_;
  begin

      try
        CreateAndLinkDoc5_user_commit( BudgetId,
                                       xID,
                                       xClass,
                                       ChildDoc);
        except
          ExceptionLog( 'Сбой CreateAndLinkDoc5_user_commit_');
      end;

  end;


  {~DoED194_195_ToStatus86_
    доводка эд 194/195х классов до статуса "Проверен" и если указан параметр
    (aCfgCreateDoc5=TRUE) то создается эд 5го класса}
  procedure DoED194_195_ToStatus86_;
  begin

      try
        repeat
          xStatusED := QueryField(
                          ' select a.DISPSTATUS_ID S'
                         +' from AUBUCASHREQUEST a where a.ID = ?',
                          [ xID],
                          'S',
                          FALSE);   // здесь кеш использовать нельзя !!!
          case xStatusED of
            '0': begin
                    WriteLog('Создан на статусе "Черновик".');
                    try
                      UpdateStatusED_(
                              'Выполняется "Завершить подготовку"...',
                              'process');
                      except
                        WriteInfo('Ошибка при завершении подготовки: ' + LastException.Message);
                        BREAK;
                    end;
                  end;

            '1': begin
                    WriteLog('Статус ЭД: Подготовлен');
                    try
                      UpdateStatusED_(
                            'Выполняется отправка в обработку...',
                            'process');
                      except
                        WriteInfo('Ошибка при отправке в обработку: '
                                  + LastException.Message);
                        BREAK;
                    end;
                  end;

            '86': begin
                    WriteLog( 'Статус ЭД: Готов к исполнению.');
                    // меняем статус выгрузки на "Проверен"
                    try
                      UpdateStatusED_(
                            'Изменение статуса выгрузки на "Проверен"...',
                            '',
                            // при указании константы возникает
                            // сбой. причина не понятна.
                            // вероятно баг компилятора.
                            '4');//cnExtStatusID_Tested);
                      except
                        WriteInfo( 'Ошибка при изменении статуса выгрузки на статусе "Готов к исполнению": '
                                    + LastException.Message);
                        BREAK;
                    end;
                    // exchange #2866 - создаем эд 5го класса
                    CreateAndLinkDoc5ByDoc_;

                    // exchange #2952
                    // если указано создавать эд 193й, создаем его
                    if (xExtMode.Values[ 'Create193'] = '1')
                      then CreateAndLinkDoc193_spawn_moneytransfer(
                                               BudgetId,
                                               xID,
                                               xClass,
                                               ChildDoc.getAttribute('DOC_NUMBER'),
                                               ChildDoc.getAttribute('DOC_DATE'),
                                               ChildDoc.getAttribute('AMOUNT'));
                    BREAK;
                  end;

            '85': begin
                    WriteLog( 'Статус ЭД: Средства есть.');
                    try
                      UpdateStatusED_(
                            'Выполняется "Готов к исполнению"...',
                            'accept');
                      except
                        WriteInfo('Ошибка при подготовке к исполнению: '
                                   + LastException.Message);
                        BREAK;
                    end;
                  end;

            '42': begin
                    WriteLog('Статус ЭД: Проверка');
                    try
                      UpdateStatusED_(
                            'Выполняется "обработка"...',
                            'process');
                      except
                        WriteInfo( 'Ошибка при выполнении обработки: '
                                    + LastException.Message);
                        BREAK;
                    end;
                  end;

            '84': begin
                    WriteLog('Статус ЭД: Нет средств');
                    try
                      UpdateStatusED_(
                            'Выполняется "Проверить документ"...',
                            'docmentcheck');
                      except
                        WriteInfo( 'Ошибка при выполнении проверки документа: '
                                    + LastException.Message);
                        BREAK;
                    end;
                  end;

            else begin
                    WriteInfo( FORMAT( 'Статус ЭД %s не соответствует дальнейшей обработке.',
                                        [ xStatusED]));
                    BREAK;
                  end;
          end;//case//
        until FALSE;

        except
          ExceptionLog( 'Сбой DoED194_195_ToStatus86_');
      end;

  end;


begin
  try
    xExtMode:= NIL;

    try
      xExtMode:= TStringList.Create;
      xExtMode.Text := aExtMode;

      // exchange #3055
      // проверяем в эд спец.тег
      xDataExch3055 := GetNodeAttributeEx( ChildDoc, '_DATAEXCH3055_');


      if ((not VarIsNull(ChildDoc.GetAttribute('ID'))) and (ChildDoc.GetAttribute('ID') <> '')) then
      begin
        xAnswerAzkOnChildXml := CreateOleObject('Microsoft.XmlDom');
        AnswerAzkOnChildDoc := xAnswerAzkOnChildXml.appendChild(xAnswerAzkOnChildXml.createElement('DOC'));
        AnswerAzkOnChildDoc.SetAttribute('DOCUMENTCLASS_ID', ChildDoc.getAttribute('class'));
        AnswerAzkOnChildDoc.SetAttribute('ID', ChildDoc.GetAttribute('ID'));
        AnswerAzkOnChildDoc := xAnswerAzkOnChildXml;
      end else
      begin
        AnswerAzkOnChildDoc := CreateOleObject('Microsoft.XmlDom');
        AnswerAzkOnChildDoc.LoadXml(ExecXml(ChildDoc.xml, BudgetId));
      end;

      //  старый алгоритм обработки статуса эд
      xOldChangeStatus := TRUE;

      //Обработка дополнительного документа
      with AnswerAzkOnChildDoc.documentElement do begin
        xClass := getAttribute('DOCUMENTCLASS_ID');
        xID    := getAttribute('ID');


        // exchange #3063
        // при наличие ошибки эд остается на статусе создания
        // проверяется наличие тега ошибки по фт-3 в эд 11го класса
        if (xClass = '11') then
          if (GetNodeAttributeEx( ChildDoc, '__ERROR_3063__') <> '')
            then EXIT;

        if aEDExecute then
          case xClass of
            // exchange #2826 для ЭД 195 и 194го класса
            '195','194': begin
                          //xActionProcessState := '';
                          DoED194_195_ToStatus86_;
                          EXIT;
                        end;

            // exchange #2832 для ЭД 199го класса
            // оставлено на будущую доработку
            // доводка эд 199го класса до статуса "Обработан" (10)
            '199': begin
                      // exchange #2945
                      // если указано что эд 199 должны оставаться на статусе
                      // "черновик", блокируем дальнейшее изменение эд
                      if (xExtMode.Values[ 'no_change_status_199'] = '1')
                        then EXIT;

                      EDMoveToStatus( BudgetID,
                                      xID,
                                      xClass,
                                      '10',
                                      '0=process,1=process,46=process');
                      EXIT;
                    end;

            // exchange #2866
            '11': if aCfgCreateDoc5 then begin
                    // доводим созданный эд до 13го статуса
                    // для создания эд 5го класса и создаем эд 5го класса
                    if EDMoveToStatus( BudgetID,
                                        xID,
                                        xClass,
                                        '13',
                                        '0=finalize,88=in_processing,56=process,'
                                       +'57=accept,5=execute')
                      // exchange #3045
                      then CreateAndLinkDoc5_user_commit_;
                    EXIT;
                  end;

            // exchange #2866
            '75': if aCfgCreateDoc5 then begin
                    // доводим созданный эд до 13го статуса
                    // для создания эд 5го класса и создаем эд 5го класса
                    if EDMoveToStatus( BudgetID,
                                        xID,
                                        xClass,
                                        '13',
                                        '0=process')
                      then CreateAndLinkDoc5_user_commit_;
                    EXIT;
                  end;

            // exchange #2866
            '118': if aCfgCreateDoc5 then begin
                    // доводим созданный эд до 6го статуса
                    // для создания эд 5го класса и создаем эд 5го класса
                    if EDMoveToStatus( BudgetID,
                                        xID,
                                        xClass,
                                        '6',
                                        '0=process,1=process,5=to_execute')
                      then CreateAndLinkDoc5_user_commit_;
                    EXIT;
                  end;

            // exchange #2866
            '80': if aCfgCreateDoc5 then begin
                    // доводим созданный эд до 16го статуса
                    // для создания эд 5го класса и создаем эд 5го класса
                    if EDMoveToStatus( BudgetID,
                                        xID,
                                        xClass,
                                        '16',
                                        '0=process,1=send')
                      then CreateAndLinkDoc5_user_commit_;
                    EXIT;
                  end;
          end;//case//


        // сделано через отдельную переменную на случай, если потребуется
        // доводить эд по новому варианту с совместимостью дальнейшей
        // обработки эд по старому варианту.
        if xOldChangeStatus then
          case xClass of
            // exchange #2349
            // созданный документ остается на статуе "черновик"
            '195': begin
                    WriteInfo('Создан на статусе "черновик"');
                    EXIT;
                  end;

            '7': begin

                    ExecProc('DOCUMENT', ['action', 'execute', 'class', '7',
                      'ID',  getAttribute('ID')], BudgetId);
                    WriteInfo('Создан');
                  end;

            // exchange #2335
            // 215-й документ после импорта переводится на статус "Отложен"
            // и дальше пускается в обработку.
            '215': try
            {        ExecProc('DOCUMENT', ['action', 'execute', 'class', getAttribute('DOCUMENTCLASS_ID'),
                      'ID',  getAttribute('ID')], BudgetId);}
                    xFlag := FALSE;
                    if NOT XmlAttrExists( ChildDoc, 'EST_KIND')
                      then WriteLog( 'Нет поля EST_KIND в документе ChildDoc.')
                      else xFlag :=
                            ( (isDirectionControl(
                                  getAttribute('DOCUMENTCLASS_ID'),
                                  ChildDoc.getAttribute('EST_KIND')) = '1')
                             and
                              (ChildDoc.SelectNodes('//LINE[@DIRECTION_ID=''' + ''+''']').length >=1));
          		      if not xFlag then begin
                      // ВНИМАНИЕ! процесс обработки имеет имя, отличной от
                      // процесса классов 39 и 40

                      ExecProc('DOCUMENT', ['action', 'process', 'class',
                        getAttribute('DOCUMENTCLASS_ID'), 'ID',  getAttribute('ID')], BudgetId);
                      WriteInfo('Создан/Обработан');
                    end else begin
                      WriteInfo('Создан на статусе "отложен"');
                      Exit;
                    end;
                    except
                      ExceptionLog( 'Сбой дополнительного документа: Класс 215.');
                  end;

            '75', '80', '118': begin
    //                if getAttribute('DOCUMENTCLASS_ID') in ['75', '80', '118'] then begin

                    ExecProc('DOCUMENT', ['action', 'process', 'class',
                      getAttribute('DOCUMENTCLASS_ID'), 'ID',  getAttribute('ID')], BudgetId);
                    WriteInfo('Создан');
                  end;
            '39', '40': begin
    //      if getAttribute('DOCUMENTCLASS_ID') in ['39', '40'] then
                    if ((getAttribute('DOCUMENTCLASS_ID') = '39') and (GetNodeAttributeEx( ChildDoc, 'DONT_PROCESS') <> '1')) or
                 			 ((getAttribute('DOCUMENTCLASS_ID') = '40') and
            		       not ((isDirectionControl(
                                  getAttribute('DOCUMENTCLASS_ID'),
                                  ChildDoc.getAttribute('EST_KIND')) = '1') and
                            (ChildDoc.SelectNodes('//LINE[@DIRECTION_ID=''' + ''+''']').length >=1)))
                      then begin

                        ExecProc('DOCUMENT', ['action', 'carry', 'class',
                          getAttribute('DOCUMENTCLASS_ID'), 'ID',  getAttribute('ID')], BudgetId);
                        WriteInfo('Создан/Обработан');
                      end else begin
                        WriteInfo('Создан на статусе "отложен"');
                        Exit;
                      end;
                    end;
            '11': begin
            //        if getAttribute('DOCUMENTCLASS_ID') = '11' then
                    //1-Контролировать, 0-нет, 2-запрещать
                    // подменяем класс документа, т.к в АЦК ЗОР по лс фк в этой настройке это 48 класс
                    if not ((isDirectionControl('48', ChildDoc.getAttribute('EST_KIND')) = '1')
                      and (ChildDoc.SelectNodes('//LINE[@DIRECTION_ID=''' + ''+''']').length >=1)) then
                    begin

                      ExecProc('DOCUMENT', ['action', 'process', 'class', getAttribute('DOCUMENTCLASS_ID'),
                      'ID',  getAttribute('ID')], BudgetId);
                      WriteInfo('Создан');
                    end
                    else begin
                      WriteInfo('Создан на статусе "отложен"');
                      Exit;
                    end;
                  end;

            '25': begin
                    // exchange #3057
                    // если БР не определен, то и его тип тоже
                    if (GetNodeAttributeEx( ChildDoc, 'EST_KIND') = '') then begin
                      WriteInfo('Создан на статусе "отложен"');
                      Exit;
                    end;
                    //1-Контролировать, 0-нет, 2-запрещать
                    if not ((isDirectionControl(
                                    getAttribute('DOCUMENTCLASS_ID'),
                                    ChildDoc.getAttribute('EST_KIND')) = '1')
                       and (ChildDoc.SelectNodes(
                                '//LINE[@DIRECTION_ID=''' + ''+''']').length >=1))
                      then begin

                        ExecProc( 'DOCUMENT',
                                  [ 'action', 'process',
                                    'class', '25',
                                    'ID',  getAttribute('ID')],
                                  BudgetId);
                        WriteInfo('Создан');
                      end else begin
                        WriteInfo('Создан на статусе "отложен"');
                        Exit;
                      end;
                  end;
              '35': begin
                    if (GetNodeAttributeEx( ChildDoc, 'DONT_PROCESS') = '1') then begin
                      WriteInfo('Создан на статусе "отложен"');
                      Exit;
                    end
                    else
                    begin
                      ExecProc('DOCUMENT', ['action', 'process', 'class',
                        getAttribute('DOCUMENTCLASS_ID'), 'ID',  getAttribute('ID')], BudgetId);
                      WriteInfo('Создан');
                    end;
                  end;

            else begin

                ExecProc('DOCUMENT', ['action', 'process', 'class',
                  getAttribute('DOCUMENTCLASS_ID'), 'ID',  getAttribute('ID')], BudgetId);
                WriteInfo('Создан');
              end;
          end;//case//

        
        if not (xClass in ['11', '75', '80', '35', '39', '40', '118', '215'])
          then begin
            //Линкуем дополнительный документ

            ExecProc('DOCUMENT', ['action', 'link', 'class', getAttribute('DOCUMENTCLASS_ID'),
              'ID',  getAttribute('ID'), 'PARENT_ID', IdDoc], BudgetId);
            WriteInfo('Слинкован');
            
          end;
      
        if (ChildDoc.getAttribute('F_ORIGINAL_TYPE') = 'IK') and
          (getAttribute('DOCUMENTCLASS_ID') in ['11', '75', '80', '118']) then
        begin
          // проверка статуса созданного эд
          if CheckDispStatusDoc( getAttribute('ID'),
                                 getAttribute('DOCUMENTCLASS_ID')) and
            (not VarIsNull(ChildDoc.getAttribute('F_CREATE5'))) and (StrToBool(ChildDoc.getAttribute('F_CREATE5'))) then
          try

            ExecProc('DOCUMENT', ['action', 'user_commit', 'class',
              getAttribute('DOCUMENTCLASS_ID'), 'ID', getAttribute('ID')], BudgetId);
            WriteInfo('АЦК: "Приложение к выписке дебетовое" № ' +
              ChildDoc.getAttribute('DOC_NUMBER') + ' Дата: ' +
              DateToStr(XmlToDateTime(ChildDoc.getAttribute('DOC_DATE'))) + ' Сумма: ' +
              ChildDoc.getAttribute('AMOUNT'), True);
            WriteInfo('Слинкован');
            
          except
            WriteInfo('Ошибка при создании дебетового приложения: ' + LastException.Message);
          end;
        end;
      end;
      except
        { Exchange #2373
          перехватываем except при создании доп. доков.
          логируем сбой в журнале, но продолжаем работу скрипта.}

        WriteInfo('Ошибка при вставке/обработке доп. документа: ' + LastException.Message);
    end;
    finally
      if (xExtMode <> NIL) then xExtMode.Free;

  end;
end;

//Функция возвращает наименование парного файла, если пусто, то парный файл
//не найден.
//FirstFile - полный путь и наименование первого файла
//ShemaFirstFile - наименование файла схемы первого файла.
function GetPairFileName(FirstFile, ShemaFirstFile: String; var Guid_FK: String): String;
var
  Pair: TFileSearch;
  Xml: Variant;
  FileMarker, FileName: String;
begin

    try
      Result := '';
      Pair := TFileSearch.Create;
      try
      // загружаем схему первого файла
        LoadSchema(ShemaFirstFile);
        Xml := LineTextFileToXml(FirstFile, 3);
        // exchange #2571
        // если файл не загружен или возникла ошибка загрузки, результат =NULL
        if VarIsNull( Xml) then begin
          WriteInfo( FORMAT( 'Файл %s не будет обрабатываться, поскольку он загружен с ошибками.',
                             [ FirstFile]));
          EXIT;
        end;
        try
          Guid_FK := Xml.documentElement.getAttribute('GUID_FK');

          except
            WriteInfo('Нарушена структура файла:' + FirstFile + '. Нет поля GUID_FK.');

            EXIT;
        end;
        // exchange #2453
        // расширение файла берем всегда в верхнем регистре, поскольку при
        // сравнении со значением в XML при несовпадении регистра расширения
        // файл пары не будет найден.
        FileMarker := UPPERCASE( Copy(ExtractFileExt(FirstFile), 2, 2));
        // загружаем схему второго файла
        LoadSchema( GetFileNameSchemaTFF( 'bd_txbd*'));//DirIni + 'Schems\bd_txbd100701.xml');
        if Pair.FindFirst(ExtractFilePath(DirIn) + '*.BD?', faAnyFile) = 0 then
        begin

          repeat
            if (Pair.Name <> '.') and (Pair.Name <> '..') and (Pair.Attr <> faDirectory) then
            begin
              // нашли какой-то файл удовлетворяющий маске, проверяем является ли он
              // парой для первого файла
              FileName := ExtractFilePath(DirIn) + Pair.Name;

              Xml := LineTextFileToXml(FileName, 3);
              // exchange #2571
              // если файл не загружен или возникла ошибка загрузки, результат =NULL
              if VarIsNull( Xml) then begin
                WriteInfo( FORMAT( 'Файл %s не будет обрабатываться, поскольку он загружен с ошибками.',
                                   [ FirstFile]));
                CONTINUE;
              end;

              try
                // exchange #2593
                // для ТФФ 11.2 проверяется BD.VID_OTCH.
                // файлы BD не загружается, если BD.VID_OTCH <>0.

                // exchange #2616
                // при переходе на ТФФ12 условие должно остаться
                // exchange #2703
                // переход на ТФФ 12.2: условие проверки ТФФ отменяется,
                // поскольку параметр BD.VID_OTCH имеется начиная с ТФФ 11.2.
                //if (IsVersionSupport( cnVersionTFF_11_2)
                //    OR IsVersionSupport( cnVersionTFF_12)) then
                  if (Xml.documentElement.getAttribute('VID_OTCH') <> '0') then begin
                    WriteInfo( FORMAT( 'Файл %s не будет загружен, поскольку не имеет признака принадлежности к итоговому отчёту.',
                                        [ Pair.Name]));

                    CONTINUE;
                  end;


                // exchange #2453
                // сравнение выполняем в верхнем регистре, иначе пару можно не найти
                // поскольку имя файла может быть в регистре, отличном от
                // поля KOD_DOC в XML.
                if (Xml.documentElement.getAttribute('GUID_OTCH') = Guid_FK) and
                  (UPPERCASE( Xml.documentElement.getAttribute('KOD_DOC')) = FileMarker) then
                begin
                  Result := FileName;

                  Exit;
                end;

              except
                WriteInfo('Структура файла ' + FileName + ' не соответсвует ' +
                  'структуре описанной формате - пропущен');
              end;
            end;
          until Pair.FindNext <> 0;

        end;
      finally
        Pair.Free;
      end;
      except
        ExceptionProc( 'Un_Import.GetPairFileName');
    end;

end;

{~Rearrange
// переформирование xml в зависимости от класса дочернего документа
  exchange #3062
  доработка кода}
procedure Rearrange(Doc, NewDoc: Variant);
var
  i: Integer;
  NodeName: String;
  Node: Variant;
begin

    try
      NewDoc := NewDoc.appendChild(NewDoc.createElement('DOCUMENT'));
      Doc := Doc.childNodes.item[0].childNodes;

      for i := 0 to Doc.length - 1 do
      begin
        Doc := Doc.item[i];
        NodeName := 'DOCUMENT_' + Doc.getAttribute('F_CHILD_CLASS');
        Node := NewDoc.getElementsBytagName(NodeName);

        if Node.length = 0 then
        begin
          NewDoc := NewDoc.appendChild(NewDoc.ownerDocument.createElement(NodeName));
          if (not VarIsNull(Doc.parentNode.parentNode.getAttribute('F_CRUSH24')))
           and (StrToBool(Doc.parentNode.parentNode.getAttribute('F_CRUSH24'))) then
          begin
            NewDoc := NewDoc.appendChild(Doc.parentNode.parentNode.cloneNode(false));
            NewDoc.setAttribute('F_CHILD_CLASS', Doc.getAttribute('F_CHILD_CLASS'));
            NewDoc := NewDoc.appendChild(Doc.parentNode.cloneNode(True));
          end
          else begin
            NewDoc := NewDoc.appendChild(Doc.ownerDocument.documentElement.cloneNode(false));
            NewDoc.setAttribute('AMOUNT', 0);
            NewDoc.setAttribute('F_CHILD_CLASS', Doc.getAttribute('F_CHILD_CLASS'));
            NewDoc := NewDoc.appendChild(Doc.ownerDocument.documentElement.childNodes.item[0].cloneNode(false));
          end;
        end
        else
          NewDoc := Node.item[0].childNodes.item[0].childNodes.item[0];

        if not ((not VarIsNull(Doc.parentNode.parentNode.getAttribute('F_CRUSH24')))
         and (StrToBool(Doc.parentNode.parentNode.getAttribute('F_CRUSH24')))) then begin
          NewDoc := NewDoc.appendChild(Doc.CloneNode(True));

          NewDoc.parentNode.parentNode.setAttribute('AMOUNT',
          StrToCurrDef(NewDoc.parentNode.parentNode.getAttribute('AMOUNT'), 0) +
          StrToCurrDef(NewDoc.getAttribute('AMOUNT'), 0));
        end;

        NewDoc := NewDoc.ownerDocument.documentElement;
        Doc := Doc.parentNode.childNodes;
      end;

      if (not VarIsNull(NewDoc.childNodes.item[0].childNodes.item[0].getAttribute('F_SPECSR')))
           and (NewDoc.childNodes.item[0].childNodes.item[0].getAttribute('F_SPECSR') = 'по правилу ЛенОбласти') then
        SplitClass74ByOrgId(NewDoc);

      if (not VarIsNull(NewDoc.childNodes.item[0].childNodes.item[0].getAttribute('F_SPECSR')))
           and (NewDoc.childNodes.item[0].childNodes.item[0].getAttribute('F_SPECSR') = 'по правилу Иркутск') then
        SplitClass74ByLine(NewDoc);

      if (not VarIsNull(NewDoc.childNodes.item[0].childNodes.item[0].getAttribute('F_SPECSR')))
        and (NewDoc.childNodes.item[0].childNodes.item[0].getAttribute('F_SPECSR') = 'по правилу Чита') then
        SplitClass74ByLine(NewDoc, True);
      except
        ExceptionLog( 'Сбой Un_Import.Rearrange');
    end;

end;
  (*
procedure Rearrange(Doc, NewDoc: Variant);
var
  i: Integer;
  NodeName: String;
  Node: Variant;
  xDocLines: Variant;
  xDocLine: Variant;
begin

    try
      NewDoc := NewDoc.appendChild(NewDoc.createElement('DOCUMENT'));
//      Doc := Doc.childNodes.item[0].childNodes;
      xDocLines := Doc.childNodes.item[0].childNodes;

//      for i := 0 to Doc.length - 1 do
      for i := 0 to xDocLines.length - 1 do begin
//        Doc := Doc.item[i];
        xDocLine := xDocLines.item[i];
        NodeName := 'DOCUMENT_' + Doc.getAttribute('F_CHILD_CLASS');
        Node := NewDoc.getElementsBytagName(NodeName);

        if Node.length = 0 then begin
          NewDoc := NewDoc.appendChild(NewDoc.ownerDocument.createElement(NodeName));
          if (not VarIsNull(Doc{.parentNode.parentNode}.getAttribute('F_CRUSH24')))
           and (StrToBool(Doc{.parentNode.parentNode}.getAttribute('F_CRUSH24'))) then
          begin
            NewDoc := NewDoc.appendChild(Doc{.parentNode.parentNode}.cloneNode(false));
            NewDoc.setAttribute('F_CHILD_CLASS', Doc.getAttribute('F_CHILD_CLASS'));
            NewDoc := NewDoc.appendChild(xDocLines{Doc.parentNode}.cloneNode(True));
          end
          else begin
            NewDoc := NewDoc.appendChild(Doc.ownerDocument.documentElement.cloneNode(false));
            NewDoc.setAttribute('AMOUNT', 0);
            NewDoc.setAttribute('F_CHILD_CLASS', Doc.getAttribute('F_CHILD_CLASS'));
            NewDoc := NewDoc.appendChild(Doc.ownerDocument.documentElement.childNodes.item[0].cloneNode(false));
          end;
        end
        else
          NewDoc := Node.item[0].childNodes.item[0].childNodes.item[0];

        if not ((not VarIsNull(Doc.parentNode.parentNode.getAttribute('F_CRUSH24')))
         and (StrToBool(Doc.parentNode.parentNode.getAttribute('F_CRUSH24')))) then begin
          NewDoc := NewDoc.appendChild(Doc.CloneNode(True));

          NewDoc.parentNode.parentNode.setAttribute('AMOUNT',
          StrToCurrDef(NewDoc.parentNode.parentNode.getAttribute('AMOUNT'), 0) +
          StrToCurrDef(NewDoc.getAttribute('AMOUNT'), 0));
        end;

        NewDoc := NewDoc.ownerDocument.documentElement;
        Doc := Doc.parentNode.childNodes;
      end;

      if (not VarIsNull(NewDoc.childNodes.item[0].childNodes.item[0].getAttribute('F_SPECSR')))
           and (NewDoc.childNodes.item[0].childNodes.item[0].getAttribute('F_SPECSR') = 'по правилу ЛенОбласти') then
        SplitClass74ByOrgId(NewDoc);

      if (not VarIsNull(NewDoc.childNodes.item[0].childNodes.item[0].getAttribute('F_SPECSR')))
           and (NewDoc.childNodes.item[0].childNodes.item[0].getAttribute('F_SPECSR') = 'по правилу Иркутск') then
        SplitClass74ByLine(NewDoc);

      if (not VarIsNull(NewDoc.childNodes.item[0].childNodes.item[0].getAttribute('F_SPECSR')))
        and (NewDoc.childNodes.item[0].childNodes.item[0].getAttribute('F_SPECSR') = 'по правилу Чита') then
        SplitClass74ByLine(NewDoc, True);
      except
        ExceptionLog( 'Сбой Un_Import.Rearrange');
    end;

end;
*)

// переформирование xml в зависимости от типа операции
procedure RearrangeByLine(Doc, NewDoc: Variant);
var
  i: Integer;
  NodeName: String;
  Node: Variant;
begin
  NewDoc := NewDoc.appendChild(NewDoc.createElement('DOCUMENT'));
  Doc := Doc.childNodes.item[0].childNodes.item[0].childNodes;
  for i := 0 to Doc.length - 1 do
  begin
    Doc := Doc.item[i];
    //  по типу операции
    NodeName := 'DOCUMENT_' + Doc.getAttribute('OPERTYPE_ID');
    Node := NewDoc.getElementsBytagName(NodeName);
    if Node.length = 0 then
    begin
      NewDoc := NewDoc.appendChild(NewDoc.ownerDocument.createElement(NodeName));
      NewDoc := NewDoc.appendChild(Doc.ownerDocument.documentElement.cloneNode(false));
      NewDoc.setAttribute('AMOUNT', 0);
      NewDoc.setAttribute('OPERTYPE_ID', Doc.getAttribute('OPERTYPE_ID'));
      NewDoc := NewDoc.appendChild(Doc.ownerDocument.documentElement.childNodes.item[0].cloneNode(False));
    end
    else
      NewDoc := Node.item[0].childNodes.item[0].childNodes.item[0];
    NewDoc := NewDoc.appendChild(Doc.CloneNode(False));
    NewDoc.parentNode.parentNode.setAttribute('AMOUNT',
    StrToCurrDef(NewDoc.parentNode.parentNode.getAttribute('AMOUNT'), 0) +
    StrToCurrDef(NewDoc.getAttribute('AMOUNT'), 0));
    NewDoc := NewDoc.ownerDocument.documentElement;
    Doc := Doc.parentNode.childNodes;
  end;
end;


{~LinkDoc
  если будет найден ЭД, то будет создан и слинкован ЭД 5/24го класса.
  результат:
    =TRUE - ЭД создан и слинкован.
    =FALSE - операция создания и линковки ЭД не выполнена.

  если файл загружен из файла 'VJ','VI','VS','VK' - поиск осуществляется
  по:
     DOC_DATE+F_AMOUNT'+'F_DOC_NUMBER'+F_PARENTCLASS+F_BUDGET_ID+PAY_ACCOUNT
     или
     DOC_DATE+AMOUNT+DOC_NUMBER+F_PARENTCLASS+F_BUDGET_ID.

  если файл загружен из файла 'IK' - поиск осуществляется
  по:
     DOC_DATE+AMOUNT+DOC_NUMBER+F_BUDGET_ID+GUID(BDPD.GUID)
     или
     DOC_DATE+AMOUNT+DOC_NUMBER+F_BUDGET_ID+FOREIGN_KEY(BDPD.GUID_FK).

  при загрузке файла IK поле Doc.getAttribute('F_PARENTCLASS') не заполняется
    или равно пустой строке.

  exchange #2831
  при линковке ЭД 5го класса, созданного по IK.BDPD по новому алгоритму,
  если ЭД для линковки не найден.


  при загрузке 'VJ','VI','VS','VK', ЭД для линковки ищется на 86м статусе
  с внешним статусом выгрузки =1 (см. GetLinkId).
  а при линковке, внешний статус всегда меняется на 4 (проверен)
  (перед вызовом link эд 5го класса).

  а для IK - при поиске эд для линковки, внешний статус не используется
  ни для каких эд (так было раньше и после доработки #2600)
  (см.GetLinkIdforIK).}
function LinkDoc(Doc: Variant): Boolean;
var
  DocLoad, Link: Variant;
  Link_Id: String;
  n: integer;
  xDoc: Variant;
  //xCreateDoc5ByInsert: boolean;
  xOldLinkMethod: integer;
  xF_ORIGINAL_TYPE: string;
  xDoc195: Variant;
  xDeclineAction: string;
  xDeclineExtStatus: string;
  xParentClass: string;
  xDoc5ID: string;
  xBudgetID: string;
  xLinkDocumentID: string;
  xF_PARENTCLASS: string;
  xErrorText: string;
  xDataExch3055: string;
//  xFoundDoc195: variant;

  {~DoLink_
    поиск эд для линковки с эд 5го класса (загрузка IK)}
  procedure DoLink_;
  var
    xQuery: String;
    Xml: Variant;
    Query: TRunQuery;
  begin

      try
        // если указано поле BDPD.GUID - ищем по этому полю,
        // иначе по BDPD.GUID_FK.
        // по форматам IK, BDPD.GUID должен совпадать с GUID_FG в блоках
        // IK.ZR,ZS,ZV,ZN. если это не так, то эд для линковки вряд ли найдется,
        // поскольку выполняется поиск: BDPD.GUID=ЭД.FOREGN_KEY, где:
        // ЭД.FOREGN_KEY заполняется из GUID_FG в блоках IK.ZR,ZS,ZV,ZN.
        if (not VarIsNull(Doc.getAttribute('GUID')))
                                        and (Doc.getAttribute('GUID') <> '')
          then Link := GetLinkIdforIK(
                            XmlToDateTime(Doc.getAttribute('DOC_DATE')),
                            StrToCurr(Doc.getAttribute('AMOUNT')),
                            Doc.getAttribute('DOC_NUMBER'),
                            Doc.getAttribute('F_BUDGET_ID'),
                            Doc.getAttribute('GUID'))
          else Link := GetLinkIdforIK(
                            XmlToDateTime(Doc.getAttribute('DOC_DATE')),
                            StrToCurr(Doc.getAttribute('AMOUNT')),
                            Doc.getAttribute('DOC_NUMBER'),
                            Doc.getAttribute('F_BUDGET_ID'),
                            Doc.getAttribute('FOREIGN_KEY'));
                            
        if (VarIsNull(Link)) and (Doc.getAttribute('LINK_WITH_EXT195') = '1') then // Exchange, #3187 поиск документа 195-го класса.
        begin
          xQuery := ' select au.id, au.documentclass_id ' +
                            ' from aubucashrequest au ' +
                            ' where (au.title_id is null or au.title_id = au.id) ' +
                            ' and au.documentclass_id = 195 ' +
                            ' and au.dispstatus_id = 86 ' +
                            ' and au.budget_id = ? ' +
                            ' and rtrim(ltrim(au.doc_number)) = ? ' +
                            ' and au.doc_date = ? ' +
                            ' and au.pay_acc_id = ? ' +
                            ' and au.amount = ? ';
          Query := TRunQuery.Create;
          try
            Query.addStr(Doc.getAttribute('F_BUDGET_ID'));
            Query.addStr(Doc.getAttribute('DOC_NUMBER'));
            Query.AddDate(XmlToDateTime(Doc.getAttribute('DOC_DATE')));
            Query.AddStr(Doc.getAttribute('PAY_ACC_ID'));
            Query.AddCurr(StrToCurr(Doc.getAttribute('AMOUNT')));
            Xml := CreateOleObject('Microsoft.XmlDom');
            Xml.LoadXml(Query.Run(xQuery));
            if Xml.documentElement.childNodes.length = 1
            then Link := Xml.documentElement.childNodes.Item[0]
            else Link := null;
          finally
            Query.Free;
          end;
        end;


        except
          ExceptionLog( 'Сбой DoLink_');
      end;

  end;


  {~GetLinkDoc_ExtStatus_
    получение статуса выгрузки эд aId класса aClass.
    здесь кеш использовать нельзя. }
  function GetLinkDoc_ExtStatus_: string;
  begin

      try
        Result := QueryField(
                          FORMAT( 'select EXTSTATUS_ID S from %s where ID = ?',
                                  [ TableForClass( xParentClass)]),
                          [ Link_Id],
                          'S',
                          FALSE);

        except
          ExceptionLog( 'Сбой GetLinkDoc_ExtStatus_');
      end;

  end;


  {~GetExtStatusCaption_
    определение названия статуса выгрузки aExtStatus }
  function GetExtStatusCaption_( aExtStatus: string): string;
  begin

      try
        Result := QueryField( ' select CAPTION A from extstatus where id=?',
                              [ aExtStatus],
                              'A');

        except
          ExceptionLog( 'Сбой GetExtStatusCaption_');
      end;

  end;


  {~CheckLinkDoc_ExtStatus_
    проверка статуса выгрузки эд aId класса aClass
    для перевода на новое состояние статуса выгрузки = aNewExtStatus.
    результат:
      0 - текущий статус эд не указан или пред.и новый статусы одинаковые.
          в журнал пишется сообщение.
          статус выгрузки менять не требуется.
      1 - текущий статус эд "выгружен".
          требуется менять статус на aNewExtStatus.
          в журнал ничего не пишется.
      2 - статус выгрузки имеет несоотвтетствующее значение.
          в журнал пишется сообщение.
          требуется прервать квитовку.}
  function CheckLinkDoc_ExtStatus_( aNewExtStatus: string): string;
  var
    xExtStatus: string;
  begin

      try
        xExtStatus := GetLinkDoc_ExtStatus_;
        if ( xExtStatus = aNewExtStatus) then begin
          {WriteInfo(
              FORMAT( 'Статус выгрузки ЭД %s соответствует значению "%s" и не будет изменен.',
                      [ GetDocumentNameByClass( xParentClass),
                        GetExtStatusCaption_( aNewExtStatus)]));}
          Result := '0';
        end else
          case xExtStatus of
            '1': Result := '1';
            '0': begin
                    {WriteInfo(
                        FORMAT( 'ЭД %s не выгружался. Статус выгрузки не будет изменен на "%s".',
                                [ GetDocumentNameByClass( xParentClass),
                                  GetExtStatusCaption_( aNewExtStatus)]));}
                    Result := '0';
                  end;
            else begin
                    WriteInfo(
                        FORMAT( 'ЭД %s имеет внешний статус, не подходящий для квитовки.',
                                [ GetDocumentNameByClass( xParentClass)]));
                    Result := '2';
                  end;
          end;//case//

        except
          ExceptionLog( 'Сбой CheckLinkDoc_ExtStatus_');
      end;

  end;


  {~SetExtStatus_LinkDoc_
    изменение внешнего статуса линкуемого эд Link_Id класса xParentClass.
    результат:
      =true - изменение статуса выполнено успешно.
      =false - сбой изменения внешн. статуса}
  function SetExtStatus_LinkDoc_( aNewExtStatus: string): boolean;
  begin

      try

        try
          ExecProc( 'DOCUMENT',
                    [ 'action', 'update_extstatus',
                      'class', xParentClass,
                      'ID', Link_Id,
                      'EXTSTATUS_ID', aNewExtStatus],
                    xBudgetID);
          WriteInfo( FORMAT( 'Смена внешнего статуса ЭД %s на "%s"',
                             [ GetDocumentNameByClass( xParentClass),
                               GetExtStatusCaption_( aNewExtStatus)]));
          Result := TRUE;
          except
            WriteInfo( 'Ошибка при переводе внешнего статуса: '
                        + LastException.Message);
            Result := FALSE;
        end;

        except
          ExceptionLog( 'Сбой SetExtStatus_LinkDoc_');
      end;

  end;


  {~Link5_
    линковка эд 5го класса xDoc5ID с эд xLinkDocumentID.
    результат
      =true - операция выполнена
      =false - операция не выполнена}
  function Link5_: boolean;
  begin

      try

        try
          ExecProc( 'DOCUMENT',
                    [ 'action', 'link',
                      'class', '5',
                      'ID', xDoc5ID,
                      'PARENT_ID', xLinkDocumentID],
                    xBudgetID);
          WriteInfo('Слинкован');
          Result := TRUE;
        except
          WriteInfo('Ошибка при линковке документов: ' + LastException.Message);
          Result := FALSE;
        end;

        except
          ExceptionLog( 'Сбой Link5_');
      end;

  end;


  {~LinkDocLoad_
    загрузка линкуемого эд aLinkID класса aPARENTCLASS в переменную Link (xml)}
  procedure LinkDocLoad_( aLinkID, aPARENTCLASS: string);
  begin

      try
        //линковка документов: найденной ЗОР с созданным ЭД
        // приложением к выписке кредитовым.

        Link := CreateOleObject('Microsoft.XmlDom');
        Link.LoadXml(
                ExecProc( 'DOCUMENT',
                          [ 'action', 'read',
                            'class', aPARENTCLASS,
                            'ID', aLinkID],
                          xBudgetID));
        xLinkDocumentID := Link.documentElement.getAttribute ('DOCUMENT_ID');

        except
          ExceptionLog( 'Сбой LinkDocLoad_');
      end;

  end;


  {~Doc5_Finalize_
    вызов метода finalize (завершение квитовки) эд 5го класса
    на статусе "выполнен"}
  function Doc5_Finalize_: boolean;
  begin

      try

        try
          ExecProc( 'DOCUMENT',
                    [ 'action', 'finalize',
                      'class', '5',
                      'ID', xDoc5ID],
                    xBudgetID);
          WriteInfo( 'Квитовка выполнена');
          Result := TRUE;
          except
            WriteInfo( 'Ошибка квитовки: ' + LastException.Message);
            Result := FALSE;
        end;

        except
          ExceptionLog( 'Сбой Doc5_Finalize_');
      end;

  end;


  {~Doc5_Create_
    создание эд 5го класса на статусе "отложен"}
  procedure Doc5_Create_;
  begin

      try

        DocLoad := CreateOleObject('Microsoft.XmlDom');
        DocLoad.LoadXml( ExecXML(  Doc.xml, xBudgetID));
        xDoc5ID := DocLoad.documentElement.getAttribute ('ID');

        except
          ExceptionLog( 'Сбой Doc5_Create_');
      end;

  end;


  {~Doc5_Action_
    выполнение операции aAction над созданным эд 5го класса }
  function Doc5_Action_( aAction: string): boolean;
  begin

      try

        try
          DocLoad.LoadXml(
                    ExecProc( 'DOCUMENT',
                              [ 'action', aAction,
                                'class', '5',
                                'ID', xDoc5ID],
                              xBudgetID));
          Result := TRUE;
          except
            WriteInfo( FORMAT( 'Ошибка выполнения %s: %s',
                                [ aAction,
                                  LastException.Message]));
            Result := FALSE;
        end;

        except
          ExceptionLog( 'Сбой Doc5_Action_');
      end;

  end;


  {~Doc5_PrepareDecline_
    проверка флага DECLINE в задании Doc (описание создаваемого эд 5го класса).
    если DECLINE=true - эд 5го класса будет переведен на статус "отказан".
    если DECLINE=false - эд 5го класса будет переведен на статус "выполнен".}
  procedure Doc5_PrepareDecline_;
  begin

      try
        // здесь определяем операцию (отказ или выполнен) и статус выгрузки/
        // это дает то, что код будет в одном месте.
        if StrToBool(Doc.getAttribute('DECLINE')) then begin
          xDeclineAction    := 'mark_decline';     // отказ
          xDeclineExtStatus := '3';
        end else begin
          xDeclineAction    := 'mark_finish';     // выполнен
          xDeclineExtStatus := '4';
        end;

        except
          ExceptionLog( 'Сбой Doc5_PrepareDecline_');
      end;

  end;


  {~DoCreateAndLink_
    exchange #2573
    создание эд 5го класса (Doc) и линковка его с найденным эд (Link_Id)
    класса xParentClass: аубу (194/195) или 11,118,75,80,43
    новым способом.
    exchange #2876
    логика квитовка аубу (194/195) отличается от эд 11,75,118,80х классов,
    поэтму доработку #2831/#2832 нужно применять только для эд 194/195х.}
  function DoCreateAndLink_: boolean;
  var
    xError: boolean;
  begin

      try
        xError := FALSE;
        case xParentClass of
          // exchange #2831 + exchange #2832
          // квитовка ау/бу - отдельно от эд 11,118,80,75х классов
          '194',
          '195': begin
                  // определение статуса эд для создаваемого
                  // эд 5го класса
                  Doc5_PrepareDecline_;

                  // вставка эд 5го класса на статусе "отложен"
                  Doc5_Create_;

                  // перевод эд 5го класса на "выполнен" или "отказ"
                  Doc5_Action_( xDeclineAction);
//                  // перевод эд 5го класса на "выполнен"
//                  Doc5_Action_( 'mark_finish');

                  // загрузка линкуемого эд из ацк-ф
                  LinkDocLoad_( Link_Id, xParentClass);

                  // в зависимости от текущего статуса выгрузки выполняем:
                  case CheckLinkDoc_ExtStatus_( xDeclineExtStatus) of
                    // выгружен
                    // меняем статус выгрузки на "проверен"/"ошибка проверки"
                    '1':  if NOT SetExtStatus_LinkDoc_( xDeclineExtStatus)
                            then xError := TRUE
                            else
                          // линковка
                          if NOT Link5_
                            then xError := TRUE
                            else
                          // окончание квитовки для ау/бу (194/195х классов)
                          if NOT Doc5_Finalize_
                            then xError := TRUE;

                    // не определен или проверен
                    '0':  // линковка
                          if NOT Link5_
                            then xError := TRUE
                            else
                          // окончание квитовки для ау/бу (194/195х классов)
                          if NOT Doc5_Finalize_
                            then xError := TRUE;

                    // прочие значения статуса выгрузки то выполняем
                    // только связывание эд, а квитовка не выполняется.
                    else begin
                          Link5_;
                          xError := TRUE;
                        end;
                  end;//case//
                end;

          // 11,118,75,80,43,13
          else begin
                  // определение статуса эд для создаваемого
                  // эд 5го класса
                  Doc5_PrepareDecline_;

                  // вставка эд 5го класса на статусе "отложен"
                  Doc5_Create_;

                  // перевод эд 5го класса на "выполнен" или "отказ"
                  Doc5_Action_( xDeclineAction);

                  // загрузка линкуемого эд из ацк-ф
                  LinkDocLoad_( Link_Id, xParentClass);

                  // в зависимости от текущего статуса выгрузки выполняем:
                  case CheckLinkDoc_ExtStatus_( xDeclineExtStatus) of
                    // выгружен
                    '1':  if NOT Link5_    // линковка
                            then xError := TRUE
                            else
                          // меняем статус выгрузки на "проверен"/"ошибка проверки"
                          if NOT SetExtStatus_LinkDoc_( xDeclineExtStatus)
                            then xError := TRUE;

                    // не определен или проверен
                    '0':  // линковка
                          if NOT Link5_
                            then xError := TRUE
                            else
                          // окончание квитовки без изменения внешнего статуса
                          if NOT Doc5_Finalize_
                            then xError := TRUE;

                    // прочие значения статуса выгрузки то выполняем
                    // только связывание эд, а квитовка не выполняется.
                    else begin
                          Link5_;
                          xError := TRUE;
                        end;
                  end;//case//
                end;
        end;//case//
        if xError then begin
          WriteInfo( 'Линковка не выполнена.');
          Result := FALSE;
        end else begin
          WriteInfo( 'Линковка и квитовка выполнена.');
          Result := TRUE;
        end;

        except
          ExceptionLog( 'Сбой DoCreateAndLink_');
      end;

  end;

begin

    try
      Result := False;

      // exchange #3055
      // проверяем в эд спец.тег
      xDataExch3055 := GetNodeAttributeEx( Doc, '_DATAEXCH3055_');

      // exchange #3009
      // если для эд определена опция, что линковку с эд выполнять не нужно,
      // то завершаем эту операцию сразу.

      if (GetNodeAttributeEx( Doc, '_BS_RCP_40116_LS_UBP_30_') <> '')
        then EXIT;

      // exchange #2573 - сохраняем параметр, чтобы не лазать к узлу
      xF_ORIGINAL_TYPE  := GetNodeAttributeEx( Doc, 'F_ORIGINAL_TYPE');
      xBudgetID         := GetNodeAttributeEx( Doc, 'F_BUDGET_ID');
      // exchange #3007 - проблема совмещения доработок
      xF_PARENTCLASS    := GetNodeAttributeEx( Doc, 'F_PARENTCLASS');

      // проверку на присутствие атрибута не делаем, т.к он должен быть в этих загрузках


      if (xF_ORIGINAL_TYPE in ['VJ','VI','VS','VK']) and
        (not (StrToBool(Doc.getAttribute('F_AUTOPARSING')))) then
      begin
        Result := False;
        Exit;
      end;


      Link_Id := '';
      if xF_PARENTCLASS <> '' then begin


        if (xF_ORIGINAL_TYPE in ['VJ','VI','VS','VK'])
          then Link_Id := GetLinkId(
                              StrToDateTime(Doc.getAttribute('F_DOC_DATE')),
                              StrToCurr(Doc.getAttribute('F_AMOUNT')),
                              Doc.getAttribute('F_DOC_NUMBER'),
                              Doc.getAttribute('F_PARENTCLASS'),
                              Doc.getAttribute('F_BUDGET_ID'),
                              Doc.getAttribute('PAY_ACCOUNT'))
          else Link_Id := GetLinkId(
                              XmlToDateTime(Doc.getAttribute('DOC_DATE')),
                              StrToCurr(Doc.getAttribute('AMOUNT')),
                              Doc.getAttribute('DOC_NUMBER'),
                              Doc.getAttribute('F_PARENTCLASS'),
                              Doc.getAttribute('F_BUDGET_ID'));
      end;



      // загрузка из IK файла
      if ((xF_PARENTCLASS = '') and (xF_ORIGINAL_TYPE = 'IK')) then begin
        Link_Id := '';



        // ищем эд для линковки с 5м эд
        DoLink_;

        // exchange #2831
        // если его не удалось сквитовать с ЭД класса 195 или 194
        // (ЭД класса 195 или 194 не найден в системе), то если первые два
        // знака IK.LS равны «30» требуется сформировать документ класса 195,
        // а потом попытаться с ним слинковать эд 5го класса.
        if VarIsNull(Link) then
          if Check_Doc5ByIK_BDPB_Mark2831( Doc) then begin
            // exchange #2998
            // если эд 195й по конфигурации создавать не нужно, значит
            // ищем 195й для линковки в бд без гуида. это нужно из-за того,
            // что эд 195е создают вручную, а из фк приходят bdpd 5е,
            // которые нужно слинковать с этими эд, но при ручном вводе
            // гуиды не заполняются и поиск нужно выполнить без гуида.
            // если эд найден, то нужно ему присвоить гуиз из 5го и слинковать
            // с 5м. если эд не найден - созвать только 5й без 195го.
            if Check_Doc5ByIK_BDPB_Mark2998( Doc) then begin
              Link := Found195_by_BDPD_2998( Doc);
            end else begin
              // нужно чистить поле GUID в эд 5/24м чтобы линковка выполнялась
              // по полю GUID_FK (FOREGN_KEY) - см. подпрограмму Link_
              Doc.SetAttribute( 'GUID', '');
              // создаем эд 195го класса из 5го (Doc)
              // exchange #2998
              // при создании эд 195го возможен вариант, когда такой эд уже
              // есть в бд, тогда новый эд 195й не нужно создавать.
              // а найденный нужно слинковать с 5м.
              // в этм случае, результат создания 195го будет =NIL,
              // а найденный эд будет в Link.
              //xFoundDoc195 := NIL;
              xDoc195 := CreateDoc195_ByDoc5_2831( Doc, Link);
              if NOT VarIsNull( xDoc195) then begin
                // создаем эд 195го класса и доводим до статуса
                // "готов к исполнению" (86)
                Exec_ChildDoc( Doc.getAttribute('F_BUDGET_ID'), '', xDoc195, TRUE);
                // если эд создан - пробуем повторно определить эд для линковки
                DoLink_;
              end;
            end;
          end;

        // если эд для линковки найден, то сохраняем его класс поле F_PARENTCLASS
        // в результате будет выполняться линковка по новому алгоритму #2573
        // при загрузке из файла IK.
        if not VarIsNull(Link) then begin
          Link_Id := Link.getAttribute('ID');
          xF_PARENTCLASS := Link.getAttribute('DOCUMENTCLASS_ID');
          Doc.setAttribute('F_PARENTCLASS', xF_PARENTCLASS);

        end;
      end;

      // exchange #2876 - доработка линковки.
      xParentClass:= xF_PARENTCLASS;

      if (VarToStr( Link_Id) <> '') then begin

        // exchange #2573
        // при обработке блока BDPD, если ЭД загружается из IK и найден ЭД
        // по GUI/GUID_FK то создание ЭД 5го класса выполняется методом insert.
        // при этом БЛ создания и линкофки отличается от БЛ для импорта из
        // файлов VI/VJ/VS/VK.
        // иначе - по старому.
        // exchange #2876
        // линковка выполняется аналогично загрузке IK
        case xF_ORIGINAL_TYPE of
            'VJ','VI','VS','VK': begin

                  xOldLinkMethod := 0;  // по новому
                  DoCreateAndLink_;
                end;

          // exchange #2573
          // тут не забываем, что по заполнению в разделе BDPD в скрипте Imp_FK_IK
          // поле Doc.getAttribute('F_PARENTCLASS') содержит пустую строку,
          // а если (см.выше) по GUID нашли ЭД ЗОР, то поле
          // Doc.getAttribute('F_PARENTCLASS')
          // заполняется полем ID найденного ЭД, поэтому тут проверяем,
          // если это поле заполнено - выполняем вставку ЭД методом insert!
          // см. выше: при поиске эд функцией DoLink_, если эд 11,75,118,80
          // и эд 194/195 найден, то будет заполнено поле F_PARENTCLASS.
          // в результате будет работать новый алгоритм линковки
          // exchange #2876
          // создание и линковка эд 5го класса (doc) с найденным эд (link)
          'IK':
              if (LENGTH( VarToStr( Doc.getAttribute('F_PARENTCLASS'))) <= 0)
                then xOldLinkMethod := 1// по старому (из IK)
                else begin

                  xOldLinkMethod := 0;  // по новому
                  DoCreateAndLink_;
                end;

          else  xOldLinkMethod := 2;        // по старому (прочее) - как было
        end;//case//



        // вызываем старый метод создания ЭД
        if (xOldLinkMethod <> 0) then begin

          { exchange #2443
            при разборе проблемы exchange #2443 возникла ситуация, что найти
            приложение к выписке дебитовое по guid не удается, зато находится
            ЗОР по гуиду в BDPD.
            тогда нужно проверить, если в ЗОР есть прилинкованные приложения
            к выписке кредитовые, то в журнале делаем пометку об этом,
            и новое приложение не формируем (через spawn_insert) и не квитуем.
            при этом требуется отобразить реквизиты ЭД, у которого найдены
            сквитованные приложения к выписке дебитовые.}
          if NOT StrToBool(Doc.getAttribute('DECLINE')) then begin
            n := GetDoc5ByLinkedBudgorderDocCount(
                            Doc.getAttribute('F_BUDGET_ID'),
                            Link_Id);
            if (n > 0) then begin
              xDoc := QueryXml( ' Select bo.* from Budgorder bo Where bo.id=?',
                                [ Link_Id]);

              xDoc := xDoc.documentElement;
              if (xDoc.childNodes.Length <= 0)
                then WriteInfo( 'Не удалось найти описание ЭД с порожденными ЭД '
                                +'Приложения к выписке дебетовые.')
                else begin
                  xDoc := xDoc.childNodes.Item[0];
                  WriteInfo( FORMAT( '%s № %s от %s на сумму %s уже имеет порожденное '
                                    +'Приложение к выписке дебетовое.',
                                     [ GetDocumentNameByClass(
                                          xDoc.getAttribute('DOCUMENTCLASS_ID')),
                                       TRIM( xDoc.getAttribute('DOC_NUMBER')),
                                       YYYYmMMmDD_to_DDdMMdYYYY(
                                          TRIM( xDoc.getAttribute('DOC_DATE'))),
                                       FormatStrAsNumberP2(
                                          TRIM( xDoc.getAttribute('AMOUNT')))]));
                end;
              Result := FALSE;
              EXIT;
            end;
          end;

          // exchange #3055
          // разделяем код: вместо ifthen выполняем отдельно для spawn_decline
          // и отдельно для spawn_finish.
          // вызов экшена для spawn_finish выполняем через вызов подпрограммы.
          // это дает унификацию кода!
          {
          DocLoad := CreateOleObject('Microsoft.XmlDom');
          DocLoad.LoadXml(
              ExecProc( 'DOCUMENT',
                        [ 'action', IfThen(
                                        StrToBool(Doc.getAttribute('DECLINE')),
                                        'spawn_decline',
                                        'spawn_finish'),
                          'class', Doc.getAttribute('F_PARENTCLASS'),
                          'ID', Link_Id],
                        Doc.getAttribute('F_BUDGET_ID')));

          WriteInfo( 'Слинкован/Статус '
                      + IfThen(
                            StrToBool(Doc.getAttribute('DECLINE')),
                            '"Отказан банком"',
                            '"Выполнен"'));
                            }
          DocLoad := CreateOleObject('Microsoft.XmlDom');
          if StrToBool(Doc.getAttribute('DECLINE')) then begin
            DocLoad.LoadXml(
                ExecProc( 'DOCUMENT',
                          [ 'action', 'spawn_decline',
                            'class', Doc.getAttribute('F_PARENTCLASS'),
                            'ID', Link_Id],
                          Doc.getAttribute('F_BUDGET_ID')));
            WriteInfo( 'Слинкован/Статус "Отказан банком"');
          end else begin
            if DoExecuteAction_spawn_finish(
                                      GetNodeAttributeEx( Doc, 'F_BUDGET_ID'),
                                      Link_Id,
                                      GetNodeAttributeEx( Doc, 'F_PARENTCLASS'),
                                      xDataExch3055,
                                      xErrorText,
                                      DocLoad)
              then WriteInfo( 'Слинкован/Статус "Выполнен"')
              else WriteInfo( 'Сбой перевода на статус "Выполнен": ' + xErrorText);
          end;

        end;

        DocLoad := DocLoad.documentElement;


        // exchange #2450
        // вызывается после создания ЭД и линковки обоими методами.
        updateDoc5Ex( Doc.getAttribute('F_BUDGET_ID'),
                      DocLoad.getAttribute('DOCUMENT_ID'),
                      Doc.getAttribute('CARRY_DATE'),
                      Doc.getAttribute('FOREIGN_KEY'),
                      Doc.getAttribute('DOC_NUMBER'));

        Result := True;
      end;
      except
        ExceptionLog( 'Сбой Un_Import.LinkDoc');
    end;

end;

//создает документ 11 класса на основе загруженного 5
function CreateChildDoc11(Doc: Variant; ChildDoc: Variant): Boolean;
var
  i: Integer;
  UsePrimaryOrg, Kbk, Permission, DocLines, DocLine: Variant;
  UsePrimaryFlag: Boolean;
  Fio, Dolzhnost, Est_Kind: String;
begin

    try
      Result := False;

      
      if (Doc.childNodes.Length > 0) then
      begin

        DocLines := Doc.childNodes.item[0];
        
        for i := DocLines.childNodes.Length - 1 downto 0 do
        begin
          DocLine := DocLines.childNodes.Item[i];
          if (GetNodeAttributeEx(DocLine, 'ANAL_KIND') <> '0') then
            DocLines.RemoveChild(DocLine);
        end;
        
        if (DocLines.childNodes.Length <= 0) then

          exit;
      end;

//      try
        WriteInfo('Дополнительные документы: ');
        ChildDoc := ChildDoc.appendChild(Doc.cloneNode(False));
        ChildDoc.setAttribute('class', 11);
        ChildDoc.setAttribute('BUDGET_ID', Doc.getAttribute('F_BUDGET_ID'));
        ChildDoc.setAttribute('F_ORIGINAL_TYPE', Doc.getAttribute('F_ORIGINAL_TYPE'));
        if Doc.getAttribute('QUEUE_KIND') <> '' then
          ChildDoc.setAttribute('QUEUE_KIND', Doc.getAttribute('QUEUE_KIND'))
        else
          ChildDoc.setAttribute('QUEUE_KIND', GetQueueKind);
        if IsSysparamOn('budgreq.dont_fill_limiting_date') then
          ChildDoc.setAttribute('LIMITING_DATE', '')
        else
          ChildDoc.setAttribute('LIMITING_DATE', Doc.getAttribute('DOC_DATE'));
        //признак "от ФК" - т.к. загрузка через Эксч
        ChildDoc.SetAttribute( 'FK_FLAG', '1');
        ChildDoc.setAttribute('EXTSTATUS_ID', 0);
        ChildDoc.setAttribute('ADVANCE_PAYMENT', 0);
        ChildDoc.setAttribute('RESPPERSON_SIG_DATE', Doc.getAttribute('DOC_DATE'));
        UsePrimaryFlag := False;
    //не проверяем на наличие аттрибута F_USE_PRIMARY_ORG, т.к если попали сюда,
    //значит он есть
        if StrToBool(Doc.getAttribute('F_USE_PRIMARY_ORG')) then begin
          WriteInfo('Формирования ЗОР по данным первичной организации');
          UsePrimaryOrg := CreateOleObject('Microsoft.XmlDom');
          UsePrimaryFlag := GetPrimaryOrg(Doc.getAttribute('PAY_ID'), UsePrimaryOrg);
          if not UsePrimaryFlag then
            WriteInfo('Не создан - не удалось определить первичную организацию');
          if UsePrimaryFlag then begin
    //делаем дополнительную проверку на тип счета "лицевой счет ФК"
    //наличие счета обязательно!!!
            ChildDoc.setAttribute('RECIPIENT_ID',UsePrimaryOrg.getAttribute('RECIPIENT_ID'));
            //чтобы не ломать общий поиск разрешения, записываем референс в шапку
            ChildDoc.setAttribute('ORG_ID', ChildDoc.getAttribute('RECIPIENT_ID'));
            if (not VarIsNull(ChildDoc.getAttribute('F_SS'))) and
              StrToBool(ChildDoc.getAttribute('F_SS')) then
            begin
              ChildDoc.setAttribute('ORGACCOUNT_ID',GetLicAccSs(ChildDoc.getAttribute('RECIPIENT_ID'), '5'));
              if ChildDoc.getAttribute('ORGACCOUNT_ID') = '' then begin
                WriteInfo('Не создан - не определен референс счета плательщика');
          	    UsePrimaryFlag := False;
                Result := False;
              end
              else begin
                ChildDoc.setAttribute('ESTIMATE_ID',GetEstimateIdSs(ChildDoc.getAttribute('BUDGET_ID'),
                  ChildDoc.getAttribute('RECIPIENT_ID'), ChildDoc.getAttribute('ORGACCOUNT_ID')));
                if ChildDoc.getAttribute('ESTIMATE_ID') = '' then begin
                  WriteInfo('Не создан - не определен бланк расходов плательщика');
    	            UsePrimaryFlag := False;
                  Result := False;
                end;
              end;
            end
            else begin
              ChildDoc.setAttribute('ORGACCOUNT_ID',GetLicAcc(ChildDoc.getAttribute('RECIPIENT_ID'), '5'));
              if ChildDoc.getAttribute('ORGACCOUNT_ID') = '' then begin
                WriteInfo('Не создан - не определен референс счета плательщика');
          	    UsePrimaryFlag := False;
                Result := False;
              end
              else begin
                ChildDoc.setAttribute('ESTIMATE_ID',GetEstimateId(ChildDoc.getAttribute('BUDGET_ID'),
                  ChildDoc.getAttribute('RECIPIENT_ID'), ChildDoc.getAttribute('ORGACCOUNT_ID'),
                  Doc.ChildNodes.Item[0].ChildNodes.Item[0]));
                if ChildDoc.getAttribute('ESTIMATE_ID') = '' then begin
                  WriteInfo('Не создан - не определен бланк расходов плательщика');
    	            UsePrimaryFlag := False;
                  Result := False;
                end;
              end;
            end;
          end;
        end;
    //не удалось создать по первичной организации, пытаемся по обычной
        if not UsePrimaryFlag then begin
          WriteInfo('Формирование ЗОР');
          ChildDoc.setAttribute('RECIPIENT_ID', ChildDoc.getAttribute('PAY_ID'));
          //чтобы не ломать общий поиск разрешения, записываем референс в шапку
          ChildDoc.setAttribute('ORG_ID', ChildDoc.getAttribute('RECIPIENT_ID'));
          if ChildDoc.getAttribute('RECIPIENT_ID') = '' then begin
            WriteInfo('Не создан - не определен референс плательщика');
            Result := False;
            Exit;
          end;
          //делаем дополнительную проверку на тип счета "лицевой счет ФК"
          //наличие счета обязательно!!!
          if (not VarIsNull(ChildDoc.getAttribute('F_SS'))) and
            StrToBool(ChildDoc.getAttribute('F_SS')) then
          begin
            ChildDoc.setAttribute('ORGACCOUNT_ID',GetLicAccSs(ChildDoc.getAttribute('RECIPIENT_ID'), '5'));
            if ChildDoc.getAttribute('ORGACCOUNT_ID') = '' then begin
              WriteInfo('Не создан - не определен референс счета плательщика');
              Result := False;
              Exit;
            end
            else begin
              ChildDoc.setAttribute('ESTIMATE_ID',GetEstimateIdSs(ChildDoc.getAttribute('BUDGET_ID'),
                ChildDoc.getAttribute('RECIPIENT_ID'), ChildDoc.getAttribute('ORGACCOUNT_ID')));
              if ChildDoc.getAttribute('ESTIMATE_ID') = '' then begin
                WriteInfo('Не создан - не определен бланк расходов плательщика');
                Result := False;
                Exit;
              end;
            end;
          end
          else begin
            ChildDoc.setAttribute('ORGACCOUNT_ID',GetLicAcc(ChildDoc.getAttribute('RECIPIENT_ID'), '5'));
            if ChildDoc.getAttribute('ORGACCOUNT_ID') = '' then begin
              WriteInfo('Не создан - не определен референс счета плательщика');
              Result := False;
              Exit;
            end
            else begin
              ChildDoc.setAttribute('ESTIMATE_ID',GetEstimateId(ChildDoc.getAttribute('BUDGET_ID'),
                ChildDoc.getAttribute('RECIPIENT_ID'), ChildDoc.getAttribute('ORGACCOUNT_ID'),
                Doc.ChildNodes.Item[0].ChildNodes.Item[0]));
              if ChildDoc.getAttribute('ESTIMATE_ID') = '' then begin
                WriteInfo('Не создан - не определен бланк расходов плательщика');
                Result := False;
                Exit;
              end;
            end;
          end;
        end;
        GetResperson(ChildDoc.getAttribute('RECIPIENT_ID'),'-2' , Fio, Dolzhnost);
        ChildDoc.setAttribute('CHEQUE_FIO_BOSS_STR', Fio);
        ChildDoc.setAttribute('CHEQUE_BOSS_POST', Dolzhnost);
        GetResperson(ChildDoc.getAttribute('RECIPIENT_ID'),'-3' , Fio, Dolzhnost);
        ChildDoc.setAttribute('CHEQUE_FIO_BUHGALT_STR', Fio);
        ChildDoc.setAttribute('CHEQUE_BUHGALT_POST', Dolzhnost);
        Est_Kind := 'EST_KIND' + QueryField('Select EstKind_Id From Estimate Where Id = ?',
          [ChildDoc.getAttribute('ESTIMATE_ID')], 'ESTKIND_ID');
        ChildDoc.setAttribute('EST_KIND', Est_Kind);
        Doc := Doc.ChildNodes.Item[0];
        //Exchange#1927
        //ищем разрешение и его строку по расходной классифкации(по первой строке)
        //если нашли, при создании будем проверять каждую строку
        Permission := GetPermissionRash(ChildDoc, Doc.ChildNodes.Item[0], True);
        if VarIsNull(Permission) then
          //Ищем разрешение с учетом групп по бухгалтерии
          Permission := GetPermissionRashUseGroupBuh(ChildDoc, Doc.ChildNodes.Item[0], True);
        if not VarIsNull(Permission) then
        begin
          // создаем по разрешению
          ChildDoc := ChildDoc.appendChild(ChildDoc.ownerDocument.createElement('LINES'));
          for i := 0 to Doc.childNodes.Length - 1 do
          begin
            Doc := Doc.childNodes.Item[i];
            //ищем разрешение для данной строки
            Permission := GetPermissionRash(ChildDoc.parentNode, Doc, True);
            if VarIsNull(Permission) then
            begin
              Permission := GetPermissionRashUseGroupBuh(ChildDoc.parentNode, Doc, True);
              if VarIsNull(Permission) then
              begin
                WriteInfo('Не создан - не определено разрешение на открытие лс');
                Doc := Doc.parentNode;
                Exit;
              end;
            end;
            ChildDoc := ChildDoc.appendChild(ChildDoc.ownerDocument.createElement('LINE'));
            ChildDoc.setAttribute('RECIPIENT_ID', Permission.getAttribute('RECIPIENT_ID'));
            ChildDoc.setAttribute('ESTIMATE_ID', ChildDoc.parentNode.parentNode.getAttribute('ESTIMATE_ID'));
            ChildDoc.setAttribute('DOCUMENTCLASS_ID', ChildDoc.parentNode.parentNode.getAttribute('class'));
            ChildDoc.setAttribute('ORGACCOUNT_ID', ChildDoc.parentNode.parentNode.getAttribute('ORGACCOUNT_ID'));
            ChildDoc.setAttribute('QUEUE_KIND',ChildDoc.parentNode.parentNode.getAttribute('QUEUE_KIND'));
            ChildDoc.setAttribute('BANKOPER_ID',ChildDoc.parentNode.parentNode.getAttribute('BANKOPER_ID'));
            ChildDoc.setAttribute('PAYKIND',ChildDoc.parentNode.parentNode.getAttribute('PAYKIND'));
            ChildDoc.setAttribute('CHEQUE_FIO_BOSS_STR', ChildDoc.parentNode.
              parentNode.getAttribute('CHEQUE_FIO_BOSS_STR'));
            ChildDoc.setAttribute('CHEQUE_BOSS_POST', ChildDoc.parentNode.
              parentNode.getAttribute('CHEQUE_BOSS_POST'));
            ChildDoc.setAttribute('CHEQUE_FIO_BUHGALT_STR', ChildDoc.parentNode.
              parentNode.getAttribute('CHEQUE_FIO_BUHGALT_STR'));
            ChildDoc.setAttribute('CHEQUE_BUHGALT_POST', ChildDoc.parentNode.
              parentNode.getAttribute('CHEQUE_BUHGALT_POST'));
            ChildDoc.setAttribute('AMOUNT', Doc.getAttribute('AMOUNT'));
            ChildDoc.setAttribute('KFSR_CODE', Doc.getAttribute('KFSR_CODE'));
            ChildDoc.setAttribute('KCSR_CODE', Doc.getAttribute('KCSR_CODE'));
            ChildDoc.setAttribute('KVR_CODE', Doc.getAttribute('KVR_CODE'));
            // exchange #3062 - косгу теперь копируется из рчб
            ChildDoc.setAttribute('KESR_CODE', GetNodeAttributeEx( Permission, 'KESR_CODE'));
            ChildDoc.setAttribute('KADMR_CODE', Doc.getAttribute('KADMR_CODE'));
            ChildDoc.setAttribute('KDF_CODE', Permission.getAttribute('KDF_CODE'));
            ChildDoc.setAttribute('KDE_CODE', Permission.getAttribute('KDE_CODE'));
            ChildDoc.setAttribute('KDR_CODE', Permission.getAttribute('KDR_CODE'));
            ChildDoc.setAttribute('FSR_ID', Permission.getAttribute('FSR_ID'));
            ChildDoc.setAttribute('ANAL_KIND', Doc.getAttribute('ANAL_KIND'));
            ChildDoc.parentNode.parentNode.setAttribute('CODE_GRBS', ChildDoc.getAttribute('KADMR_CODE'));
            ChildDoc.setAttribute('ORG_GRBS', '');
            Kbk := QueryXml('Select Kl.* From Kadm_lines Kl Left Join kadm K on K.Id = Kl.master_id' +
              ' Where Kl.Budget_Id = ? and K.Code = ? order by Kl.Begin_Date desc',
              [ChildDoc.parentNode.parentNode.getAttribute('BUDGET_ID'),
              ChildDoc.getAttribute('KADMR_CODE')]);
            Kbk := Kbk.ChildNodes.Item[0];
            if Kbk.ChildNodes.Length = 1 then
              ChildDoc.setAttribute('ORG_GRBS', Kbk.ChildNodes.item[0].getAttribute('DESCRIPTION'))
            else begin
              for i := 0 to Kbk.ChildNodes.Length -1 do
              begin
                Kbk := Kbk.ChildNodes.item[i];
                if Kbk.getAttribute('END_DATE') = '' then
                  ChildDoc.setAttribute('ORG_GRBS', Kbk.getAttribute('DESCRIPTION'))
                else if (Work_Date >= XmlToDateTime(Kbk.getAttribute('BEGIN_DATE'))) and
                  (Work_Date <= XmlToDateTime(Kbk.getAttribute('END_DATE'))) then
                  ChildDoc.setAttribute('ORG_GRBS', Kbk.getAttribute('DESCRIPTION'));
                Kbk := Kbk.parentNode;
              end;
              if ChildDoc.getAttribute('ORG_GRBS') = '' then
                ChildDoc.setAttribute('ORG_GRBS', Kbk.selectSingleNode('ROW').getAttribute('DESCRIPTION'));
            end;
            ChildDoc.setAttribute('PURPOSEFULGRANT_ID', Doc.getAttribute('PURPOSEFULGRANT_ID'));

    

            ChildDoc.setAttribute('DIRECTION_ID', '');

            // exchange #2389 - расходы
            Exch2389_Update_PURPOSEFULGRANT_ID(
    //                ChildDoc.parentNode.parentNode,
                    ChildDoc,
                    '10',
                    ChildDoc.parentNode.parentNode.getAttribute('BUDGET_ID'),
                    'PURPOSEFULGRANT_ID',
                    ChildDoc.parentNode.parentNode.getAttribute('class'),
                    '');  // для расходов тип дохода не указывается

            //1-Контролировать, 0-нет, 2-запрещать
            if isDirectionAutoFill(ChildDoc.parentNode.parentNode.getAttribute('BUDGET_ID')) and (isDirectionControl(ChildDoc.getAttribute('DOCUMENTCLASS_ID'),
              ChildDoc.parentNode.parentNode.getAttribute('EST_KIND')) <> '2') then
              ChildDoc.setAttribute('DIRECTION_ID', DirectionAutoFill(ChildDoc,
                ChildDoc.parentNode.parentNode.getAttribute('BUDGET_ID')));
            ChildDoc.setAttribute('PERMISSIONLINE_ID', Permission.getAttribute('PERMISSIONLINE_ID'));
            ChildDoc.setAttribute('FUNDSOURCE_ID', Permission.getAttribute('FUNDSOURCE_ID'));
            ChildDoc := ChildDoc.parentNode;
            Doc := Doc.parentNode;
          end;
        end
        else begin
          if (not VarIsNull(ChildDoc.getAttribute('F_SS'))) and
            StrToBool(ChildDoc.getAttribute('F_SS')) then
          begin
            WriteInfo('Не создан - не определено разрешение на открытие лс');
            Result := False;
            Exit;
          end
          else begin
            // создаем ЗОР без разрешения
            ChildDoc := ChildDoc.appendChild(ChildDoc.ownerDocument.createElement('LINES'));
            for i := 0 to Doc.childNodes.Length - 1 do
            begin
              Doc := Doc.childNodes.Item[i];
              ChildDoc := ChildDoc.appendChild(ChildDoc.ownerDocument.createElement('LINE'));
              ChildDoc.setAttribute('RECIPIENT_ID', ChildDoc.parentNode.parentNode.getAttribute('RECIPIENT_ID'));
              ChildDoc.setAttribute('ESTIMATE_ID', ChildDoc.parentNode.parentNode.getAttribute('ESTIMATE_ID'));
              ChildDoc.setAttribute('DOCUMENTCLASS_ID', ChildDoc.parentNode.parentNode.getAttribute('class'));
              ChildDoc.setAttribute('ORGACCOUNT_ID', ChildDoc.parentNode.parentNode.getAttribute('ORGACCOUNT_ID'));
              ChildDoc.setAttribute('QUEUE_KIND',ChildDoc.parentNode.parentNode.getAttribute('QUEUE_KIND'));
              ChildDoc.setAttribute('BANKOPER_ID',ChildDoc.parentNode.parentNode.getAttribute('BANKOPER_ID'));
              ChildDoc.setAttribute('PAYKIND',ChildDoc.parentNode.parentNode.getAttribute('PAYKIND'));
              ChildDoc.setAttribute('CHEQUE_FIO_BOSS_STR', ChildDoc.parentNode.
                parentNode.getAttribute('CHEQUE_FIO_BOSS_STR'));
              ChildDoc.setAttribute('CHEQUE_BOSS_POST', ChildDoc.parentNode.
                parentNode.getAttribute('CHEQUE_BOSS_POST'));
              ChildDoc.setAttribute('CHEQUE_FIO_BUHGALT_STR', ChildDoc.parentNode.
                parentNode.getAttribute('CHEQUE_FIO_BUHGALT_STR'));
              ChildDoc.setAttribute('CHEQUE_BUHGALT_POST', ChildDoc.parentNode.
                parentNode.getAttribute('CHEQUE_BUHGALT_POST'));
              ChildDoc.setAttribute('AMOUNT', Doc.getAttribute('AMOUNT'));
              ChildDoc.setAttribute('KFSR_CODE', Doc.getAttribute('KFSR_CODE'));
              ChildDoc.setAttribute('KCSR_CODE', Doc.getAttribute('KCSR_CODE'));
              ChildDoc.setAttribute('KVR_CODE', Doc.getAttribute('KVR_CODE'));
              // exchange #3062 - копирование косгу при наличии
              ChildDoc.setAttribute('KESR_CODE', GetNodeAttributeEx( Doc, 'KESR_CODE'));
              ChildDoc.setAttribute('KADMR_CODE', Doc.getAttribute('KADMR_CODE'));
              ChildDoc.setAttribute('KDF_CODE', Doc.getAttribute('KDF_CODE'));
              ChildDoc.setAttribute('KDE_CODE', Doc.getAttribute('KDE_CODE'));
              ChildDoc.setAttribute('KDR_CODE', Doc.getAttribute('KDR_CODE'));
              ChildDoc.setAttribute('FSR_ID', Doc.getAttribute('FSR_ID'));
              ChildDoc.setAttribute('ANAL_KIND', Doc.getAttribute('ANAL_KIND'));
              ChildDoc.parentNode.parentNode.setAttribute('CODE_GRBS', ChildDoc.getAttribute('KADMR_CODE'));
              ChildDoc.setAttribute('ORG_GRBS', '');
              Kbk := QueryXml('Select Kl.* From Kadm_lines Kl Left Join kadm K on K.Id = Kl.master_id' +
                ' Where Kl.Budget_Id = ? and K.Code = ? order by Kl.Begin_Date desc',
                [ChildDoc.parentNode.parentNode.getAttribute('BUDGET_ID'),
                ChildDoc.getAttribute('KADMR_CODE')]);
              Kbk := Kbk.ChildNodes.Item[0];
              if Kbk.ChildNodes.Length = 1 then
                ChildDoc.setAttribute('ORG_GRBS', Kbk.ChildNodes.item[0].getAttribute('DESCRIPTION'))
              else begin
                for i := 0 to Kbk.ChildNodes.Length -1 do
                begin
                  Kbk := Kbk.ChildNodes.item[i];
                  if Kbk.getAttribute('END_DATE') = '' then
                    ChildDoc.setAttribute('ORG_GRBS', Kbk.getAttribute('DESCRIPTION'))
                  else if (Work_Date >= XmlToDateTime(Kbk.getAttribute('BEGIN_DATE'))) and
                    (Work_Date <= XmlToDateTime(Kbk.getAttribute('END_DATE'))) then
                    ChildDoc.setAttribute('ORG_GRBS', Kbk.getAttribute('DESCRIPTION'));
                  Kbk := Kbk.parentNode;
                end;
                if ChildDoc.getAttribute('ORG_GRBS') = '' then
                  ChildDoc.setAttribute('ORG_GRBS', Kbk.selectSingleNode('ROW').getAttribute('DESCRIPTION'));
              end;
              ChildDoc.setAttribute('PURPOSEFULGRANT_ID', Doc.getAttribute('PURPOSEFULGRANT_ID'));

    

              // exchange #2389 - расходы
              Exch2389_Update_PURPOSEFULGRANT_ID(
                    //ChildDoc.parentNode.parentNode,
                    ChildDoc,
                    '10',
                    ChildDoc.parentNode.parentNode.getAttribute('BUDGET_ID'),
                    'PURPOSEFULGRANT_ID',
                    ChildDoc.parentNode.parentNode.getAttribute('class'),
                    '');  // для расходов тип дохода не указывается

              ChildDoc.setAttribute('DIRECTION_ID', '');
              //1-Контролировать, 0-нет, 2-запрещать
              if isDirectionAutoFill(ChildDoc.parentNode.parentNode.getAttribute('BUDGET_ID')) and (isDirectionControl(ChildDoc.getAttribute('DOCUMENTCLASS_ID'),
                ChildDoc.parentNode.parentNode.getAttribute('EST_KIND')) <> '2') then
                ChildDoc.setAttribute('DIRECTION_ID', DirectionAutoFill(ChildDoc,
                  ChildDoc.parentNode.parentNode.getAttribute('BUDGET_ID')));
              ChildDoc := ChildDoc.parentNode;
              Doc := Doc.parentNode;
            end;
          end;
        end;
{      finally
      end;}
//      Doc := Doc.ownerDocument.documentElement;
//      ChildDoc := ChildDoc.ownerDocument;
      Result := True;

      except
        ExceptionProc( 'CreateChildDoc11');
    end;

end;
{==============================================================================}
{~CreateChildDoc25
//создает документ 25 класса на основе загруженного 24}
function CreateChildDoc25(Doc, ChildDoc: Variant): Boolean;
var
  MasterEstimateId, MasterOrgId, MasterAccountId, Est_Kind, PayDoc_Name,
  PayDoc_Number,PayDoc_Date, Payment_Name, Payment_Number, Payment_Date,
  Contract_Name, Contract_Number, Contract_Date: String;
  i: Integer;
  Permission, Line, PP, Contract, BO, Condebts: Variant;
  ParcingDesc: Boolean;
  isVBType: Boolean;
  xED24: Variant;
  xED25: Variant;
  xIgnoreEmpty_ORG_ID: boolean;
  xREC_ACC_ID: string;
  xVariantSearchExtimate: integer;
begin

    try
      Result := False;
      ParcingDesc := False;
      ChildDoc := ChildDoc.appendChild(ChildDoc.createElement('DOCUMENT'));
      ChildDoc.setAttribute('action', 'insert');
      ChildDoc.setAttribute('class', 25);
      ChildDoc.setAttribute('BUDGET_ID', Doc.getAttribute('F_BUDGET_ID'));
      ChildDoc.setAttribute('DOC_NUMBER', Doc.getAttribute('DOC_NUMBER'));
      ChildDoc.setAttribute('DOC_DATE', Doc.getAttribute('CARRY_DATE'));
      ChildDoc.setAttribute('OPERTYPE_ID', Doc.getAttribute('F_OPERTYPE_ID'));
      ChildDoc.setAttribute('DESCRIPTION', Doc.getAttribute('DESCRIPTION'));
      ChildDoc.setAttribute('FINANCE_FLAG', '0'); //Возвращать финасирование
      ChildDoc.setAttribute('ORGACCOUNT_ID', '');
      ChildDoc.setAttribute('ESTIMATE_ID', '');
      ChildDoc.setAttribute('AMOUNT', Doc.getAttribute('AMOUNT'));

      // exchange #2938
      // чтобы не лазить по родительским узлам когда формируются строки
      // в эд 25м, сохраняем ссылку на шапку эд 24го
      xED24 := Doc;
      // exchange #3057
      // сохраняем ссылку на xml эд 25го
      xED25 := ChildDoc;



      // exchange #2992
      // когда создается 25й из 24го и загрузка из файла IK,
      // то по exchange #2938 БР ищется по получателю, поэтому заполнение
      // получателя из выписки игнорируем.
      if (Doc.getAttribute('ORG_ID') = '') then begin
        //получатель из выписки
        if (not VarIsNull(Doc.getAttribute('F_SS')))
           and (StrToBool(Doc.getAttribute('F_SS')))
          then xIgnoreEmpty_ORG_ID := FALSE
          else
            if (Doc.getAttribute('F_ORIGINAL_TYPE') = 'IK')
              then xIgnoreEmpty_ORG_ID := TRUE
              else xIgnoreEmpty_ORG_ID := FALSE;

        if NOT xIgnoreEmpty_ORG_ID then begin
          WriteInfo('Не создан - не определен Id получателя из выписки');
          Exit;
        end;
      end;

      //получатель из выписки
      if (not VarIsNull(Doc.getAttribute('F_SS')))
        and (StrToBool(Doc.getAttribute('F_SS'))) then
      begin
        //заполнение данных по внебюджету
        //для выписки со счета ПБС и для информации ФО о нижестоящих Id счета известно
        //совпадает со счетом получателя
        if Doc.getAttribute('F_ORIGINAL_TYPE') in ['VP', 'IK'] then
          ChildDoc.setAttribute('ORGACCOUNT_ID', Doc.getAttribute('REC_ACC_ID'))
        else
          ChildDoc.setAttribute('ORGACCOUNT_ID', GetLicAccSs(Doc.getAttribute('ORG_ID'),
            IfThen(((Doc.getAttribute('F_ORIGINAL_TYPE') in ['IP', 'IV']) and
              (Doc.getAttribute('F_SHEMA') <> '1')), '5', '')));

        ChildDoc.setAttribute(
                          'ESTIMATE_ID',
                          GetEstimateIdSs( Doc.getAttribute('F_BUDGET_ID'),
                                           Doc.getAttribute('ORG_ID')));
      end
      else begin
        //для информации ФО о нижестоящих Id счета известно(совпадает со счетом получателя)
        if Doc.getAttribute('F_ORIGINAL_TYPE') = 'IK' then
          ChildDoc.setAttribute('ORGACCOUNT_ID', Doc.getAttribute('REC_ACC_ID'))
        else
          //Exchange #2007
          if (Doc.getAttribute('F_ORIGINAL_TYPE') = 'SP') and
            (not VarIsNull(Doc.getAttribute('KOD_DOC'))) then
            if (Doc.getAttribute('KOD_DOC') in ['VP', 'IV']) then
              ChildDoc.setAttribute('ORGACCOUNT_ID',
                GetLicAcc(Doc.getAttribute('ORG_ID'), '5'))
            else//здесь всегда KOD_DOC = VB(см.заполн.в SP) => ищем счет с типом 1
              ChildDoc.setAttribute('ORGACCOUNT_ID',
                GetLicAcc(Doc.getAttribute('ORG_ID')))
          else
            ChildDoc.setAttribute('ORGACCOUNT_ID', GetLicAcc(Doc.getAttribute('ORG_ID'),
              IfThen(((Doc.getAttribute('F_ORIGINAL_TYPE') in ['IP', 'IV'])
                and (Doc.getAttribute('F_SHEMA') <> '1')), '5', '')));


        // exchange #2938
        // для загрузки из IK ищем БР по новому, для прочих - по старому
        if (Doc.getAttribute('F_ORIGINAL_TYPE') <> 'IK')
          then ChildDoc.setAttribute(
                    'ESTIMATE_ID',
                    GetEstimateId( Doc.getAttribute('F_BUDGET_ID'),
                                   Doc.getAttribute('ORG_ID'),
                                   ChildDoc.getAttribute('ORGACCOUNT_ID'),
                                   Doc.ChildNodes.Item[0].ChildNodes.Item[0]))
          else begin
            // exchange #3057
            // Если тип счета получателя родительского ЭД имеет значение
            // «Лицевой счет в ФК» (5), то ищем БР по новому
            // пока предполагаем старый вариант поиска БР
            {
            xVariantSearchExtimate := 1;
            xREC_ACC_ID := GetNodeAttributeEx( Doc, 'REC_ACC_ID');
            if ( LENGTH( xREC_ACC_ID) > 0) then
              if (QueryField( ' select a.orgacctype_id X from orgaccount a'
                             +' where a.id=?',
                              [ xREC_ACC_ID],
                              'X') = '5')
                then xVariantSearchExtimate := 2;
            case xVariantSearchExtimate of
              1: if NOT FillEstimateIDintoED25fromED24byIKnew( ChildDoc, Doc)
                   then EXIT;
              2: if NOT FillEstimateIDintoED25fromED24byIK_3057( xED25, xED24)
                   then EXIT;
            end;//case//
            }
            // по дополнению АО пункт проверки типа счета убран и всегда
            // применяется алгоритм поиска БР по exchange #3057
            if NOT FillEstimateIDintoED25fromED24byIK_3057( xED25, xED24)
              then EXIT;
          end;
      end;



      if ChildDoc.getAttribute('ORGACCOUNT_ID') = '' then begin
        // exchange #2938
        // требуется поправить сообщение, поскольку БР ищется не по ORG_ID,
        // а по REC_ID
        if (Doc.getAttribute('F_ORIGINAL_TYPE') <> 'IK')
          then WriteInfo(
                  FORMAT( 'Не создан - не определен Id счета получателя (Org_Id = %s)',
                          [ Doc.getAttribute('ORG_ID')]))
          else WriteInfo(
                  FORMAT( 'Не создан - не определен Id счета получателя (REC_ID = %s)',
                          [ GetNodeAttributeEx( Doc, 'REC_ID')]));
        Exit;
      end;

      if ChildDoc.getAttribute('ESTIMATE_ID') = '' then begin
        // exchange #2938
        // требуется поправить сообщение, поскольку БР ищется не по ORG_ID,
        // а по REC_ID
        if (Doc.getAttribute('F_ORIGINAL_TYPE') <> 'IK') then begin
          WriteInfo(
                  FORMAT( 'Не создан - не определен Id бланка расходов получателя (Org_Id = %s)',
                          [ Doc.getAttribute('ORG_ID')]));
          EXIT;
        end else begin
          // exchange #3057
          // ФТ-1 п.4 эд 25й нужно создавать
          WriteInfo( 'Не определен Id бланка расходов получателя.');
          Est_Kind := '';
          //Exit;
        end;
      end else begin
        // exchange #3057 - проверяем БР
        //Определяем тип бланка расходов
        Est_Kind := 'EST_KIND'
                      + QueryField(
                            'Select EstKind_Id From Estimate Where Id = ?',
                            [ ChildDoc.getAttribute('ESTIMATE_ID')],
                            'ESTKIND_ID');
      end;
      ChildDoc.setAttribute('EST_KIND', Est_Kind);

      // exchange #2397
      // инициализация ЭД ПП
      PP := NULL;
      // Exchange#2219
      // алгоритм работает только при загрузке выписки VB
      // и включенном параметре авторазбора назначения платежа
      // производим разбор назначения платежа и поиск первичного документа
      isVBType := (Doc.getAttribute('F_ORIGINAL_TYPE') = 'VB');
      if (isVBType) and  StrToBool(Doc.getAttribute('F_SEARCH_BO')) then
      begin
        ParcingDesc := True;
        WriteLog('Поиск первичного документа в назначении платежа');
        // to do возможно переменные Payment_X не нужны
        ParceDescription(Doc.getAttribute('DESCRIPTION'), PayDoc_Name, PayDoc_Number,
          PayDoc_Date, Payment_Name, Payment_Number, Payment_Date, True);
        if (Trim(PayDoc_Name) = '') or (Trim(PayDoc_Number) = '') or (PayDoc_Date = '') then
          WriteInfo('Невозможно распознать реквизиты первичного документа в назначении платежа', True)
        else begin
          // проводим поиск по первичному документу, на основании которого проводится возврат
          if UpperCase(Trim(PayDoc_Name)) in ['ПП', 'П/П'] then
          begin
            PP := GetPpByDescription(PayDoc_Number, PayDoc_Date, Doc.getAttribute('F_BUDGET_ID'));
            if PP.documentElement.childNodes.Length <> 1 then
              WriteInfo('Не удалось однозначно определить платежное поручение, автоподстановка ' +
                ' первичного документа и бюджетного обязательства не производится')
            else begin
              WriteInfo('Найдено платежное поручение №' + PayDoc_Number + ' от ' +
                PayDoc_Date + ' сумма=' + PP.documentElement.childNodes.item[0].getAttribute('PP_AMOUNT'), True);
              ChildDoc.setAttribute('PAYDOC_DOCUMENT_ID', PP.documentElement.childNodes.item[0].getAttribute('PP_DOCUMENT_ID'));
              WriteLog('Поиск бюджетного обязательства в назначении платежа платежного поручения');
              ParceDescription(PP.documentElement.childNodes.item[0].getAttribute('PP_DESCRIPTION'), Contract_Name, Contract_Number,
                Contract_Date, Payment_Name, Payment_Number, Payment_Date);
              if (Trim(Contract_Name) = '') or (Trim(Contract_Number) = '') or (Contract_Date = '') then
                WriteInfo('Невозможно распознать реквизиты документа-основания в назначении платежа', True)
              else begin
                // проводим поиск по типу наименования договора
                Contract := GetContract(Contract_Name, Contract_Number, Contract_Date,
                  Doc.getAttribute('F_BUDGET_ID'));
                if Contract.documentElement.childNodes.Length <> 1 then
                  WriteInfo('Не удалось однозначно определить ЭД "Договор", автоподстановка ' +
                    ' бюджетного обязательства не производится')
                else
                  WriteInfo('Найден ЭД "Договор" №' + Contract_Number + ' от ' + Contract_Date, True);
              end;
            end;
          end
          else
            WriteInfo('В назначении платежа не удалось найти символы "ПП" или "П/П", автоподстановка ' +
              ' первичного документа и бюджетного обязательства не производится');
        end;
      end;
      ChildDoc := ChildDoc.appendChild(ChildDoc.ownerDocument.createElement('LINES'));
      //Exchange #1935. Устанавливаем галки возвращать финансирование
      //и возвращать на распорядительные бланки расходов в зависимости от галок в
      //сипарамах АЦК. Работает только для бюджета. Используемые параметры
      //backorder.face_account_back - Автоматически возвращать финансирование на ЛСФО
      //autobackfinance - Атоматически возвращать финансирование на распрядительные бланки расходов
      if (VarIsNull(Doc.getAttribute('F_SS')) or (not StrToBool(Doc.getAttribute('F_SS'))))
        and (IsSysparamOn('backorder.face_account_back')) then
      begin
        //Возвращать финасирование распорядителю
        ChildDoc.parentNode.setAttribute('FINANCE_FLAG', '1');
        if IsSysparamOn('autobackfinance') then
        begin
          GetMasterId(Doc.getAttribute('F_BUDGET_ID'),
            ChildDoc.parentNode.getAttribute('ESTIMATE_ID'), MasterEstimateId, MasterOrgId);
          //Проверка: бланк расходов под распорядителем?
          if MasterEstimateId <> '' then
            //Проверка: распорядитель не ФО?
            if MasterEstimateId <> GetOrgIdByBudgetId(Doc.getAttribute('F_BUDGET_ID')) then
            begin
              MasterAccountId := GetMasterAccID(MasterOrgId);
              if MasterAccountId <> '' then
              begin
                ChildDoc := ChildDoc.parentNode.appendChild(ChildDoc.ownerDocument.createElement('BACKROUTES'));
                ChildDoc := ChildDoc.appendChild(ChildDoc.ownerDocument.createElement('BACKROUTE'));
                ChildDoc.setAttribute('ESTIMATE_ID', MasterEstimateId);
                ChildDoc.setAttribute('ORGACCOUNT_ID', MasterAccountId);
                ChildDoc := ChildDoc.ownerDocument.documentElement.childNodes.Item[0];
              end;
            end;
        end;
      end;
      //для 25 класса по спец средствам алгоритм заполнения строк другой.
      if (not VarIsNull(Doc.getAttribute('F_SS')))
        and (StrToBool(Doc.getAttribute('F_SS'))) then
      begin
        if ParcingDesc then
        begin
          // чтобы не передавать кучу параметров, запишим их в xml
          if Contract.documentElement.childNodes.Length = 1 then
          begin
            Contract.documentElement.childNodes.item[0].setAttribute('PAYMENT_NAME', Payment_Name);
            Contract.documentElement.childNodes.item[0].setAttribute('PAYMENT_NUMBER', Payment_Name);
            Contract.documentElement.childNodes.item[0].setAttribute('PAYMENT_DATE', Payment_Name);
          end;
          Result := CreateChildDoc25SS(Doc, ChildDoc, PP, Contract, ParcingDesc);
          Exit;
        end
        else begin
        Result := CreateChildDoc25SS(Doc, ChildDoc);
        Exit;
      end;
      end;
      Doc := Doc.ChildNodes.Item[0];

      for i := 0 to Doc.childNodes.Length - 1 do
      begin
        Doc := Doc.ChildNodes.Item[i];
        ChildDoc := ChildDoc.appendChild(ChildDoc.ownerDocument.createElement('LINE'));

        //Exchange #1927
        if (Doc.parentNode.parentNode.getAttribute('F_ORIGINAL_TYPE') in ['IK', 'VB', 'IP', 'IV'])
          and (not CheckAccOnPermission(ChildDoc.parentNode.parentNode)) then
        begin

          //ищем разрешение и его строку по расходной классифкации.
          Permission := GetPermissionRash(ChildDoc.parentNode.parentNode, Doc);
          if VarIsNull(Permission) then
            //Ищем разрешение с учетом групп по бухгалтерии
            Permission := GetPermissionRashUseGroupBuh(ChildDoc.parentNode.parentNode, Doc);

          if not VarIsNull(Permission) then begin
            ChildDoc.setAttribute('PERMISSIONLINE_ID', Permission.getAttribute('PERMISSIONLINE_ID'));
            ChildDoc.setAttribute('FUNDSOURCE_ID', Permission.getAttribute('FUNDSOURCE_ID'));
          end;
        end;

        if not varIsNull(ChildDoc.parentNode.parentNode.getAttribute('PAYDOC_DOCUMENT_ID')) then
        begin
        ChildDoc.setAttribute('PAYDOC_DOCUMENT_ID',
          ChildDoc.parentNode.parentNode.getAttribute('PAYDOC_DOCUMENT_ID'));
        end;

        // exchange #2340
        // обязательно нужно заполнить это поле, иначе это приведет к сбою
        // ниже (вызов isDirectionControl)
        ChildDoc.setAttribute('DOCUMENTCLASS_ID',
          ChildDoc.parentNode.parentNode.getAttribute('class'));
        ChildDoc.setAttribute('RECIPIENT_ID',
          Doc.parentNode.parentNode.getAttribute('ORG_ID'));
        ChildDoc.setAttribute('ESTIMATE_ID',
          ChildDoc.parentNode.parentNode.getAttribute('ESTIMATE_ID'));
        ChildDoc.setAttribute('ORGACCOUNT_ID',
          ChildDoc.parentNode.parentNode.getAttribute('ORGACCOUNT_ID'));
        ChildDoc.setAttribute('KFSR_CODE', Doc.getAttribute('KFSR_CODE'));
        ChildDoc.setAttribute('KCSR_CODE', Doc.getAttribute('KCSR_CODE'));
        ChildDoc.setAttribute('KVR_CODE', Doc.getAttribute('KVR_CODE'));
        // exchange #3062 - отмена косгу
        // exchange #3111 - но его нужно тянуть, если он есть
        ChildDoc.setAttribute('KESR_CODE', GetNodeAttributeEx( Doc, 'KESR_CODE'));
        ChildDoc.setAttribute('KADMR_CODE', Doc.getAttribute('KADMR_CODE'));
        ChildDoc.setAttribute('FSR_ID', Doc.getAttribute('FSR_ID'));
        ChildDoc.setAttribute('KDF_CODE', Doc.getAttribute('KDF_CODE'));
        ChildDoc.setAttribute('KDE_CODE', Doc.getAttribute('KDE_CODE'));
        ChildDoc.setAttribute('KDR_CODE', Doc.getAttribute('KDR_CODE'));
        ChildDoc.setAttribute('ANAL_KIND', Doc.getAttribute('ANAL_KIND'));

        ChildDoc.setAttribute( 'PURPOSEFULGRANT_ID',
                               GetNodeAttributeEx( Doc, 'PURPOSEFULGRANT_ID'));

    

        ChildDoc.setAttribute('AMOUNT', Doc.getAttribute('AMOUNT'));
        // Exchange#2219 - алгоритм работает только при загрузке выписки VB,
        // включенном параметре авторазбора назначения платежа
        // производим поиск строки в рчб
        if isVBType then
        begin
          Line := GetLineExpbudget(ChildDoc, Doc.parentNode.parentNode.getAttribute('F_BUDGET_ID'));
          if Line.documentElement.childNodes.Length = 1 then
          begin
            Line := Line.documentElement.childNodes.item[0];
            ChildDoc.setAttribute('KDF_CODE', Line.getAttribute('KDF_CODE'));
            ChildDoc.setAttribute('KDE_CODE', Line.getAttribute('KDE_CODE'));
            ChildDoc.setAttribute('KDR_CODE', Line.getAttribute('KDR_CODE'));
            // exchange #3111 - заполняем код из рчб
            ChildDoc.setAttribute( 'KESR_CODE',
                                   GetNodeAttributeEx( Line, 'KESR_CODE'));
          end;
          if Contract.documentElement.childNodes.Length = 1 then
          begin
            // проводим поиск БО на основании строки кбк и ранее найденного договора
            BO := GetBoByContractAndKBK(Contract.documentElement.childNodes.Item[0], ChildDoc);
            if BO.documentElement.childNodes.Length = 1 then
            begin
              BO := BO.documentElement.childNodes.Item[0];
              ChildDoc.setAttribute('BUDGORDER_ID', BO.getAttribute('ID'));
              // проставляем ссылку на БО в шапку документа только в однострочных ЭД
              if Doc.parentNode.childNodes.Length = 1 then
                ChildDoc.parentNode.parentNode.setAttribute('BUDGORDER_ID',
                  ChildDoc.getAttribute('BUDGORDER_ID'));
            end
            else
              WriteLog('Не найдено бюджетное обязательство для строки');
            // если стоит галка "Оплата в разрезе выставленых счетов" проводим поиск выставленного счета
            if Contract.documentElement.childNodes.Item[0].getAttribute('PAYABLE') = 1 then
            begin
              if (Payment_Name <> '') and (Payment_Number <> '') and (Payment_Date <> '') then
              begin
                Condebts := GetCondebts(Payment_Name, Payment_Number, Payment_Date,
                  Contract.documentElement.childNodes.Item[0].getAttribute('ID'));
                if Condebts.documentElement.childNodes.Length = 1 then
                begin
                  Condebts := Condebts.documentElement.childNodes.Item[0];
                  ChildDoc.setAttribute('CONDEBTS_ID', Condebts.getAttribute('ID'));
                  if Condebts.getAttribute('ADVMARK') = 1 then
                    ChildDoc.setAttribute('ADVPAYMENT', 1)
                  else
                    ChildDoc.setAttribute('ADVPAYMENT', 0);
                end else
                  WriteLog('Не найден выставленный счет для строки');
              end else
                WriteLog('В назначении платежа невозможно определить выставленный счет');
            end;
          end;
          // проводим проверку строки 25 класса и строки ЗОР найденного ПП
          // exchange #2397
          // не всегда создается ЭД ПП, поэтому проверяем описание ЭД ПП
          if NOT VarIsNull( PP) then
            if PP.documentElement.childNodes.Length = 1 then
            begin
              if not CheckLineFor25Class(ChildDoc, PP.documentElement.childNodes.item[0]) then
                WriteInfo('Строка в ЭД "Уведомление о возврате средств" не соответствует' +
                  ' строке в ЭД "ЗОР"');
            end;
        end;

        // exchange #2938
        // только для загрузки из IK файла
        if (xED24.getAttribute('F_ORIGINAL_TYPE') = 'IK') then
          // проверяем параметр конфига:
          // "Схема загрузки доп кодов из поля ADD_KLASS" из шапки эд 24го
          // exchange #3057
          // только для значения параметра «Схема загрузки доп кодов
          // из ADD_KLASS» = нет (пусто)
          // реализовано через глобальную переменную.
          if ( LENGTH( vCfg_LoadDopKD_from_ADD_KLASS) <= 0) then begin
{          if (VarToStr( xED24.GetAttribute( '__CfgShemaLoadDopKbk__')) = '')
            then begin}

              // exchange #3057
              GetLineExpbudget_3057( xED25, ChildDoc, xED24, Doc);
              {
              end else begin
                // необходимо подгрузить доп коды из РЧБ.
                // не забываем что по новому алгоритму поиска БР, организация
                // оператор в БР не ORG_ID, а получатель - REC_ID!
                ChildDoc.SetAttribute( 'RECIPIENT_ID',
                                       GetNodeAttributeEx( xED24, 'REC_ID'));
                Line := GetLineExpbudget( ChildDoc,
                                          GetNodeAttributeEx( xED24, 'F_BUDGET_ID'));
                if (Line.documentElement.childNodes.Length = 1) then begin
                  Line := Line.documentElement.childNodes.item[0];
                  ChildDoc.setAttribute('KDF_CODE', Line.getAttribute('KDF_CODE'));
                  ChildDoc.setAttribute('KDE_CODE', Line.getAttribute('KDE_CODE'));
                  ChildDoc.setAttribute('KDR_CODE', Line.getAttribute('KDR_CODE'));
                end;
              end;
              }
            end;

        // exchange #2389 - расходы
        Exch2389_Update_PURPOSEFULGRANT_ID(
    //          ChildDoc.parentNode.parentNode,
              ChildDoc,
              '10',
              ChildDoc.parentNode.parentNode.getAttribute('BUDGET_ID'),
              'PURPOSEFULGRANT_ID',
              ChildDoc.parentNode.parentNode.getAttribute('class'),
              '');     // тип дохода заполнять необязательно


        // exchange #2921
        // поле код цели нужно заполнять перед заполнением поля РО
        ChildDoc.setAttribute('DIRECTION_ID', '');
        //1-Контролировать, 0-нет, 2-запрещать
        if isDirectionAutoFill(ChildDoc.parentNode.parentNode.getAttribute('BUDGET_ID')) and (isDirectionControl(ChildDoc.getAttribute('DOCUMENTCLASS_ID'),
          ChildDoc.parentNode.parentNode.getAttribute('EST_KIND')) <> '2') then
          ChildDoc.setAttribute('DIRECTION_ID', DirectionAutoFill(ChildDoc,
            ChildDoc.parentNode.parentNode.getAttribute('BUDGET_ID')));


        ChildDoc := ChildDoc.parentNode;
        Doc := Doc.parentNode;
      end;

      Doc := Doc.ownerDocument.documentElement;
      ChildDoc := ChildDoc.ownerDocument;

      Result := True;
      except
        ExceptionProc( 'Un_Import.CreateChildDoc25');
    end;

end;
{==============================================================================}
//создает документ 25 класса по внебюджету на основе загруженного 24
function CreateChildDoc25SS(Doc, ChildDoc: Variant; PP, Contract: Variant = Null;
  ParcingDesc: Boolean = False): Boolean;
var
  i: Integer;
  Permission, HeadChildDoc, Line, BO, Condebts: Variant;
  Est_Kind: String;
begin

    try
      Result := False;
      //заполняем строки 25 класса по внебюджету.
      HeadChildDoc := ChildDoc.ownerDocument.documentElement;
      if (not VarIsNull(Doc.getAttribute('RULE_1621'))) and
        (StrToBool(Doc.getAttribute('RULE_1621'))) then
      begin
        //алгоритм создания 25 класса по внебюджету по правилу в Exchange #1621
        //ищем ПП
        if Rule1621_getIdPp(Doc) = '' then
        begin
          WriteInfo('Не создан - не найдено платежное поручение');
          Exit;
        end;
      end;
      //Определяем тип бланка расходов
      Est_Kind := 'EST_KIND' + QueryField('Select EstKind_Id From Estimate Where Id = ?',
        [HeadChildDoc.getAttribute('ESTIMATE_ID')], 'ESTKIND_ID');
      Doc := Doc.ChildNodes.Item[0];
      for i := 0 to Doc.childNodes.Length - 1 do
      begin
        Doc := Doc.childNodes.Item[i];
        //ищем разрешение и его строку по расходной классифкации.
        Permission := GetPermissionRash(HeadChildDoc, Doc);
        if VarIsNull(Permission) then
        begin
          //Exchange #1997
          if (not VarIsNull(Doc.parentNode.parentNode.getAttribute('USEGROUPBUH25')))
            and (StrToBool(Doc.parentNode.parentNode.getAttribute('USEGROUPBUH25'))) then
          begin
            //Ищем разрешение с учетом групп по бухгалтерии
            Permission := GetPermissionRashUseGroupBuh(HeadChildDoc, Doc);
            if VarIsNull(Permission) then
            begin
              WriteInfo('Не создан - не определено разрешение на открытие лс');
              Doc := Doc.parentNode.parentNode;
              Exit;
            end;
          end
          else begin
            WriteInfo('Не создан - не определено разрешение на открытие лс');
            Doc := Doc.parentNode.parentNode;
            Exit;
          end;
        end;
        ChildDoc := ChildDoc.appendChild(ChildDoc.ownerDocument.createElement('LINE'));
        ChildDoc.setAttribute('RECIPIENT_ID', Permission.getAttribute('RECIPIENT_ID'));
        ChildDoc.setAttribute('ESTIMATE_ID', HeadChildDoc.getAttribute('ESTIMATE_ID'));
        ChildDoc.setAttribute('ORGACCOUNT_ID', HeadChildDoc.getAttribute('ORGACCOUNT_ID'));
        if not varIsNull(HeadChildDoc.getAttribute('PAYDOC_DOCUMENT_ID')) then
        begin
          ChildDoc.setAttribute('PAYDOC_DOCUMENT_ID',
            HeadChildDoc.getAttribute('PAYDOC_DOCUMENT_ID'));
          ChildDoc.setAttribute('DOCUMENTCLASS_ID',
            ChildDoc.parentNode.parentNode.getAttribute('class'));
        end;
        ChildDoc.setAttribute('KFSR_CODE', Doc.getAttribute('KFSR_CODE'));
        ChildDoc.setAttribute('KCSR_CODE', Doc.getAttribute('KCSR_CODE'));
        ChildDoc.setAttribute('KVR_CODE', Doc.getAttribute('KVR_CODE'));
        // exchange #3062 - копирование косгу при наличие
        ChildDoc.setAttribute('KESR_CODE', GetNodeAttributeEx( Doc, 'KESR_CODE'));
        ChildDoc.setAttribute('KADMR_CODE', Doc.getAttribute('KADMR_CODE'));
        ChildDoc.setAttribute('FSR_ID', Permission.getAttribute('FSR_ID'));
        ChildDoc.setAttribute('KDF_CODE', Permission.getAttribute('KDF_CODE'));
        ChildDoc.setAttribute('KDE_CODE', Permission.getAttribute('KDE_CODE'));
        ChildDoc.setAttribute('KDR_CODE', Permission.getAttribute('KDR_CODE'));
        ChildDoc.setAttribute('ANAL_KIND', Doc.getAttribute('ANAL_KIND'));
        ChildDoc.setAttribute('PURPOSEFULGRANT_ID', Doc.getAttribute('PURPOSEFULGRANT_ID'));

    

        ChildDoc.setAttribute('PERMISSIONLINE_ID',
          Permission.getAttribute('PERMISSIONLINE_ID'));
        ChildDoc.setAttribute('FUNDSOURCE_ID', Permission.getAttribute('FUNDSOURCE_ID'));
        ChildDoc.setAttribute('AMOUNT', Doc.getAttribute('AMOUNT'));
        // Exchange#2219 - алгоритм работает только при загрузке выписки VB,
        // включенном параметре авторазбора назначения платежа
        // производим поиск строки в рчб
        if ParcingDesc then
        begin
          Line := GetLineExpbudget(ChildDoc, Doc.parentNode.parentNode.getAttribute('F_BUDGET_ID'));
          if Line.documentElement.childNodes.Length = 1 then
          begin
            Line := Line.documentElement.childNodes.item[0];
            ChildDoc.setAttribute('KDF_CODE', Line.getAttribute('KDF_CODE'));
            ChildDoc.setAttribute('KDE_CODE', Line.getAttribute('KDE_CODE'));
            ChildDoc.setAttribute('KDR_CODE', Line.getAttribute('KDR_CODE'));
            // exchange #3111 - переносим косгу из рчб
            ChildDoc.setAttribute('KESR_CODE', Line.getAttribute('KESR_CODE'));
          end;
          if Contract.documentElement.childNodes.Length = 1 then
          begin
            Contract := Contract.documentElement.childNodes.item[0];
            // проводим поиск БО на основании строки кбк и ранее найденного договора
            BO := GetBoByContractAndKBK(Contract, ChildDoc);
            if BO.documentElement.childNodes.Length = 1 then
            begin
              BO := BO.documentElement.childNodes.Item[0];
              ChildDoc.setAttribute('BUDGORDER_ID', BO.getAttribute('ID'));
              // проставляем ссылку на БО в шапку документа только в однострочных ЭД
              if Doc.parentNode.childNodes.Length = 1 then
                ChildDoc.parentNode.parentNode.setAttribute('BUDGORDER_ID',
                  ChildDoc.getAttribute('BUDGORDER_ID'));
            end
            else
              WriteLog('Не найдено бюджетное обязательство для строки');
            // если стоит галка "Оплата в разрезе выставленых счетов" проводим поиск выставленного счета
            if Contract.getAttribute('PAYABLE') = 1 then
            begin
              if (Contract.getAttribute('PAYMENT_NAME') <> '') and
                (Contract.getAttribute('PAYMENT_NUMBER') <> '') and
                (Contract.getAttribute('PAYMENT_DATE') <> '') then
              begin
                Condebts := GetCondebts(Contract.getAttribute('PAYMENT_NAME'),
                  Contract.getAttribute('PAYMENT_NUMBER'), Contract.getAttribute('PAYMENT_DATE'),
                  Contract.getAttribute('ID'));
                if Condebts.documentElement.childNodes.Length = 1 then
                begin
                  Condebts := Condebts.documentElement.childNodes.Item[0];
                  ChildDoc.setAttribute('CONDEBTS_ID', Condebts.getAttribute('ID'));
                  if Condebts.getAttribute('ADVMARK') = 1 then
                    ChildDoc.setAttribute('ADVPAYMENT', 1)
                  else
                    ChildDoc.setAttribute('ADVPAYMENT', 0);
                end else
                  WriteLog('Не найден выставленный счет для строки');
              end else
                WriteLog('В назначении платежа невозможно определить выставленный счет');
            end;
          end;
          // проводим проверку строки 25 класса и строки ЗОР найденного ПП
          if PP.documentElement.childNodes.Length = 1 then
          begin
            if not CheckLineFor25Class(ChildDoc, PP.documentElement.childNodes.item[0]) then
              WriteInfo('Строка в ЭД "Уведомление о возврате средств" не соответствует' +
                ' строке в ЭД "ЗОР"');
          end;
        end;

        // exchange #2389 - расходы
        Exch2389_Update_PURPOSEFULGRANT_ID(
                  //ChildDoc.parentNode.parentNode,
                  ChildDoc,
                  '10',
                  ChildDoc.parentNode.parentNode.getAttribute('BUDGET_ID'),
                  'PURPOSEFULGRANT_ID',
                  ChildDoc.parentNode.parentNode.getAttribute('class'),
                  '');  // для расходов тип дохода не указывается

        // exchange #2921
        // поле код цели нужно заполнять перед заполнением поля РО
        ChildDoc.setAttribute('DIRECTION_ID', '');
        //1-Контролировать, 0-нет, 2-запрещать
        if isDirectionAutoFill(ChildDoc.parentNode.parentNode.getAttribute('BUDGET_ID')) and (isDirectionControl(ChildDoc.getAttribute('DOCUMENTCLASS_ID'),
          ChildDoc.parentNode.parentNode.getAttribute('EST_KIND')) <> '2') then
          ChildDoc.setAttribute('DIRECTION_ID', DirectionAutoFill(ChildDoc,
            ChildDoc.parentNode.parentNode.getAttribute('BUDGET_ID')));

        ChildDoc := ChildDoc.parentNode;
        Doc := Doc.parentNode;
      end;
      Doc := Doc.parentNode;
      ChildDoc := ChildDoc.parentNode;

      Result := True;
      except
        ExceptionProc( 'CreateChildDoc25SS');
    end;

end;

procedure SplitClass74ByOrgId(NewDoc: Variant);
var
  i, j: Integer;
  List, Node, Lines: Variant;
  Amount: Currency;
begin
  List := NewDoc.selectNodes('.//DOCUMENT_74');
  for i := 0 to List.length - 1 do
  begin
    Node := List.item[i].firstChild.firstChild;
    List.item[i].firstChild.setAttribute('AMOUNT', 0.00);
    while Node.childNodes.length > 0 do
    begin
      Lines := Node.selectNodes('./PAYORDERLINE[@ORG_ID=' +
        Node.childNodes.item[0].getAttribute('ORG_ID') + ']');
      Node.parentNode.setAttribute('AMOUNT', 0);
      with NewDoc.appendChild(List.item[i].cloneNode(false)).
        appendChild(List.item[i].firstChild.cloneNode(false)).
        appendChild(List.item[i].firstChild.firstChild.cloneNode(false)) do
      for j := 0 to Lines.length - 1 do
      begin
        Amount := StrToCurr(parentNode.getAttribute('AMOUNT'));
        parentNode.setAttribute('AMOUNT', Amount + StrToCurr(Lines.item[j].getAttribute('AMOUNT')));
        parentNode.setAttribute('ORG_ID', Lines.item[j].getAttribute('ORG_ID'));
        appendChild(Lines.item[j].cloneNode(false));
        Node.removeChild(Lines.item[j]);
      end;
    end;
    NewDoc.removeChild(List.item[i]);
  end;
end;

//Разделяет n-строчный документ 74 класса на n однострочных.
procedure SplitClass74ByLine(NewDoc: Variant; Flag: Boolean = False);
var
  List, Node, Lines: Variant;
  i: Integer;
begin
  List := NewDoc.selectNodes('.//DOCUMENT_74');
  //стоит параметр разбивать 24 класс.
  for i := 0 to List.length - 1 do
  begin
    Node := List.item[i].firstChild.firstChild;
    while Node.childNodes.length > 1 do
    begin
      Lines := Node.selectNodes('.//PAYORDERLINE');
      //записываем сумму первой строки в шапку документа перед клонировнием
      List.item[i].firstChild.setAttribute('AMOUNT',
        Lines.item[0].getAttribute('AMOUNT'));
      //для Читы переносим org_id из строки в шапку документа
      if Flag then
        //записываем Id организации из первой строки в шапку документа перед клонировнием
        List.item[i].firstChild.setAttribute('ORG_ID',
          Lines.item[0].getAttribute('ORG_ID'));
      NewDoc.appendChild(List.item[i].cloneNode(false)).
        appendChild(List.item[i].firstChild.cloneNode(false)).
        appendChild(List.item[i].firstChild.firstChild.cloneNode(false)).
        appendChild(Lines.item[0].cloneNode(false));
      Node.removeChild(Lines.item[0]);
    end;
    //выравниваем сумму для оставшейся строки
    Lines := Node.selectNodes('.//PAYORDERLINE');
    Node.parentNode.setAttribute('AMOUNT', Lines.item[0].getAttribute('AMOUNT'));
    //выравниваем id организации для оставшейся строки
    if Flag then
      Node.parentNode.setAttribute('ORG_ID', Lines.item[0].getAttribute('ORG_ID'));
  end;
end;


{~FillGrantinvestmentIntoLine
  exchange #2926
  заполнение кода субсидии (по коду aCode) и кода цели в строке aLineTo.
  код цели заполняется нулевым значением.
  результат:
    =true - код субсидии определен;
    =false - код субсидии (aCode) не указан или не найден в бд.

  используется при загрузке VK и IK для нового алгоритма (по BDPB #2600).
  код субсидии нужно брать из поля BDPDST.ADD_KLASS.
    если BDPDST.ADD_KLASS пусто - поле не заполнять.

  exchange #2979
  добавлен параметр: aOrgID и aOrgID_Obligatory.
    если aOrgID не равен пустой строки, то:
  поиск кода субсидии в справочнике «Коды субсидий» осуществлять
  с учетом этого параметра (учредитель=aOrgID).
  Если код в структурированном файле указан, но не найден в справочнике,
  то ЭД класса 24 формировать с нулевым значением поля,
  в журнале загрузки отражать соответствующее сообщение.
    если aOrgID равен пустой строке, то:
    если aOrgID_Obligatory=false - то параметр aOrgID не учитывается.
    если aOrgID_Obligatory=true - то в журнал пишется сообщение aMsg,
    а код субсидии подставляется =0, и результат функции =true

  ацк-ф 21918
    добавлено название поля (aFieldName) отр кода.
    это дает возможность заполнять его как для бюджетной, так и для
    аналит. строки эд.
    aFillPURPOSEFULGRANT определяет необходимость чистки полей кода цели
    бюджетной строки:
      =true - чистятся,
      =false - не чистятся.

  результат:
    1 - код подставлен =0 для случая:
         если aOrgID равен пустой строке и если aOrgID_Obligatory=true.
    0 - код найден
   -1 - код aCode не указан
   -2 - код не найден
   -3 - найдено несколько кодов
   прочее - неопределенная ошибка}
function FillGrantinvestmentIntoLine( aBudgetID, aCode: string;
                                      aLineTo: Variant;
                                      aOrgID: string = '';
                                      aOrgID_Obligatory: boolean = FALSE;
                                      aMsg: string = '';
                                      aFieldName: string = '';
                                      aFillPURPOSEFULGRANT: boolean = TRUE): integer;
var
  xPURPOSEFULGRANT_FieldName: string;
  xCode: string;
  xFound: string;
begin

    try
      // поскольку ищем код субсидии, поле кода цели заполняем системным нулем
      if aFillPURPOSEFULGRANT then begin
        case GetNodeAttributeEx( aLineTo, 'ANAL_KIND') of
          '0': xPURPOSEFULGRANT_FieldName := 'PURPOSEFULGRANT_ID';
          '1': xPURPOSEFULGRANT_FieldName := 'PURPOSEFULGRANTD_ID';
          '2': xPURPOSEFULGRANT_FieldName := 'PURPOSEFULGRANTI_ID';
          // на случай отладки
          else xPURPOSEFULGRANT_FieldName := 'PURPOSEFULGRANT_ID';
        end;//case//
        aLineTo.SetAttribute( xPURPOSEFULGRANT_FieldName,
                              GetPurposeFulgrantId( aBudgetID, '0'));
      end;

      xCode := TRIM( aCode);
      if (LENGTH( xCode) <= 0)
        then Result := -1        // код не указан
        else begin
          if (LENGTH( aOrgID) <= 0) then begin
            if aOrgID_Obligatory then begin
              // если код орг должен быть, а его нет
              // заполнение кода субсидии нулевым кодом
              aLineTo.SetAttribute( aFieldName, //'GRANTINVESTMENT_ID',
                                    SearchUnicalGrantinvestmentCodeNull( aBudgetID));
              WriteInfo( aMsg);
              Result := 1;
              EXIT;
            end;

            xFound := QueryField(  'Select count( * ) N From GrantInvestment G'
                                  +' Where G.Budget_Id = ? and G.Code = ?',
                                   [ aBudgetID,
                                     xCode],
                                   'N');
            if (xFound = '1') then begin
              aLineTo.SetAttribute(
                          aFieldName, //'GRANTINVESTMENT_ID',
                          QueryField(  'Select G.ID From GrantInvestment G'
                                      +' Where G.Budget_Id = ? and G.Code = ?',
                                       [ aBudgetID,
                                         xCode],
                                       'ID'));
              Result := 0;
              EXIT;
            end;
          end else begin
            xFound := QueryField(  'Select count( * ) N From GrantInvestment G'
                                  +' Where G.Budget_Id = ? and G.Code = ?'
                                  +' and G.ORG_ID=?',
                                   [ aBudgetID,
                                     xCode,
                                     aOrgID],
                                   'N');
            if (xFound = '1') then begin
              aLineTo.SetAttribute(
                          aFieldName, //'GRANTINVESTMENT_ID',
                          QueryField(  'Select G.ID From GrantInvestment G'
                                      +' Where G.Budget_Id = ? and G.Code = ?'
                                      +' and G.ORG_ID=?',
                                       [ aBudgetID,
                                         xCode,
                                         aOrgID],
                                       'ID'));
              Result := 0;
              EXIT;
            end;
          end;

          // результат поиска кода в бд - сколько найдено
          if (xFound = '0')
            then Result := -2    // ни одного
            else Result := -3;    // несколько
        end;

      // заполнение кода субсидии нулевым кодом
      aLineTo.SetAttribute( aFieldName, //'GRANTINVESTMENT_ID',
                            SearchUnicalGrantinvestmentCodeNull( aBudgetID));
      except
        ExceptionLog( 'Сбой FillGrantinvestmentIntoLine');
    end;

end;



{~CreateDoc_194_195_by_ik_Ex
  exchange #2952
  создание эд 194/195 aXmlDoc c возможностью создания эд 5го (aCfgCreateDoc5).
  aProblemIntoLines2952 - флаг проблем в эд.
  aCfg_CreateParamAUBU - значение параметра конфига
  «Заменять значение аналитического кода АУ/БУ в строке на 0 при отсутствии
  в справочнике»

  проверяется aProblemIntoLines2952
     если =false - эд создается по старому (с доведением до статуса 86 и
                    созданием эд 5го)
     если =false то проверяется параметр aCfg_CreateParamAUBU.

  aCreateED193 - учитывается ФТ-4 (загрузка по IK.ZR)
    при этом вместо эд 5го создается эд 193й.

  exchange #2945
  добавлено задание расширенный параметров (aExtParams).
  это дает возможность управлять созданием эд в функции Exec_ChildDoc.}
procedure CreateDoc_194_195_by_IK_Ex( aBudgetID: string;
                                      aXmlDoc: variant;
                                      aCfgCreateDoc5: boolean;
                                      aProblemIntoLines2952: boolean;
                                      aCfg_CreateParamAUBU: string;
                                      aCreateED193: boolean = FALSE;
                                      aExtParams: string = '');
var
  xExtParam: string;
begin

    try
      xExtParam := aExtParams;

      // если создается 193й, то эд 5го не создаем, а вместо него указываем
      // создание 193го через строку дополнительного режима обработки
      // создаваемого эд.
      if aCreateED193 then begin
        aCfgCreateDoc5 := FALSE;
        xExtParam := TRIM( xExtParam + #13#10'Create193=1');
      end;

      if NOT aProblemIntoLines2952
        then Exec_ChildDoc( aBudgetID, '', aXmlDoc, TRUE, aCfgCreateDoc5, xExtParam)
        else
          case LOWERCASE( aCfg_CreateParamAUBU) of
            // создается без обработки
            'да, не обрабатывать': begin
                   WriteInfo( 'ЭД заполнен некорректно - будет создан без обработки.');
                   if aCfgCreateDoc5
                     then WriteInfo( 'ЭД "Приложение к выписке дебетовое" не будет создан.');
                   if aCreateED193
                     then WriteInfo( 'ЭД "Распоряжение на зачисление средств на лицевой счет" не будет создан.');
                   Exec_ChildDoc( aBudgetID, '', aXmlDoc);
                   EXIT;
                 end;

            // не создавать эд
            'нет': begin
                   WriteInfo( 'ЭД заполнен некорректно - не будет создан по настройке конфигурации.');
                   EXIT;
                 end;

            // да, обрабатывать (или прочее)
            // создается с полной обработкой, но в журнале помечаем,
            // что могут быть проблемы
            else begin
                  WriteInfo( 'ЭД заполнен некорректно - будет создан с обработкой.');
                  Exec_ChildDoc( aBudgetID, '', aXmlDoc, TRUE, aCfgCreateDoc5, xExtParam);
                end;
          end;//case//
      except
        ExceptionProc( 'CreateDoc_194_195_by_IK_Ex');
    end;

end;




(*
{~GetEstimateIdForED215
  поиск бланка расходов по орг, и счету + кбк (без кода цели).
  алгоритм применяется для формирвания ЭД 215х
  (exchange #2353 + exchange #2960)
  здесь несколько отличный поиск БР в справочнике.
  за основу взят алгоритм exchange #2353.
  результат:
    пустая строка или id.БР}
function GetEstimateIdForED215( aBudgetId, aOrg_Id, aAccount: String;
                                aLine: Variant): String;
var
  xXml: Variant;
  xSQL: string;
begin

    try
      Result := '';

      // поиск БР в справочнике БР
      if (LENGTH( aAccount) <= 0) then begin
        xSQL :=  ' Select distinct e.Id From Estimate e'
                +' Where e.EstKind_Id in (1, 7) and e.Actual_Flag = 1'
                +' and e.Budget_Id = ? and e.Org_Id = ?';
        xXml := QueryXml( xSQL,
                         [ aBudgetId,
                            aOrg_Id]);

        // здесь проверяем, если не найдено ни одной записи, то бланк расходов
        // считаем не найденным. если нашли несколько БР - ищем в РЧБ.
        // причем только среди тех, которые нашлись в справочнике (см. выше).
        if (xXml.documentElement.childNodes.Length > 1)
          then xXml := QueryXml( 'Select distinct E.Estimate_Id Id'
                                +' From Expbudget E'
                                +' Where E.Estimate_Id in (' + xSQL + ')'
                                +'  and E.Budget_Id = ?'
                                +'   and E.Kfsr_Code = ?'
                                +'   and E.Kvr_Code = ? and E.Kesr_Code = ? '
                                +' and E.Kcsr_Code = ? and E.Kadmr_Code = ?',
                                [ aBudgetId,
                                  aOrg_Id,
                                  aBudgetId,
                                  aLine.getAttribute('KFSR_CODE'),
                                  aLine.getAttribute('KVR_CODE'),
                                  aLine.getAttribute('KESR_CODE'),
                                  aLine.getAttribute('KCSR_CODE'),
                                  aLine.getAttribute('KADMR_CODE')]);
      end else begin
        xSQL :=  ' Select distinct e.Id From Estimate e'
                +' Where e.EstKind_Id in (1, 7) and e.Actual_Flag = 1'
                +' and e.Budget_Id = ? and e.Org_Id = ?'
                +' and ('
                +'   exists( select * from orgaccount oa1'
                +'            where oa1.id=e.face_acc and'
                +'            oa1.orgacctype_id=5 and oa1.ACCOUNT_NUMBER = ?'
                +'            and oa1.DISTRIBUTIVE_FLAG = 0 )'
                +'  or'
                +'   exists( select * from orgaccount oa2'
                +'            join orgaccount oa3 on oa3.id=oa2.keeperacc_id'
                +'            where oa2.id=e.face_acc and'
                +'            oa2.orgacctype_id=1 and oa3.ACCOUNT_NUMBER = ?'
                +'            and       oa2.DISTRIBUTIVE_FLAG = 0)'
                +')';
        xXml := QueryXml( xSQL,
                         [ aBudgetId,
                            aOrg_Id,
                            aAccount,
                            aAccount]);

        // здесь проверяем, если не найдено ни одной записи, то бланк расходов
        // считаем не найденным. если нашли несколько БР - ищем в РЧБ.
        // причем только среди тех, которые нашлись в справочнике (см. выше).
        if (xXml.documentElement.childNodes.Length > 1)
          then xXml := QueryXml( 'Select distinct E.Estimate_Id Id'
                                +' From Expbudget E'
                                +' Where E.Estimate_Id in (' + xSQL + ')'
                                +'  and E.Budget_Id = ?'
                                +'   and E.Kfsr_Code = ?'
                                +'   and E.Kvr_Code = ? and E.Kesr_Code = ? '
                                +' and E.Kcsr_Code = ? and E.Kadmr_Code = ?',
                                [ aBudgetId,
                                  aOrg_Id,
                                  aAccount,
                                  aAccount,
                                  aBudgetId,
                                  aLine.getAttribute('KFSR_CODE'),
                                  aLine.getAttribute('KVR_CODE'),
                                  aLine.getAttribute('KESR_CODE'),
                                  aLine.getAttribute('KCSR_CODE'),
                                  aLine.getAttribute('KADMR_CODE')]);
      end;

      if xXml.documentElement.childNodes.Length = 1
        then Result := xXml.documentElement.childNodes.item[0].getAttribute('ID');
      except
        ExceptionLog( 'GetEstimateIdForED215');
    end;

end;
*)


{~FillDopKDinLinebyExpBudget
  заполнение доп.кодов в строке aLine либо нулями, либо по строке РЧБ,
  с учетом БР=aEstimateID и бюджетополучателя=aRECIPIENTID + КБК из строки.
  не учитывается код цели
  exchange #3062
  убран косгу из поиска в рчб.}
procedure FillDopKDinLinebyExpBudget( aBudgetId: string;
                                      aLine: Variant;
                                      aEstimateID: string;
                                      aRECIPIENTID: string);
var
  xXml: Variant;
begin

    try
      if (QueryField(  ' select count( * ) N From Expbudget E'
                      +' Where E.Estimate_Id = ?'
                      +'  and E.Budget_Id = ?'
                      +'   and E.Kfsr_Code = ?'
                      +'   and E.Kvr_Code = ?'
                      // exchange #3062
//                      +' and E.Kesr_Code = ? '
                      +' and E.Kcsr_Code = ? and E.Kadmr_Code = ?'
                      +' and RECIPIENT_ID=?',
                      [ aEstimateID,
                        aBudgetId,
                        GetNodeAttributeEx( aLine, 'KFSR_CODE'),
                        GetNodeAttributeEx( aLine, 'KVR_CODE'),
  //                      GetNodeAttributeEx( aLine, 'KESR_CODE'),
                        GetNodeAttributeEx( aLine, 'KCSR_CODE'),
                        GetNodeAttributeEx( aLine, 'KADMR_CODE'),
                        aRECIPIENTID],
                      'N') <> '1') then begin
        aLine.setAttribute( 'KDF_CODE', FormatKbk( 'KDF', '0', aBudgetId));
        aLine.setAttribute( 'KDE_CODE', FormatKbk( 'KDE', '0', aBudgetId));
        aLine.setAttribute( 'KDR_CODE', FormatKbk( 'KDR', '0', aBudgetId));
      end else begin
        xXml := QueryXml(  ' select E.* From Expbudget E'
                          +' Where E.Estimate_Id = ?'
                          +'  and E.Budget_Id = ?'
                          +'   and E.Kfsr_Code = ?'
                          +'   and E.Kvr_Code = ?'
                          // exchange #3062
//                          +' and E.Kesr_Code = ? '
                          +' and E.Kcsr_Code = ? and E.Kadmr_Code = ?'
                          +' and RECIPIENT_ID=?',
                          [ aEstimateID,
                            aBudgetId,
                            GetNodeAttributeEx( aLine, 'KFSR_CODE'),
                            GetNodeAttributeEx( aLine, 'KVR_CODE'),
//                            GetNodeAttributeEx( aLine, 'KESR_CODE'),
                            GetNodeAttributeEx( aLine, 'KCSR_CODE'),
                            GetNodeAttributeEx( aLine, 'KADMR_CODE'),
                            aRECIPIENTID]);
        if (xXml.documentElement.childNodes.Length <> 1) then begin
          aLine.setAttribute( 'KDF_CODE', FormatKbk( 'KDF', '0', aBudgetId));
          aLine.setAttribute( 'KDE_CODE', FormatKbk( 'KDE', '0', aBudgetId));
          aLine.setAttribute( 'KDR_CODE', FormatKbk( 'KDR', '0', aBudgetId));
        end else begin
          xXml := xXml.documentElement.childNodes.item[0];
          aLine.setAttribute( 'KDF_CODE', GetNodeAttributeEx( xXml, 'KDF_CODE'));
          aLine.setAttribute( 'KDE_CODE', GetNodeAttributeEx( xXml, 'KDE_CODE'));
          aLine.setAttribute( 'KDR_CODE', GetNodeAttributeEx( xXml, 'KDR_CODE'));
          // exchange #3111 - косгу тоже переносится из рчб
          aLine.SetAttribute( 'KESR_CODE',GetNodeAttributeEx( xXml, 'KESR_CODE'));
        end;
      end;

      except
        ExceptionProc( 'FillDopKDinLinebyExpBudget');
    end;

end;



{~FillLineED_2957_ByZR
  exchange #2957

  1.	Среди строк найденных бланков ищем строку по КБК+Код цели (с учетом,
      что если в файле пришло пустое поле для КЦ, для поиска в базе считаем КЦ=0).

  a)  Если строка нашлась единственная, то подставляем в ЭД ее реквизиты:
    Бюджетополучатель, КБК, Код цели, КВФО, доп.коды.
      Если таких строк не нашлось вообще, заполняем в ЭД КБК,
    Код цели из файла, КВФО =1, доп.коды = нули,
    Бюджетополучатель определяется в зависимости от наличия признака
    «Межбюджетные трансферты» в найденном бланке:
      если признак не установлен, то ставим Бюджетополучатель=Организация-оператор
        бланка расходов,
      если признак установлен, то Бюджетополучатель = Контрагент (Контрагента
        определяем так:
          ищем в справочнике организаций организацию по
    ИНН= IK.ZR.INN_RSP, актуальную, а если не нашли, то по ИНН+КПП
    (у четом «Дополнительных КПП»), равным соответственно IK.ZR.INN_RSP,
    IK.ZR.KPP_RCP, актуальную.
          Если найдена однозначно, устанавливаем в Бюджетополучателя.
          Если не найдена или найдена не однозначно, то в Бюджетополучателя
    устанавливаем «Не указана».
      При поиске Контрагента осуществляем
    дополнительную проверку, если организация Контрагента найдена однозначно
    и имеет роль «Бюджетное учреждение» или «Автономное учреждение», проверяем,
    чтобы в списке ее счетов организаций был счет 5 типа с номером,
    равным ZR.LS_UBP_RCP. Если такой счет присутствует, то организацию
    в поле Бюджетополучатель проставляем, если нет, то в Бюджетополучателя
    ставим «Не указана»).

b)	Если найденных строк несколько, продолжаем поиск строки РЧБ.
1.1.	Если среди строк найденных бланков по КБК+Код цели
(с учетом, что если в файле пришло пустое поле для КЦ, для поиска в базе
считаем КЦ=0) нашлось несколько строк, ищем среди них строку с учетом
Бюджетополучателя=Контрагенту:
  Контрагента определяем так: ищем в справочнике организаций организацию
  по ИНН= IK.ZR.INN_RSP, актуальную, а если не нашли, то по ИНН+КПП
  (с учетом «Дополнительных КПП»), равным соответственно IK.ZR.INN_RSP,
  IK.ZR.KPP_RCP, актуальную. Если найдена однозначно, ищем строку по
  Бланк+КБК+КЦ+Бюджетополучатель.

a)	Если строка нашлась единственная, то подставляем в ЭД ее реквизиты:
  Бюджетополучатель, КБК, Код цели, КВФО, доп.коды.
b)	Если не найдена или найдена не однозначно, то в Бюджетополучателя
  устанавливаем «Не указана», заполняем в ЭД КБК, Код цели из файла, КВФО =1,
  доп.коды = нули.
При поиске с учетом Контрагента также осуществляем дополнительную проверку:
  если организация Контрагент найдена однозначно и имеет роль
  «Бюджетное учреждение» или «Автономное учреждение», проверяем,
  чтобы в списке ее счетов организаций был счет 5 типа с номером,
  равным ZR.LS_UBP_RCP. Если такой счет присутствует,
  то ищем строку в РЧБ с учетом Бюджетополучателя и далее действуем по
  пунктам a) и b), если нет, то не ищем с учетом Бюджетополучателя,
  ставим в ЭД в Бюджетополучателя = «Не указана», заполняем в ЭД КБК,
  Код цели из файла, КВФО =1, доп.коды = нули.

  aEDLine - строка в создаваемом эд (11,195)
  aXmlZRST - исходная строка файла ZRST}
procedure FillLineED_2957_ByZR( aBudgetId: string;
                               aESTIMATE_ID: string;
                                aINN: string;
                                aKPP: string;
                                aLS: string;
                               aEDLine, aXmlZRST: Variant);
var
  xXml: Variant;
  xPURPOSEFULGRANT_ID: string;
  xKFSR_CODE: string;
  xKVR_CODE: string;
  xKESR_CODE: string;
  xKCSR_CODE: string;
  xKADMR_CODE: string;
  xFound: string;
  xRECIPIENT_ID: string;
  xOrgID: string;
//  xZR_INN_RCP: string;
//  xZR_KPP_RCP: string;
//  xZR_LS_UBP_RCP: string;

  {~DoLineFillDefault_
    заполнение строки по умолчанию: КВФО =1, доп.коды = нули,
    бюджетополучатель="не указан"}
  procedure DoLineFillDefault_;
  begin

      try
        aEDLine.setAttribute( 'KDF_CODE', FormatKbk( 'KDF', '0', aBudgetId));
        aEDLine.setAttribute( 'KDE_CODE', FormatKbk( 'KDE', '0', aBudgetId));
        aEDLine.setAttribute( 'KDR_CODE', FormatKbk( 'KDR', '0', aBudgetId));
        aEDLine.SetAttribute( 'FSR_ID', '1');
        aEDLine.SetAttribute( 'RECIPIENT_ID', '0');
        except
          ExceptionProc( 'DoLineFillDefault_');
      end;

  end;

  {~DoLineFill_ExpBudget_
    заполняем доп коды и КВФО из строки РЧБ.
      если параметр aReceipientID не будет указан, то поиск в рчб осуществляем
    без него, а в строке заполняем бюджетополучателя из строки РЧБ.
      если параметр aReceipientID будет указан, то при поиске в РЧБ учитываем
    этот параметр как бюджетополучателя, а в строке бюджетополучателя не
    заполняем.}
  procedure DoLineFill_ExpBudget_( aReceipientID: string = '');
  var
    xExpBudget: Variant;
  begin

      try
        if (LENGTH( aReceipientID) <= 0)
          then xExpBudget := QueryXml(  ' Select E.KDF_CODE, E.KDE_CODE, E.KDR_CODE,'
                                       +'  E.FSR_ID, E.RECIPIENT_ID, E.KESR_CODE'
                                       +' From Expbudget E'
                                       +' Where E.Budget_Id = ?'
                                       +'  and E.Estimate_Id = ?'
                                       +'  and E.Kfsr_Code = ?'
                                       +'  and E.Kvr_Code = ?'
                                       // exchange #3062 - отмена косгу
//                                       +'  and E.Kesr_Code = ?'
                                       +'  and E.Kcsr_Code = ?'
                                       +'  and E.Kadmr_Code = ?'
                                       +'  and E.PURPOSEFULGRANT_ID=?',
                                        [ aBudgetId,
                                          aESTIMATE_ID,
                                          xKFSR_CODE,
                                          xKVR_CODE,
  //                                        xKESR_CODE,
                                          xKCSR_CODE,
                                          xKADMR_CODE,
                                          xPURPOSEFULGRANT_ID])
        // exchange #2989
        // нужно возвращать поле бюджетополучателя, даже если это
        // критерий фильтра в рчб!
          else xExpBudget := QueryXml(  ' Select E.KDF_CODE, E.KDE_CODE, E.KDR_CODE,'
                                       +'  E.FSR_ID, E.RECIPIENT_ID, E.KESR_CODE'
                                       +' From Expbudget E'
                                       +' Where E.Budget_Id = ?'
                                       +'  and E.Estimate_Id = ?'
                                       +'  and E.Kfsr_Code = ?'
                                       +'  and E.Kvr_Code = ?'
                                       // exchange #3062 - отмена косгу
//                                       +'  and E.Kesr_Code = ?'
                                       +'  and E.Kcsr_Code = ?'
                                       +'  and E.Kadmr_Code = ?'
                                       +'  and E.PURPOSEFULGRANT_ID=?'
                                       +'  and E.RECIPIENT_ID=?',
                                        [ aBudgetId,
                                          aESTIMATE_ID,
                                          xKFSR_CODE,
                                          xKVR_CODE,
  //                                        xKESR_CODE,
                                          xKCSR_CODE,
                                          xKADMR_CODE,
                                          xPURPOSEFULGRANT_ID,
                                          aReceipientID]);
        // на всякий случай проверяем результат запроса
        if (xExpBudget.documentElement.childNodes.Length <> 1) then begin
          WriteInfo( 'Найдено несколько строк в РЧБ - строка заполняется по умолчанию.');
          DoLineFillDefault_;
          EXIT;
        end;
        xExpBudget := xExpBudget.documentElement.childNodes.item[0];

        aEDLine.SetAttribute( 'KDF_CODE',
                                GetNodeAttributeEx( xExpBudget, 'KDF_CODE'));
        aEDLine.SetAttribute( 'KDE_CODE',
                                GetNodeAttributeEx( xExpBudget, 'KDE_CODE'));
        aEDLine.SetAttribute( 'KDR_CODE',
                                GetNodeAttributeEx( xExpBudget, 'KDR_CODE'));
        aEDLine.SetAttribute( 'FSR_ID',
                                GetNodeAttributeEx( xExpBudget, 'FSR_ID'));

        // exchange #3111 - косгу тоже переносится из рчб
        aEDLine.SetAttribute( 'KESR_CODE',
                                GetNodeAttributeEx( xExpBudget, 'KESR_CODE'));

        // заполняем бюджетополучателя в строке ЭД 11го
        {if (LENGTH( aReceipientID) <= 0)
          then }aEDLine.SetAttribute( 'RECIPIENT_ID',
                                       GetNodeAttributeEx( xExpBudget,
                                                           'RECIPIENT_ID'));
        except
          ExceptionProc( 'DoLineFill_ExpBudget_');
      end;

  end;


  {~QueryOrgReceipient_
    запрос поиска контрагента только по инн+кпп.
    описываем запрос без select.
      это дает зделать два запроса:
      первый - количество записей, второй - конкретную выборку.
    альтернатива - использовать константу.}
  function QueryOrgReceipient_: string;
  begin

      try
        Result :=  ' from ORG ooo '
                   // здесь проверяется галка "актуальная" у организации
                  +' Join Contractor C on C.Org_Id = ooo.Id'
                  +' Join Budget Obd on Obd.Org_Id = C.Inspector_Id'
                  +' where Obd.ID=?'
                  // у орг не должно быть даты закрытия
                  +' and ooo.Close_Date is null'
                  // инн+(кпп или среди дополнительных кпп)
                  +' and ooo.TAXCODE=? and'
                  +' (ooo.KPP=? or exists(select * from orgkpp ok'
                                 +' where ok.org_id=ooo.id and ok.kpp=?))';
        except
          ExceptionProc( 'QueryOrgReceipient_');
      end;

  end;

(*
  {~QueryOrgReceipientAuBu_
    запрос поиска контрагента с ролью ау/бу и типом счета 5.
    описываем запрос без select.
      это дает зделать два запроса:
      первый - количество записей, второй - конкретную выборку.
    альтернатива - использовать константу.}
  function QueryOrgReceipientAuBu_: string;
{  var
    xQueryAllAccount: string;}
  begin

      try
        // если счет не указан, то вместо того чтобы его исключить из запроса
        // и чтобы не увеличивать код, добавляем в запрос подзапрос проверки
        // наличия любого незакрытого счета у организации.
        if ( LENGTH( aLS) <= 0)
          then xQueryAllAccount := ''
          else xQueryAllAccount :=
                   // наличие счета у орг 5го типа
                  +' and exists ( select * from  ORGACCOUNT OA'
                  +'     where OA.ORG_ID = OOO.ID'
                  +'  and OA.CLOSE_DATE is null'
                  +'  and (OA.ACCOUNT_NUMBER=? and oa.orgacctype_id=5))';

        Result :=  ' from ORG ooo '
                   // здесь проверяется галка "актуальная" у организации
                  +' Join Contractor C on C.Org_Id = ooo.Id'
                  +' Join Budget Obd on Obd.Org_Id = C.Inspector_Id'
                  +' where Obd.ID=?'
                  // у орг не должно быть даты закрытия
                  +' and ooo.Close_Date is null'
                  // наличие оргроли орг 18 или 19
                  +' and exists ( select * from orgroles oor where'
                  +'   oor.orgrole_id in (18,19) and oor.org_id=ooo.id)'
                  // инн+(кпп или среди дополнительных кпп)
                  +' and ooo.TAXCODE=? and'
                  +' (ooo.KPP=? or exists(select * from orgkpp ok'
                                 +' where ok.org_id=ooo.id and ok.kpp=?))'
                  +xQueryAllAccount
                  +')';
        except
          ExceptionProc( 'QueryOrgReceipientAuBu_');
      end;

  end;
  *)


  {~QueryExpBudget2_
    запрос поиска строки в РЧБ с бюджетополучателем, равным контрагенту,
    который определяется подзапросом QueryOrgReceipient_.
    возвращает значение запроса в поле aResultFieldName.
    aSelect - подзапрос select...
    например:
      select count( * ) N
      или
      select e.receipient ID }
  function QueryExpBudget2_( aSelect, aResultFieldName, aRecipientID: string): string;
  var
    xXml: Variant;
  begin

      try
//        if (LENGTH( aResultFieldName) > 0)
//          then
        Result := QueryField( aSelect
                             +' From Expbudget E'
                             +' Where E.Budget_Id = ?'
                             +'  and E.Estimate_Id = ?'
                             +'  and E.Kfsr_Code = ?'
                             +'  and E.Kvr_Code = ?'
                             // exchange #3062 - отмена косгу
//                             +'  and E.Kesr_Code = ?'
                             +'  and E.Kcsr_Code = ?'
                             +'  and E.Kadmr_Code = ?'
                             +'  and E.PURPOSEFULGRANT_ID=?'
                             +'  and E.RECIPIENT_ID=?',
//                              in (select ooo.ID ID '
  //                           +QueryOrgReceipient_ + ')',
                              [ aBudgetId,
                                aESTIMATE_ID,
                                xKFSR_CODE,
                                xKVR_CODE,
//                                xKESR_CODE,
                                xKCSR_CODE,
                                xKADMR_CODE,
                                xPURPOSEFULGRANT_ID,
                                aRecipientID {
                                aBudgetId,
                                aINN,//xZR_INN_RCP,
                                aKPP,//xZR_KPP_RCP,
                                aKPP,//xZR_KPP_RCP,
                                aLS}],//xZR_LS_UBP_RCP],
                              aResultFieldName);
                              (*
        else begin
          xXml := QueryXml( aSelect
                             +' From Expbudget E'
                             +' Where E.Budget_Id = ?'
                             +'  and E.Estimate_Id = ?'
                             +'  and E.Kfsr_Code = ?'
                             +'  and E.Kvr_Code = ?'
                             +'  and E.Kesr_Code = ?'
                             +'  and E.Kcsr_Code = ?'
                             +'  and E.Kadmr_Code = ?'
                             +'  and E.PURPOSEFULGRANT_ID=?'
                             +'  and E.RECIPIENT_ID=?',
                             // in (select ooo.ID ID '
//                             +QueryOrgReceipient_ + ')',
                              [ aBudgetId,
                                aESTIMATE_ID,
                                xKFSR_CODE,
                                xKVR_CODE,
                                xKESR_CODE,
                                xKCSR_CODE,
                                xKADMR_CODE,
                                xPURPOSEFULGRANT_ID,
                                aRecipientID{,
                                aBudgetId,
                                aINN,
                                aKPP,
                                aKPP,
                                aLS}]);
          Result := INTTOSTR( xXml.documentElement.childNodes.Length);
        end;
        *)
        except
          ExceptionProc( 'QueryExpBudget2_');
      end;

  end;

  {~QueryExpBudget1_
    запрос поиска строки в РЧБ без бюджетополучателя.
    возвращает значение запроса в поле aResultFieldName.
    aSelect - подзапрос select...
    например:
      select count( * ) N
      или
      select e.receipient ID }
  function QueryExpBudget1_{( aSelect, aResultFieldName: string)}: integer;
//  var
//    xXml: Variant;
  begin

      try
{        if (LENGTH( aResultFieldName) > 0)
          then
        Result := QueryField( aSelect
                             +' From Expbudget E'
                             +' Where E.Budget_Id = ?'
                             +'  and E.Estimate_Id = ?'
                             +'  and E.Kfsr_Code = ?'
                             +'  and E.Kvr_Code = ?'
                             +'  and E.Kesr_Code = ?'
                             +'  and E.Kcsr_Code = ?'
                             +'  and E.Kadmr_Code = ?'
                             +'  and E.PURPOSEFULGRANT_ID=?',
                              [ aBudgetId,
                                aESTIMATE_ID,
                                xKFSR_CODE,
                                xKVR_CODE,
                                xKESR_CODE,
                                xKCSR_CODE,
                                xKADMR_CODE,
                                xPURPOSEFULGRANT_ID],
                              aResultFieldName)
        else begin}
          xXml := QueryXml(
                              ' Select distinct E.RECIPIENT_ID ID'
                             +' From Expbudget E'
                             +' Where E.Budget_Id = ?'
                             +'  and E.Estimate_Id = ?'
                             +'  and E.Kfsr_Code = ?'
                             +'  and E.Kvr_Code = ?'
                             // exchange #3062 - отмена косгу
//                             +'  and E.Kesr_Code = ?'
                             +'  and E.Kcsr_Code = ?'
                             +'  and E.Kadmr_Code = ?'
                             +'  and E.PURPOSEFULGRANT_ID=?',
                              [ aBudgetId,
                                aESTIMATE_ID,
                                xKFSR_CODE,
                                xKVR_CODE,
  //                              xKESR_CODE,
                                xKCSR_CODE,
                                xKADMR_CODE,
                                xPURPOSEFULGRANT_ID]);
          Result := xXml.documentElement.childNodes.Length;
          if (Result = 1)
            then xXml := xXml.documentElement.childNodes.item[0];
//        end;
        except
          ExceptionProc( 'QueryExpBudget1_');
      end;

  end;

  {~QueryReceipient_
    ищем орг по инн+кпп.
    если найдена однозначно - проверяется, если орг. имеет роль ау/бу
    проверяем счет aLS для этой орг. 5го типа.
    если счет не указан - проверку не выполняем, и считаем что такого счета
    орг. не имеет.
    результат
      =орг.id - ид.найденной орг.
      =пусто - если орг не найдена, или найдено несколько, или это ау/бу, но
           счет не найден или не указан.}
  function QueryReceipient_: string;
  begin

      try
        Result := '';
        // проверяем, сколько есть строк в РЧБ с учетом райденного бланка расходов
        // и кбк+код цели текущей строки ZRST
        // а бюджетополучатель определяем как контрагент
        // проверяем, если контрагент найден один, то ищем строку в РЧБ
        // с бюджетополучателем=контрагент, если контрагент не найден или
        // найдено несколько - ищем в РЧБ строку без бюджетополучателя
        if (QueryField( 'select count( * ) N ' + QueryOrgReceipient_,
                        [ aBudgetId,
                          aINN,
                          aKPP,
                          aKPP],
                        'N') = '1') then begin
            Result := QueryField( 'select ooo.ID ID ' + QueryOrgReceipient_,
                        [ aBudgetId,
                          aINN,
                          aKPP,
                          aKPP],
                        'ID');
           // прверяем роль орг. ау/бу
           if (QueryField( ' select count( * ) N from orgroles oor'
                          +' where oor.orgrole_id in (18,19) and oor.org_id=?',
                           [ Result],
                           'N') <> '0') then begin
             // если ау/бу - проверяем, есть ли у этой орг. счет aLS, 5го типа.
             // если счет не указан - тогда и проверку не делаем,
             // и в журнале info пишем что счет не указан.
             if (LENGTH( aLS) > 0) then begin
               if (QueryField( ' select count( * ) N from ORGACCOUNT OA'
                              +' where OA.ORG_ID = ? and'
                              +' OA.CLOSE_DATE is null and'
                              +' (OA.ACCOUNT_NUMBER = ? and OA.ORGACCTYPE_ID = 5)',
                               [ Result,
                                 aLS],
                               'N') = '0')
                 then Result := '';
             end else begin
               WriteInfo( 'Счет не указан. Бюджетополучатель будет подставлен "Не указан".');
               Result := '';
             end;
           end;
        end;
        except
          ExceptionProc( 'QueryReceipient_');
      end;

  end;

(*
  {~DoGetFieldsFromZR_
    заполнение переменных из раздела ZR.}
  procedure DoGetFieldsFromZR_;
  begin

      try
        xZR_INN_RCP    := GetNodeAttributeEx( aXmlZR, 'INN_RCP');
        xZR_KPP_RCP    := GetNodeAttributeEx( aXmlZR, 'KPP_RCP');
        xZR_LS_UBP_RCP := GetNodeAttributeEx( aXmlZR, 'LS_UBP_RCP');
        except
          ExceptionProc( 'DoGetFieldsFromZR_');
      end;

  end;
  *)


begin

    try
//      aESTIMATE_ID  := GetNodeAttributeEx( aED11, 'ESTIMATE_ID');
//      aBudgetId     := GetNodeAttributeEx( aED11, 'BUDGET_ID');

      // использование кода цели при поиске бланка расходов
      // если цод цели в файле пустой - заменяем его на системный 0
      xPURPOSEFULGRANT_ID := GetNodeAttributeEx( aXmlZRST, 'PURPOSEFULGRANT_ID');
      if (xPURPOSEFULGRANT_ID = '')
        then xPURPOSEFULGRANT_ID := GetPurposeFulgrantId( aBudgetId, '0');

      // переносим параметры КБК в локальные переменные
      // это несколько ускорит работу и уменьшит размер скомп.скрипта
      xKFSR_CODE  := GetNodeAttributeEx( aXmlZRST, 'KFSR_CODE');
      xKVR_CODE   := GetNodeAttributeEx( aXmlZRST, 'KVR_CODE');
      xKESR_CODE  := GetNodeAttributeEx( aXmlZRST, 'KESR_CODE');
      xKCSR_CODE  := GetNodeAttributeEx( aXmlZRST, 'KCSR_CODE');
      xKADMR_CODE := GetNodeAttributeEx( aXmlZRST, 'KADMR_CODE');

      // проверяем, сколько есть строк в РЧБ с учетом райденного бланка расходов
      // и кбк+код цели текущей строки ZRST
      xFound := QueryField( ' Select count( * ) N From Expbudget E'
                           +' Where E.Budget_Id = ?'
                           +'  and E.Estimate_Id = ?'
                           +'  and E.Kfsr_Code = ?'
                           +'  and E.Kvr_Code = ?'
                           // exchange #3062 - отмена косгу
//                           +'  and E.Kesr_Code = ?'
                           +'  and E.Kcsr_Code = ?'
                           +'  and E.Kadmr_Code = ?'
                           +'  and E.PURPOSEFULGRANT_ID=?',
                            [ aBudgetId,
                              aESTIMATE_ID,
                              xKFSR_CODE,
                              xKVR_CODE,
  //                            xKESR_CODE,
                              xKCSR_CODE,
                              xKADMR_CODE,
                              xPURPOSEFULGRANT_ID],
                            'N');
      case xFound of
        '0': begin
              DoLineFillDefault_;
              // описание бланка расходов в справочнике
              xXml := QueryXml( ' Select INTER_BUDG_TRANS_FLAG MBT, ORG_ID'
                               +' From Estimate Where Id = ?',
                                [ aESTIMATE_ID]);
              xXml := xXml.documentElement.childNodes.item[0];
              // проверяем признак МБТ

              if (GetNodeAttributeEx( xXml, 'MBT') = '0')
                then xRECIPIENT_ID := GetNodeAttributeEx( xXml, 'ORG_ID')
                else begin
                  // берем поля для поиска контрагента
                  DoLineFillDefault_;
                  // поиск контрагента
                  xRECIPIENT_ID := QueryReceipient_;
                  if (LENGTH( xRECIPIENT_ID) <= 0)
                    then xRECIPIENT_ID := '0';
                  (*
                  if (QueryField( 'select count( * ) N ' + QueryOrgReceipient_,
                                  [ aBudgetId,
                                    aINN,
                                    aKPP,
                                    aKPP,
                                    aLS],
                                  'N') <> '1')
                  // если не нашли орг - бюджетополучатель = "не указан"
                    then xRECIPIENT_ID := '0'
                    else xRECIPIENT_ID :=
                              QueryField(
                                    'select ooo.ID ID ' + QueryOrgReceipient_,
                                    [ aBudgetId,
                                      aINN,
                                      aKPP,
                                      aKPP,
                                      aLS],
                                    'ID');
                                    *)
                end;
              // заполняем бюджетополучателя в строке ЭД 11го
              aEDLine.SetAttribute( 'RECIPIENT_ID', xRECIPIENT_ID);
              EXIT;
            end;
        '1': begin
              // п.1 а) если в РЧБ найдена одна строка
              // заполняем доп коды из строки РЧБ
              DoLineFill_ExpBudget_;
              EXIT;
            end;
      end;//case//

      // берем поля из ZR для поиска контрагента
//      DoGetFieldsFromZR_;

      // проверяем, сколько есть строк в РЧБ с учетом райденного бланка расходов
      // и кбк+код цели текущей строки ZRST
      // а бюджетополучатель определяем как контрагент
      // проверяем, если контрагент найден один, то ищем строку в РЧБ
      // с бюджетополучателем=контрагент, если контрагент не найден или
      // найдено несколько - ищем в РЧБ строку без бюджетополучателя
      xOrgID := QueryReceipient_;
      if (LENGTH( xOrgID) > 0) then begin
      {
      if (QueryField( 'select count( * ) N ' + QueryOrgReceipient_,
                      [ aBudgetId,
                        aINN,
                        aKPP,
                        aKPP,
                        aLS],
                      'N') = '1')
        then begin
          xOrgID := QueryField( 'select ooo.ID ID ' + QueryOrgReceipient_,
                      [ aBudgetId,
                        aINN,
                        aKPP,
                        aKPP,
                        aLS],
                      'ID');
       }
          if (QueryExpBudget2_( 'Select count( * ) N', 'N', xOrgID) <> '1')
            then DoLineFillDefault_       // заполнение строки по умолчанию
            else begin
//              xRECIPIENT_ID := xOrgID;//QueryExpBudget2_( 'select e.RECIPIENT_ID ID', 'ID', xOrgID);
              aEDLine.SetAttribute( 'RECIPIENT_ID', xOrgID);//xRECIPIENT_ID);
              DoLineFill_ExpBudget_( xOrgID);//xRECIPIENT_ID);
            end;
        end else begin
          // проверяем, сколько есть строк с одинаковым кбк+КЦ+БР в рчб,
          // и сколько в них разных бюджетополучателей.
          if (QueryExpBudget1_{( 'Select distinct E.RECIPIENT_ID ID ', '')} = 1) then begin
            // если бюджетополучатель один, проверяем, сколько строк в РЧБ
            // с найденным бюджетополучателем
            xOrgID := GetNodeAttributeEx( xXml, 'ID');
            case QueryExpBudget2_( 'Select count( * ) N', 'N', xOrgID) of
              '0': DoLineFillDefault_;       // заполнение строки по умолчанию
              '1': begin
                      DoLineFillDefault_;       // заполнение строки по умолчанию
                      aEDLine.SetAttribute( 'RECIPIENT_ID', xOrgID);
                    end;
              else begin
        //              xRECIPIENT_ID := xOrgID;//QueryExpBudget2_( 'select e.RECIPIENT_ID ID', 'ID', xOrgID);
                      aEDLine.SetAttribute( 'RECIPIENT_ID', xOrgID);//xRECIPIENT_ID);
                      DoLineFill_ExpBudget_( xOrgID);//xRECIPIENT_ID);
                    end;
            end;//case//
          end else begin
            DoLineFillDefault_;       // заполнение строки по умолчанию
          end;
          {
            if (QueryExpBudget1_( 'Select count( * ) N', 'N') <> '1')
              then DoLineFillDefault_       // заполнение строки по умолчанию
              else begin
                xRECIPIENT_ID := QueryExpBudget1_( 'select e.RECIPIENT_ID ID', 'ID');
                aEDLine.SetAttribute( 'RECIPIENT_ID', xRECIPIENT_ID);
                DoLineFill_ExpBudget_( xRECIPIENT_ID);
              end;}
        end;
      except
        ExceptionProc( 'FillLineED_2957_ByZR');
    end;

end;

{~GetPurposefullGraintIDByUF_
  получение ид.кода цели по коду aCode.
  если aCode пустая строка, возвращается ид.нулевого кода цели.

  exchange #2863
    ФТ1: При  загрузке документов по конфигурациям Imp_FK_IK и  IMP_FK_BH,
         если в  блоке UF значение  UFPP_N.ADD_KLASS имеют значение "-"
         (прочерк), то интерпритировать данное значение как пустое.
        При формировании уточненной бюджетной строки ЭД полю "Код цели"
        присваивать значение "0".

  exchange #2937
    проверять "-" нужно и для строк UFPP и для UFPP_N.}
function GetPurposefullGraintIDByUF_( aCode: string;
                                      aIsUFPP_N: boolean;
                                      aBudgetID: string): string;
begin

    try
      if (LENGTH( aCode) <= 0)
        then Result := Exch2389_GetPURPOSEFULGRANT_ID_NULL_ByBudget( aBudgetID)
        else
          if (aCode <> '-')
            then Result := GetPurposeFulgrantId( aBudgetID, aCode)
            else Result := Exch2389_GetPURPOSEFULGRANT_ID_NULL_ByBudget( aBudgetID);

      except
        ExceptionLog( 'Сбой GetPurposefullGraintIDByUF_');
    end;

end;

{~FillGrantinvestment2979
  exchange #2979
  поиск кода субсидии aADD_KLASS в справочнике «Коды субсидий»
  осуществлять  с учетом «Код вышестоящего ГРБС(РБС) карточки
  организации aOrgID.
  Если код в структурированном файле указан, но не найден в
  справочнике, то ЭД класса 24 формировать с нулевым значением поля,
  в журнале загрузки отражать соответствующее сообщение.
  если у орг. не указан Код вышестоящего ГРБС(РБС), то в журнал
  пишем сообщение, а код субсидии подставляется =0.

  ацк-ф 21918
    потребовалось добавить название поля отр кода, поскольку для аналитической
    строки поле называется по другому.
    по умолчанию название поля соответствует бюджетной строке - это позволит
    работать  старому коду без доработки.
    aFillPURPOSEFULGRANT:
      =true - будут очищены поля кода цели бюджетной строки.
      =false - поля кода цели бюджетной строки не очищаются.}
procedure FillGrantinvestment2979( aBudgetId: string;
                                   aED_Line: Variant;
                                   aADD_KLASS: string;
                                   aOrgID: string;
                                   aFieldName: string = 'GRANTINVESTMENT_ID';
                                   aFillPURPOSEFULGRANT: boolean = TRUE);
var
  xFound: integer;
begin

    try
      if (LENGTH( aOrgID) <= 0)
        then xFound := FillGrantinvestmentIntoLine(
                            aBudgetId,
                            aADD_KLASS,
                            aED_Line,
                            '',
                            TRUE,
                            'Получатель не определен - код субсидии заполняется нулем.',
                            aFieldName,
                            aFillPURPOSEFULGRANT)
        else begin
          xFound := FillGrantinvestmentIntoLine(
                              aBudgetId,
                              aADD_KLASS,
                              aED_Line,
                              QueryField( ' select o.manager_id Z from org o'
                                         +' where o.ID = ?',
                                          [ aOrgID],
                                          'Z'),
                              TRUE,
                              'Учредитель получателя не указан - код субсидии заполняется нулем.',
                              aFieldName,
                              aFillPURPOSEFULGRANT);
          // здесь отображаем только ошибки, когда код не найден или найдено
          // несколько кодов.
          case xFound of
            -2: WriteInfo( FORMAT( 'Код субсидии %s для учредителя получателя не найден в БД'
                                  +' - код субсидии заполняется нулем.',
                                   [ aADD_KLASS]));
            -3: WriteInfo( FORMAT( 'В БД найдено несколько определений кода субсидии %s'
                                  +' для учредителя получателя - код субсидии заполняется нулем.',
                                    [ aADD_KLASS]));
          end;//case//
        end;

      // exchange #2987
      // если код не указан то он заменяется на 0. сообщение в журнале об этом
      // не нужно.
      {
      if (xFound = -1)
        then WriteInfo( 'Значение кода субсидии не указано - заполняется нулем.');
       }
      except
        ExceptionProc( 'FillGrantinvestment2979');
    end;

end;

{~Load_IK_ZSCH1_2898
  exchange #2898
  разбор разделов IK.ZSCH1/ZS.ZSCH1 загружаемого файла aDocXml
  и создание строк в ЭД aDoc (классы 11 или 194)
  на закладке "расшифровка по символам кассы"

  в результате в aDoc создается раздел:
     ...
     <SYMBCASHDOC>        - список строк ZSCH1
       <SYMBCASHDOC ...>     - строка ZSCH1
       <SYMBCASHDOC ...>
       <SYMBCASHDOC ...>

  результат:
    =true - ошибок нет
    =false - есть ошибки. эд не должен быть создан.

  особенности:
    ожидается обязательнось хотя бы одного раздела IK.ZSCH1/ZS.ZSCH1
    символ кассы в разделе IK.ZSCH1/ZS.ZSCH1 обязателен. он так же проверяется
    на наличие в бд.}
function  Load_IK_ZSCH1_2898( aDoc, aFileXml: Variant): boolean;
var
  i: integer;
  s,sN: string;
  xDocDocument: Variant;
  xNode_File: Variant;
  xNode_SYMBCASHDOC: Variant;
  xList_SYMBCASHDOC: Variant;
begin

    try
      Result := TRUE;      // пока считаем все нормально
      xDocDocument := aDoc.OwnerDocument;
      // создаем строки SYMBCASHDOC по разделам ZSCH1
      xList_SYMBCASHDOC := NULL;
      for i := 0 to aFileXml.ChildNodes.Length - 1 do begin
        xNode_File := aFileXml.ChildNodes.Item[ i];
        // подразумевается, что в файле идут подразделы ZSCH1... ZSCH2.
        // на первом не ZSCH1 прерываем обработку
        if (xNode_File.NodeName <> 'ZSCH1') then BREAK;
        //ищем разрешение для данной строки

        // создаем узел списка строк расшифровки, если встретится хотя бы
        // один раздел ZSCH1
        if VarIsNULL( xList_SYMBCASHDOC)
          then xList_SYMBCASHDOC := aDoc.AppendChild(
                                      xDocDocument.CreateElement( 'SYMBCASHDOC'));
        // создаем узел списка строк расшифровки
        xNode_SYMBCASHDOC := xList_SYMBCASHDOC.AppendChild(
                                 xDocDocument.CreateElement( 'SYMBCASHDOC'));
        // символ кассы
        s := VarToStr( xNode_File.GetAttribute( 'CHECK_KAS'));
        xNode_SYMBCASHDOC.SetAttribute( 'SYMBCASH_ID', s);
        // проверяем наличие кода в бд
        // на момнет АЦК-Ф 2.37.0.13 код бюджетонезависимый
        if (LENGTH( s) <= 0)
          then sN := '0'
          else sN := QueryField( 'select count( * ) N from SYMBCASH where id=?',
                                 [ s],
                                 'N');
        if (sN <> '1') then begin
          if (LENGTH( s) <= 0)
            then WriteInfo( FORMAT( 'ЭД не создан - символ кассы не указан в строке ZSCH1, с порядковым номером %s, не найден в БД.',
                                    [ INTTOSTR( i + 1)]))
            else WriteInfo( FORMAT( 'ЭД не создан - символ кассы %s в строке ZSCH1, с порядковым номером %s, не найден в БД.',
                                    [ s, INTTOSTR( i + 1)]));
          // есть ошибка
          Result := FALSE;
        end;
        // сумма
        // хоть поле и обязательное, на всякий случай проверяем на пустую
        // строку. если не заполнено - заменяем на 0.00
        s := VarToStr( xNode_File.GetAttribute( 'SUMR_ZVK'));
        if (LENGTH( s) <= 0)
          then xNode_SYMBCASHDOC.SetAttribute( 'AMOUNT', '0.00')
          else xNode_SYMBCASHDOC.SetAttribute( 'AMOUNT',
                                               Format( '%0.2f',
                                                       [ StrToCurr( s)]));

      end;//for//
      if VarIsNULL( xList_SYMBCASHDOC) then begin
        WriteInfo( 'ЭД не создан - Не найдено ни одного раздела ZSCH1.');
        // есть ошибка
        Result := FALSE;
      end;
      // при успешном результате выставляем флаг "от ФК" в сформированном ЭД
      if Result then aDoc.SetAttribute( 'FK_FLAG', '1');

      except
        ExceptionProc( 'Un_Import.Load_IK_ZSCH1_2898');
    end;

end;
{------------------------------------------------------------------------------}
{~UpdateDocLines_IK_ZSCH1_ZSCH2_2898
  если в ЭД 11/194 aDoc одна строка LINES/LINE и одна строка на закладке
  "расшифровка по символам кассы" (<SYMBCASHDOC>/<SYMBCASHDOC ...>)
  то в строку переносим символ кассы из закладки "расшифровка по символам кассы".

  проблема в том, что нельзя создавать вложенный эд, в котором символ кассы
  будет вложен в строку - ацк-ф это не приемлет.
  в результате строки расшифровок для строк должны формироваться в корне эд
  и связываться со строками через атрибут LINENUM.
<BUDGORDER ID="1">
  <LINES>
   <LINE LINENUM=3/>
  </LINES>
  <SYMBCASHDOC>
    <SYMBCASHDOC/>
  </SYMBCASHDOC>
  <SYMBCASHLINE>
    <SYMBCASHLINE LINENUM="3"/>
  </SYMBCASHLINE>
</BUDGORDER>

  доработка: если строка в эд одна, то она связывается со всеми расшифровками
  символов кассы.}
function UpdateDocLines_IK_ZSCH1_ZSCH2_2898( aDoc: Variant): boolean;
var
  i: integer;
  xNode_SYMBCASHDOC: Variant;
  xList_SYMBCASHDOC: Variant;
  xNode_Line: Variant;
  xList_Line: Variant;
  xNode: Variant;
  xLines_SYMBCASHDOC: Variant;
  xLine_SYMBCASHDOC: Variant;
begin

    try
      Result := FALSE;            // эд не изменился
      xList_SYMBCASHDOC := NULL;
      xList_Line        := NULL;
      for i := 0 to aDoc.ChildNodes.Length - 1 do begin
        xNode := aDoc.ChildNodes.Item[ i];
        case xNode.NodeName of
          'LINES'       : xList_Line        := xNode;
          'SYMBCASHDOC' : xList_SYMBCASHDOC := xNode;
        end;//case//
      end;//for//
      // нет строк - ничего не делаем
      if VarIsNULL( xList_Line) then EXIT;
      if VarIsNULL( xList_SYMBCASHDOC) then EXIT;
      // не по одной строке - ничего не делаем
      if (xList_Line.ChildNodes.Length <> 1) then EXIT;
      // допускается несколько строк символов кассы
      if (xList_SYMBCASHDOC.ChildNodes.Length <= 0) then EXIT;
      // переносим расшифровку в строку
      xNode_Line := xList_Line.ChildNodes.Item[ 0];

      // добавляем атрибут номера строки для ацк-ф
      xNode_Line.SetAttribute( 'LINENUM', '1');
      // в строке создается строка символа кассы, причем описание строки
      // символа кассы добавляем в шапку эд
      xLines_SYMBCASHDOC := aDoc.AppendChild(
                               aDoc.OwnerDocument.CreateElement( 'SYMBCASHLINE'));
      for i := 0 to xList_SYMBCASHDOC.ChildNodes.Length - 1 do begin
        xNode_SYMBCASHDOC := xList_SYMBCASHDOC.ChildNodes.Item[ i];

        xLine_SYMBCASHDOC := xLines_SYMBCASHDOC.AppendChild(
                                 aDoc.OwnerDocument.CreateElement( 'SYMBCASHLINE'));
        xLine_SYMBCASHDOC.SetAttribute(
                      'SYMBCASH_ID',
                      xNode_SYMBCASHDOC.GetAttribute( 'SYMBCASH_ID'));
        xLine_SYMBCASHDOC.SetAttribute(
                      'AMOUNT',
                      xNode_SYMBCASHDOC.GetAttribute( 'AMOUNT'));
        // связываем строку символа кассы с первой строкой эд
        xLine_SYMBCASHDOC.SetAttribute( 'LINENUM', '1');
      end;//for//


      Result := TRUE;
      except
        ExceptionProc( 'Un_Import.UpdateDocLines_IK_ZSCH1_ZSCH2_2898');
    end;

end;
{------------------------------------------------------------------------------}
begin
end.
