// АЦК: Расходное расписание, реестр расходных расписаний
// Постановка: Exchange #1519
// #2344 - убран спец параметр
//  #2389 - доработка получения значения ADD_KLASS по ТФФ9
uses
  'Un_Exch2719',    // exchange #2719
  'Un_Exch2344',
  'Un_Export',
  'Un_Org',
  'Un_Default',
  'QueryWork',
  'QueryKbk',
  'Un_SysParams',     // exchange #2412
  'QueryTools',
  'Un_MessageValidForm',
  'Un_VersionSupport',
  'Un_Schems',
  'Un_ToolsXml',
  'Un_Tools',
  'Un_Const',
  'Un_Progress',
  'Un_System',
  'Un_Log',
  'Un_Debug';
//  'Un_ProgressControls';

const
  TestFileName = 'Exp_Fk_AP.Xml';

var
  param_AddKlass, param_Spec: Boolean;
  param_Exch2411: boolean;
  // exchange #2572
  vCfg_ExpKodUFK: boolean;
  // exchange #2631
  vCfg_LimByAssign: boolean;


// основная функция, в которую передаются данные AzkExchange
function Main(Xml: Variant): Boolean;
begin
  Result := False;
  xml := InitializeMain( xml, TestFileName);
  if VarIsNull( xml) then exit;
  try
    try
      Initialize(Xml);
      //заполнение содержимого файла.
      // exchange #2399 переход на ТФФ 10.0 с удалением кода ТФФ8
      // #2344 - выгрузка расходного расписания ТФФ9 возможна в версиях 2.28.0.xxx
      if NOT CompareVersionAZK_Finance(
                 'Выгрузка ЭД "Расходное расписание, реестр расходных расписаний" по ТФФ 9/ТФФ 10.0',
                 '2.28',
                 FALSE,
                 TRUE)
        then EXIT;
      // exchange #2399 ТФФ 10.0 аналогично ТФФ 9.0
      if not MakeFormat_TFF9(Xml) then EXIT;
      //валидация схем.
      if param_CtlValidOn then
      begin
        if not ValidateFormat then
        begin
          ShellExecute('NotePad', FileValidate, False);
          WriteLog('Не пройден контроль валидности отдельными документами');
          if MessageDlg('Не пройден контроль валидности.' + cr +
            'Продолжить выгрузку?', mtConfirmation, mbYes + mbNo, 0) = mrNo then
          begin
            WriteLog('Выгрузка прервана пользователем');
            if param_StopAllUnloadDocNotValid then
              Exit
            else begin
              Result := True;
              Exit;
            end;
          end;
        end;
      end;
      try
        FileTmp := DirTmp + FileOut;
        WriteLog('Сохранение во временном каталоге: ' + FileTmp, True);
        XmlToTextFile(FileTmp);
      except
        raise('Ошибка сохранения: ' + FileTmp);
      end;

      // exchange #2719
      ExportOutDirExch2719( Xml.documentElement.getAttribute('EXCH_DATE'),
                            'AP');

      WriteLog('Перенос документов в архив', True);
      Move_To_ArhivEx(Xml);
//      WriteLog('Перенос файла в исходящий каталог: ' + DirOut + FileOut, True);
//      CopyFile(DirTmp + FileOut, DirOut + FileOut, False);
      if Trim(DirArh) <> '' then
      begin
        WriteLog('Копирование файла в каталог архива, согласно настройке');
        CopyFile(DirTmp + FileOut, DirArh + FileOut, False);
        if not FileExists(DirArh + FileOut) then
          ShowMessage('Не удалось скопировать файл в каталог архива:' +
              DirArh + FileOut);
      end;

      // exchange #2968 - формируем конечный файл с учетом создания zip архива
      CopyExportResultFile( DirTmp + FileOut, DirOut);
{      if not FileExists(DirOut + FileOut) then
        MessageDlg('Ошибка копирования в исходящий каталог.' + #13 + #10 +
            'Файл находится: ' + DirTmp + FileOut, mtError, mbOk, 0)
      else
        DeleteFile(DirTmp + FileOut);}
    except
      WriteLog(LastException.Message);
      raise(LastException.Message);
    end;
    Result := True;
  finally
    Finalize(Xml);
//    ProgressBar.Position := 0;
//    StatusBar.SimpleText := '';
    ShowJournalEnd;
  end;
end; {end Main}


{~FillLS_2572
  exchange #2572
  сохраняет в секции TO/AP (aSection) название (в атрибуте aFieldName)
  и код организации (в атрибуте aFieldKOD) из карточки счета,
  определенного по:
    4.1.	если заполнен «Счет» блока «РБС/АИФДБ», берем его,
    4.2.	если не заполнен «Счет» блока «РБС/АИФДБ»,
          берем «Счет» блока «ГРБС/ГАИФДБ»,
    4.3.	если не заполнены счета блоков «РБС/АИФДБ» и «ГРБС/ГАИФДБ»,
          то берем счет из настройки «Бухгалтерия/Настройка счетов/Счета
          ФО/Основной бюджетный счет», если он 9 типа.

          А если в этой настройке счет не заполнен или другого типа,
          то выгружаем код и наименование Организации-владельца
          «Единого счета бюджета» из карточки бюджета.}
function FillLS_2572( aBudgetID: string;
                      aClassID: string;
                      aLS1, aLS2: string;
                       aSection: Variant;
                       aFieldName: string;
                       aFieldKOD: string): boolean;
var
  xLS: string;
begin

    try
      Result := TRUE;
      if NOT vCfg_ExpKodUFK then EXIT;
      if NOT (aClassID in ['148','149']) then EXIT;
      // определяем счет
      // 4.1.	если заполнен «Счет» блока «РБС/АИФДБ», берем его
      xLS := aLS1;

      // 4.2.	если не заполнен «Счет» блока «РБС/АИФДБ»,
      // берем «Счет» блока «ГРБС/ГАИФДБ»

      if (LENGTH( xLS) <= 0)
        then xLS := aLS2;

      // 4.3.	если не заполнены счета блоков «РБС/АИФДБ» и «ГРБС/ГАИФДБ»,
      // то берем счет из настройки «Бухгалтерия/Настройка счетов/Счета ФО/
      // Основной бюджетный счет», если он 9 типа

      if (LENGTH( xLS) <= 0)
        then xLS := QueryField( ' select ba.mainacc_id ID from budget ba'
                               +' join orgaccount o on ba.mainacc_id=o.id'
                               +' where ba.id=? and o.orgacctype_id=9',
                                [ aBudgetID],
                                'ID');


      // на этом этапе проверяем, если счет найден, то в ЭД РР он указан
      // такого типа, что поле УФК заполнено, а по пп.4.3. бухгалтерии
      // счет 9го типа - поле УФК имеется.
      // тогда поля пп.1 и пп.2 заполняются из поля УФК в карточке счета.
      if (LENGTH( xLS) > 0) then begin
        // в поле aFieldName выгружать наименование
        // организации, указанной в поле «УФК» карточки «Счета»
        aSection.SetAttribute( aFieldName,
                               QueryField( ' select oo.description N from org oo'
                                          +' join orgaccount o on oo.id=o.EXECUTER_ID'
                                          +' where o.id=?',
                                           [ xLS],
                                           'N'));
        // в aFieldKOD поле выгружать значение поля «Код организации»
        // указанное на основной закладке в карточке организации
        aSection.SetAttribute( aFieldKOD,
                               QueryField( ' select oo.name N from org oo'
                                          +' join orgaccount o on oo.id=o.EXECUTER_ID'
                                          +' where o.id=?',
                                           [ xLS],
                                           'N'));
      end else begin
        // пп.4.3: А если в этой настройке счет не заполнен или другого типа,
        // то выгружаем код и наименование Организации-владельца «Единого счета
        // бюджета» из карточки бюджета
        xLS := QueryField( ' select ba.COMMON_ACC_ID ID from budget ba'
                          +' where ba.id=?',
                           [ aBudgetID],
                           'ID');

        if (LENGTH( xLS) > 0) then begin
          // в поле aFieldName выгружать наименование Организации-владельца
          aSection.SetAttribute(
                  aFieldName,
                  QueryField(  ' select oo.description N from budget ba'
                              +' join orgaccount o on o.id=ba.COMMON_ACC_ID'
                              +' join org oo on oo.id=o.org_id'
                              +' where ba.id=?',
                               [ aBudgetID],
                               'N'));
          // в aFieldKOD поле выгружать значение код Организации-владельца
          aSection.SetAttribute(
                  aFieldKOD,
                  QueryField(  ' select oo.name N from budget ba'
                              +' join orgaccount o on o.id=ba.COMMON_ACC_ID'
                              +' join org oo on oo.id=o.org_id'
                              +' where ba.id=?',
                               [ aBudgetID],
                               'N'));
        end else begin

          Result := FALSE;
        end;
      end;

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

end;


{~DocCaptionStr
  возвращает описание ЭД aDocXML.}
function DocCaptionStr( aDocXML: Variant): string;
begin

    try
      Result := FORMAT( 'Реестр расходных расписаний № %s от %s.',
                        [ TRIM( VarToStr( aDocXML.GetAttribute( 'DOC_NUMBER'))),
                          TRIM( VarToStr( aDocXML.GetAttribute( 'DOC_DATE')))]);
      except
        ExceptionLog( 'Сбой DocCaptionStr');
    end;

end;


{~FillAPRC_2572
  exchange #2572
  сохраняет в секции APRC aSection название (в атрибуте NAME_TOFK)
  и код организации (в атрибуте KOD_TOFK), указанной в поле «УФК»
  карточки «Счета» блока «Получатель» (aLS).
  3.	при выгрузке блока APRC:
3.1.	в поле NAME_TOFK выгружать полное наименование организации, указанной
      в поле «УФК» карточки «Счета» блока «Получатель»;
3.2.	в поле KOD_TOFK выгружать значение поля «Код организации» указанное
      на основной закладке в карточке организации, найденной в п. 3.1.}
procedure FillAPRC_2572( aClassID: string;
                        aLS: string;
                        aSection: Variant);
begin

    try
      if NOT vCfg_ExpKodUFK then EXIT;
      if NOT (aClassID in ['148','149']) then EXIT;
      if (LENGTH( aLS) <= 0) then EXIT;

      // в поле aFieldName выгружать наименование
      // организации, указанной в поле «УФК» карточки «Счета»
      aSection.SetAttribute( 'NAME_TOFK',
                             QueryField( ' select oo.description N from org oo'
                                        +' join orgaccount o on oo.id=o.EXECUTER_ID'
                                        +' where o.id=?',
                                         [ aLS],
                                         'N'));
      // в aFieldKOD поле выгружать значение поля «Код организации»
      // указанное на основной закладке в карточке организации
      aSection.SetAttribute( 'KOD_TOFK',
                             QueryField( ' select oo.name N from org oo'
                                        +' join orgaccount o on oo.id=o.EXECUTER_ID'
                                        +' where o.id=?',
                                         [ aLS],
                                         'N'));

(*
      if NOT xResult
        then WriteInfo( FORMAT( 'Расходное расписание № %s от %s.',
                        [ TRIM( VarToStr( aAPRC.GetAttribute( 'NOM_RR'))),
                          TRIM( VarToStr( aAPRC.GetAttribute( 'DATE_FORM_RR')))]));

,
                      ',
                              then begin
          // счет не найден - прерываем экспорт
          WriteInfo( 'Не найден ЛС в ЭД ' + DocCaptionAPRCStr( xDataAPRC));
          raise( 'Не найден ЛС в ЭД ' + DocCaptionAPRCStr( xDataAPRC));
        end;

                          *)
      except
        ExceptionLog( 'Сбой FillAPRC_2572');
    end;

end;


{~FillAPRC_2684
  exchange #2684
    Если в конфигурации выгрузки AP включен параметр:
    «Выгружать код и наименование УФК», заполнять поля KOD_TOFK и  NAME_TOFK
    в строке APRC по exchange #2572 (пп.3.1 и п.3.2) только в следующих случаях:

1. Если отправителем является ПБС. Необходимо проверять, если организация
    в блоке «РБС/ПБС/АИФДБ» имеет роль «Бюджетополучатель» и счет
    начинается на 03, Бюджетный, Не распорядительный, то нужно заполнить
    поля KOD_TOFK и  NAME_TOFK в блоке APRC.

2.Если ОФК отправителя и получателя не совпадают.
    Необходимо сравнивать организации УФК в РР/РРР в блоках Получатель и От кого
    (по ID организации), и если они не совпадают, то выгружать.
  Необходимо сравнивать до первого выполненного условия:

2.1:  если счет блока "ГРБС/ГАИФДБ" заполнен и ID орг. УФК Счета блока
      "ГРБС/ГАИФДБ" не равен УФК "Счета" блока "Получатель", то
      нужно заполнить поля KOD_TOFK и  NAME_TOFK в блоке APRC.
      если счет блока "ГРБС/ГАИФДБ" заполнено и ID орг. УФК Счета блока
      "ГРБС/ГАИФДБ" равен УФК "Счета" блока "Получатель", то проверяем дальше.
      если счет блока "ГРБС/ГАИФДБ" не заполнен, то проверяем дальше.

2.2:  если счет блока "РБС/ПБС/АИФДБ" заполнен и ID орг. УФК Счета блока
      "РБС/ПБС/АИФДБ" не равен УФК "Счета" блока "Получатель", то
      нужно заполнить поля KOD_TOFK и  NAME_TOFK в блоке APRC.
      если счет блока "РБС/ПБС/АИФДБ" заполнено и ID орг. УФК Счета блока
      "РБС/ПБС/АИФДБ" равен УФК "Счета" блока "Получатель", то проверяем дальше.
      если счет блока "РБС/ПБС/АИФДБ" не заполнен, то проверяем дальше.

2.3: проверяется:
     Бухгалтерия-Настройка счетов-Счета ФО-Основной бюджетный счет 9го типа.
     если счет указан, проверяем ID орг. УФК "Счета" блока "Получатель".
     если ID орг. не равны - нужно заполнить поля KOD_TOFK и NAME_TOFK
     в блоке APRC.
     если ID орг. равны, или счет не указан (или не 9го типа), то проверяем
     дальше.

2.4: проверяется:
     Организацию-владельца «Единого счета бюджета» из карточки бюджета.
     если счет указан, проверяем орг. владельца этого счета c ID орг.
     УФК "Счета" блока "Получатель".
     если ID орг. не равны - нужно заполнить поля KOD_TOFK и NAME_TOFK
     в блоке APRC.
     если ID орг. равны, или счет не указан - поля KOD_TOFK и NAME_TOFK
     в блоке APRC необходимо очищать.

  при проверке орг УФК из счета в пп.2.1-п.2.3,
  на всякий случай здесь проверяем заполнение организации УФК.
  если в счете, орг. УФК не заполнена - проверка ид.орг. счета с УФК "Счета"
  блока "Получатель" не выполняется.

Остальные условия заполнения полей при включенном параметре не должны измениться.

Если параметр отключен, условия выгрузки не должны измениться.}
function FillAPRC_2684( aXmlNode, aSectionAPRC: Variant): boolean;
var
  xMain_ACC_ID: string;
  xORG_ACC_ID: string;
  xREC_ACC_ID: string;
  xREC_ACC_UFK_ORG_ID: string;
  xACC_ID_BUH: string;
  xOrgID_ACC_ID_BUDGET: string;
  xORG_ID: string;
  xBudgetID: string;

  {~GetOrgID_UFK_
    получения ID орг УФК по ид.счета aAcc_ID }
  function GetOrgID_UFK_( aAcc_ID: string): string;
  begin

      try
        Result:= QueryField(  ' select o.executer_id ID from orgaccount o'
                             +' where o.id = ?',
                              [ aAcc_ID],
                              'ID');
        except
          ExceptionProc( 'GetOrgID_UFK_');
      end;

  end;


  {~Compare_UFK_
    сравнение УФК указанного счета aAcc_ID, с УФК "Счета" блока "Получатель".
    результат:
      =true - УФК указанного счета aAcc_ID <> УФК "Счета" блока "Получатель".
      =false - если УФК счета aAcc_ID не заполнен,
               или УФК указанного счета aAcc_ID = УФК "Счета" блока "Получатель".}
  function Compare_UFK_( aAcc_ID: string): boolean;
  var
    xOrgID_UFK: string;
  begin

      try
        xOrgID_UFK := GetOrgID_UFK_( aAcc_ID);

        // на всякий случай здесь проверяем заполнение организации УФК
        // для указанного счета
        if (LENGTH( xOrgID_UFK) <= 0)
          then Result := FALSE
          else
            if (xOrgID_UFK <> xREC_ACC_UFK_ORG_ID)
              then Result := TRUE
              else Result := FALSE;
        except
          ExceptionProc( 'Compare_UFK_');
      end;

  end;

begin

    try
      Result := FALSE;

      if NOT vCfg_ExpKodUFK then EXIT;

      // чистим поля APRC.NAME_TOFK и APRC.KOD_TOFK
      // это связано с тем, что при включенной настройки, выгрузка в эти
      // поля по старому алгоритму не должна работать,
      // поскольку заполнять значения нужно не по ОФК, а по УФК.
      aSectionAPRC.SetAttribute( 'NAME_TOFK', '');
      aSectionAPRC.SetAttribute( 'KOD_TOFK', '');

      // Счет блока "ГРБС/ГАИФДБ"
      xMain_ACC_ID  := aXmlNode.GetAttribute( 'MAIN_ACC_ID');
      // Счет блока "РБС/ПБС/АИФДБ"
      xORG_ACC_ID   := aXmlNode.GetAttribute( 'ORG_ACC_ID');
      // "Счет" блока "Получатель"
      xREC_ACC_ID   := aXmlNode.GetAttribute( 'REC_ACC_ID');
      // орг. блока "РБС/ПБС/АИФДБ"
      xORG_ID := aXmlNode.GetAttribute( 'ORG_ID');

      // ID орг. УФК "Счета" блока "Получатель"
      xREC_ACC_UFK_ORG_ID := GetOrgID_UFK_( xREC_ACC_ID);

      if ((LENGTH( xORG_ACC_ID) > 0) AND (LENGTH( xORG_ID) > 0)) then
        // если счет "РБС/ПБС/АИФДБ" начинается на 03
        if (COPY( aXmlNode.GetAttribute( 'ORG_ACCOUNT'), 1, 2) = '03') then
          // если организация в блоке «РБС/ПБС/АИФДБ» имеет роль
          // «Бюджетополучатель»
          if (QueryField( ' select count( * ) N from orgroles r'
                         +' where r.orgrole_id=0 and r.org_id=?',
                          [ xORG_ID],
                          'N') = '1') then
            // если счет "РБС/ПБС/АИФДБ":  Бюджетный, Не распорядительный
            if (QueryField( ' select count( * ) N from orgaccount o'
                           +' where o.DISTRIBUTIVE_FLAG=0 and o.budget_flag=1'
                           +' and o.id=?',
                           [ xORG_ACC_ID],
                           'N') = '1')
              // нужно заполнить поля KOD_TOFK и  NAME_TOFK в блоке APRC
              then begin
                Result := TRUE;
                EXIT;
              end;

      // если счет блока "ГРБС/ГАИФДБ" заполнен и ID орг. УФК Счета блока
      // "ГРБС/ГАИФДБ" не равен УФК "Счета" блока "Получатель", то
      // нужно заполнить поля KOD_TOFK и  NAME_TOFK в блоке APRC.
      // если счет блока "ГРБС/ГАИФДБ" заполнено и ID орг. УФК Счета блока
      // "ГРБС/ГАИФДБ" равен УФК "Счета" блока "Получатель", то проверяем дальше.
      // если счет блока "ГРБС/ГАИФДБ" не заполнен, то проверяем дальше.

      if (LENGTH( xMain_ACC_ID) > 0) then
        if Compare_UFK_( xMain_ACC_ID) then begin
          Result := TRUE;
          EXIT;
        end;

      // если счет блока "РБС/ПБС/АИФДБ" заполнен и ID орг. УФК Счета блока
      // "РБС/ПБС/АИФДБ" не равен УФК "Счета" блока "Получатель", то
      // нужно заполнить поля KOD_TOFK и  NAME_TOFK в блоке APRC.
      // если счет блока "РБС/ПБС/АИФДБ" заполнено и ID орг. УФК Счета блока
      // "РБС/ПБС/АИФДБ" равен УФК "Счета" блока "Получатель", то проверяем дальше.
      // если счет блока "РБС/ПБС/АИФДБ" не заполнен, то проверяем дальше.

      if (LENGTH( xORG_ACC_ID) > 0) then
        if Compare_UFK_( xORG_ACC_ID) then begin
          Result := TRUE;
          EXIT;
        end;

      xBudgetID := aXmlNode.getAttribute('BUDGET_ID');

      // проверяем:
      // Бухгалтерия-Настройка счетов-Счета ФО-Основной бюджетный счет 9го типа

      xACC_ID_BUH := QueryField( ' Select Oa.ID ID From OrgAccount Oa'
                                +' Join Budget B on B.MainAcc_Id = Oa.Id'
                                +' Where B.Id = ? and Oa.OrgAcctype_Id = 9',
                                 [ xBudgetID],
                                 'ID');
      // если счет указан, проверяем ID орг. УФК Счета c ID орг.
      // УФК "Счета" блока "Получатель".
      // если ID орг. не равны - нужно заполнить поля KOD_TOFK и NAME_TOFK
      // в блоке APRC
      // если ID орг. равны, или счет не указан (или не 9го типа), то проверяем
      // дальше.
      // exchange #2976
      // Из постановки:
      // - Если Счет блока "ГРБС/ГАИФДБ" и "РБС/ПБС/АИФДБ" не заполнен,
      // то ID организации из поля УФК карточки счета бюджета.
      // Счет бюджета смотреть в Бухгалтерии/Настройке счетов,
      // если там указан счет 9 типа.
      // А если в этой настройке счет не заполнен или другого типа,
      // то сравниваем Организацию-владельца «Единого счета бюджета»
      // из карточки бюджета.
      // Согласно реализации проверяется исполнение этих двух требований
      // одновременно, что неверно - если выполняется первое условие -
      // Счет бюджета смотреть в Бухгалтерии/Настройке счетов,
      // если там указан счет 9 типа То этого достаточно, чтобы не выгружать
      // код и название УФК.
{
      if (LENGTH( xACC_ID_BUH) > 0) then
        if Compare_UFK_( xACC_ID_BUH) then begin
          Result := TRUE;
          EXIT;
        end;
        }
      if (LENGTH( xACC_ID_BUH) <= 0) then begin

        // если счет не указан или другого типа, то сравниваем
        // Организацию-владельца «Единого счета бюджета» из карточки бюджета
        // c УФК "Счета" блока "Получатель"
        xOrgID_ACC_ID_BUDGET :=
                  QueryField( ' select o.org_id ID from budget b'
                             +' join orgaccount o on o.id = b.COMMON_ACC_ID'
                             +' where b.id=?',
                              [ xBudgetID],
                              'ID');
        if (LENGTH( xOrgID_ACC_ID_BUDGET) > 0) then
          if (xREC_ACC_UFK_ORG_ID <> xOrgID_ACC_ID_BUDGET) then begin
            Result := TRUE;
            EXIT;
          end;
      end;


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

end;


function CheckED148(  aXml: Variant;
                      aMsgInfo: TStringList;
                      var aBreakLoad: boolean): boolean;
var
  i, j, n: Integer;
  xXmlNodeAPRC: Variant;
  xLinkUBNLines: Variant;
  xDocLineXml: Variant;
  xCount0, xCount1: integer;
  xCount3, xCount4: integer;
  xBreakDoc: boolean;
begin

    try
      Result := FALSE;

      // exchange #2631
      if vCfg_LimByAssign then begin

        // пока считаем что это РР выгружается
        xBreakDoc := FALSE;
        // сканируем строки РР (148го класса)
        xCount3 := 0;
        xCount4 := 0;
        for j := 0 to aXml.childNodes.length - 1 do begin
          xDocLineXml := aXml.childNodes.items[j];

          // ФТ3. Если в 148 классе по строке заполнен только блок
          // "Ассигнования" (блок "Лимиты" содержит нулевые значения),
          // проверять настройку бланка расходов из связанных УБН
          // "Разрешать доведение лимитов", и если она включена,
          // формировать блоки с учетом ФТ2.
          // если в строках ассигнования=0, то такую строку не проверяем.
          if (   (Format('%0.2f', [StrToCurr(xDocLineXml.getAttribute('ASSIGN_AMT1'))]) <> '0.00')
              or (Format('%0.2f', [StrToCurr(xDocLineXml.getAttribute('ASSIGN_AMT2'))]) <> '0.00')
              or (Format('%0.2f', [StrToCurr(xDocLineXml.getAttribute('ASSIGN_AMT3'))]) <> '0.00'))
            then
          // проверяем, если лимиты=0 - считаем такие строки в xCount3
          // если лимиты <>0 - считаем такие строки в xCount4
          // проверяются по ФТ3 и ФТ4 строки, имеющие лимиты=0
          if (    (Format('%0.2f', [StrToCurr(xDocLineXml.getAttribute('LIMIT_AMT1'))]) <> '0.00')
               or (Format('%0.2f', [StrToCurr(xDocLineXml.getAttribute('LIMIT_AMT2'))]) <> '0.00')
               or (Format('%0.2f', [StrToCurr(xDocLineXml.getAttribute('LIMIT_AMT3'))]) <> '0.00'))
            then INC( xCount4)
            else begin
              INC( xCount3);
              // для этого получаем все строки связанных УБН с учетом КБК
              // строки РР и в них получаем только ид.бланка расходов и
              // флаг "разрешать доведение лимитов".
              xLinkUBNLines :=
                  QueryXml(  ' select distinct es.id ID, es.BRING_LIM_FLAG F'
                            +' from registerdoc r'
                            +' join document de on de.id=r.master_id'
                            +' join expschedule e on e.document_id=de.id'
                            +' join EXPASSIGNMENT ex on '
                            +'     ex.document_id=r.slave_id'
                            +' join expassignment el on '
                            +'    (el.title_id=ex.id and el.title_id<>el.id)'
                            +'     or (el.id=ex.id and el.title_id is null)'
                            +' join estimate es on es.id=el.estimate_id'
                            +' where e.ID=?'
            // при этом нужно проверить только те строки УБН, в которых
            // ассигнования заполнены, а лимиты нулевые.
                            +' and ((el.assign_amt1<>0 or el.assign_amt2<>0'
                            +'       or el.assign_amt3<>0)'
                            +'      and (el.limit_amt1=0 and el.limit_amt2=0'
                            +'           and el.limit_amt3=0))'
            // ищем только строку, соответствующую строке РР (ЭД 148го класса)
            // в УБН в строках есть поле бланка расходов, которого нету в строках
            // РР. в результате, при создании строк из УБН в РР, строки в РР
            // схлопываются пр одинаковых КБК но с разными бланками расходов.
            // поэтому в ЭД РР строк может быть меньше чем в связанном ЭД УБН.
                            +' and (el.kfsr_code=?'
                            +'      and el.kcsr_code=?'
                            +'      and el.kvr_code=?'
                            // exchange #3095 - отмена косгу
//                            +'      and el.kesr_code=?'
                            +'      and el.kadmr_code=?'
                            +'      and el.purposefulgrant_id=?'
                            +'      and el.fsr_id=?)',
                             [ aXml.getAttribute( 'ID'),
                               xDocLineXml.getAttribute( 'KFSR_CODE'),
                               xDocLineXml.getAttribute( 'KCSR_CODE'),
                               xDocLineXml.getAttribute( 'KVR_CODE'),
  //                             xDocLineXml.getAttribute( 'KESR_CODE'),
                               xDocLineXml.getAttribute( 'KADMR_CODE'),
                               xDocLineXml.getAttribute( 'PURPOSEFULGRANT_ID'),
                               xDocLineXml.getAttribute( 'FSR_ID')]);

            // если ничего не нашли, значит ЭД, связанные с РР, не УБН.
            // тогда проверку прерываем - все нормально.
            xLinkUBNLines := xLinkUBNLines.documentElement;
            n := xLinkUBNLines.childNodes.length;
            if (n <= 0) then BREAK;
            // если вернется несколько строк, значит в УБН есть несколько
            // строк с одним и тем же КБК, как в строке РР, но разными
            // бланками расходов. тогда проверяем, если в строках УБН
            // в бланках расходов стоит флаг "разрешено доведение лимитов",
            // а в некоторых не стоит - тогда это критично и прерываем обработку.
            xCount0 := 0;
            xCount1 := 0;
            for i := 0 to n - 1 do
              if (xLinkUBNLines.childNodes.items[ i].GetAttribute('F') = '1')
                then INC( xCount1)
                else INC( xCount0);
            if ((xCount0 > 0) AND (xCount1 > 0)) then begin
              aMsgInfo.Add( FORMAT( 'Расходное расписание № %s, дата %s'
                                +' сформировано на основе многобланкового'
                                +' документа с различными режимами доведения'
                                +' ассигнования и лимитов. Выгрузка не возможна.'
                                +' Требуется переформировать исходные документы".',
                                 [ TRIM( aXml.getAttribute( 'DOC_NUMBER')),
                                   aXml.getAttribute( 'DOC_DATE')]));
{
              ShowMessage( FORMAT( 'Расходное расписание № %s, дата %s,'
                                +' , сформировано на основе многобланкового'
                                +' документа с различными режимами доведения'
                                +' ассигнования и лимитов. Выгрузка не возможна.'
                                +' Требуется переформировать исходные документы".',
                                 [ TRIM( aXml.getAttribute( 'DOC_NUMBER')),
                                   aXml.getAttribute( 'DOC_DATE')]));
}
              aBreakLoad := TRUE;
              EXIT;
            end;

            // если в УБН найдены строки по КБК, и в них все бланки расходов
            // имеют галочку "разрешено доведение лимитов", то выгрузку
            // такого РР не выполняем, но продолжаем проверять строки.
            if (xCount1 > 0) then begin
              // чтобы одно и тоже сообщение не выдавалось по нескольку раз,
              // для нескольких строк, в одном и том же ЭД, блокируем повторную
              // выгрузку сообщения в лог.
              if NOT xBreakDoc then begin
                aMsgInfo.Add( FORMAT( 'Расходное расписание № %s, дата %s,'
                                  +' не выгружено, не указаны суммы лимитов'
                                  +' при включеной настройке бланка расходов'
                                  +' "Разрешать доведение лимитов".',
                                   [ TRIM( aXml.getAttribute( 'DOC_NUMBER')),
                                     aXml.getAttribute( 'DOC_DATE')]));
              end;
              xBreakDoc := TRUE;     // не выгружаем РР, но продолжаем загрузку
            end;
          end;
        end;//for//

        // если строки прошли проверку по ФТ3 и ФТ4
        // то проверяем, если есть смесь строк с заполненными и нулевыми
        // лимитами, тогда такой ЭД не выгружаем
        if (( xCount3 > 0) AND (xCount4 > 0)) then begin
          aMsgInfo.Add( FORMAT( 'Расходное расписание № %s, дата %s,'
                            +' не выгружено, содержит строки с нулевыми суммами лимитов'
                            +' так и с не нулевыми суммами лимитов,'
                            +' с ненулевыми суммами ассигнований.',
                             [ TRIM( aXml.getAttribute( 'DOC_NUMBER')),
                               aXml.getAttribute( 'DOC_DATE')]));
          xBreakDoc := TRUE;
        end;

        // если в результате проверки строк, определено, что ЭД не выгружается,
        // то выходим из подпрограммы.
        if xBreakDoc then EXIT;
      end;

      Result := TRUE;
      except
        ExceptionLog( 'Сбой CheckED148');
    end;

end;

function CheckDoubleKBK_( xXmlData: Variant;
                          aL_KBK, aL_Index: TStrings;
                          aKBK: string; var aIndex: integer): boolean;
var
  xIndexKBK: integer;
begin

    try
      xIndexKBK := aL_KBK.IndexOf( aKBK);
      if (xIndexKBK = -1) then begin
        // если такого кбк в списке нет - сохраняем новый код
        // и кол-во узлов Data - это укажет индекс узла APLBOSTR
        // для этого кбк.
        aL_KBK.Add( aKBK);
        aL_Index.Add( INTTOSTR( xXmlData.ChildNodes.Length));
        aIndex := -1;
        Result := FALSE;
      end else begin
        // такой APLBOSTR уже есть - добавляем суммы в этом разделе
        aIndex := STRTOINT( aL_Index[ xIndexKBK]);
        Result := TRUE;
      end;

      except
        ExceptionProc( 'CheckDoubleKBK_');
    end;

end;


procedure CreateListKBK_(var aL_KBK, aL_Index: TStringList);
begin

    try
      aL_KBK   := NIL;
      aL_Index := NIL;
      aL_KBK   := TStringList.Create;
      aL_Index := TStringList.Create;
      except
        ExceptionProc( 'CreateListKBK_');
    end;

end;


procedure FreeListKBK_(var aL_KBK, aL_Index: TStringList);
begin

    try
      if (aL_KBK <> NIL) then aL_KBK.Free;
      if (aL_Index <> NIL) then aL_Index.Free;
//      aL_KBK   := NIL;
//      aL_Index := NIL;
      except
        ExceptionProc( 'FreeListKBK_');
    end;

end;


{~Fill_APPBASTR
  заполнение блока APBASTR (бюджетных ассигнований).

  APBASTR формируется, если в строках РР заполнены суммы ассигнований,
  и счет APRC.REC_ACCOUNT = указанному счету (aAp_ls).

  вынесено отдельно, поскольку для РР и ЭД РР в РРР заполнение блока идентично.
  exchange #2631
    ФТ2: если включена настройка "Выгружать только лимиты по строкам, где
         доводятся и ассигнования, и лимиты", И блок лимитов бюджетных
         обязательств (LIMIT_AMT1...LIMIT_AMT3) <>0 (суммы лимитов и ассигнований
         в строках <>0), то поля SUM_BA_1Y...SUM_BA_3Y заполняем нулями
         и блок APBASTR не формируем.

  exchange #3095
  исключение дублей строк с одинаковым кбк}
  (*
procedure Fill_APPBASTR( aXml, aData: Variant;
                          aAp_ls: string);
var
  j: integer;
  xOutAPPBASTR: boolean;
  xDocLineXml: Variant;
  xDataLineXml: Variant;
  xL_KBK: TStringList;
  xL_Index: TStringList;
  xKBK: String;
  xADD_KLASS: String;
  xIndex: integer;
  xCurr1: Currency;
  xCurr2: Currency;
  xCurr3: Currency;
begin

    try
      // суммы ассигн.проверяются в шапке ЭД, поскольку суммы ассигн и лимитов
      // в шапке ЭД суммируются из таких же полей в строках, хотя эти
      // суммы шапки ЭД на форме не отображаются.
      if ((   (Format('%0.2f', [StrToCurr(aXml.getAttribute('ASSIGN_AMT1'))]) <> '0.00')
           or (Format('%0.2f', [StrToCurr(aXml.getAttribute('ASSIGN_AMT2'))]) <> '0.00')
           or (Format('%0.2f', [StrToCurr(aXml.getAttribute('ASSIGN_AMT3'))]) <> '0.00'))
          and (aAp_ls <> aXml.getAttribute('REC_ACCOUNT')))
        then begin
          // exchange #2631
          // если включена настройка "Выгружать только лимиты по строкам, где
          // доводятся и ассигнования, и лимиты", И блок лимитов бюджетных
          // обязательств (LIMIT_AMT1...LIMIT_AMT3) <>0, то поля
          // SUM_BA_1Y...SUM_BA_3Y заполняем нулями и блок APBASTR не формируем.
          xOutAPPBASTR := TRUE;
          if vCfg_LimByAssign then
            if (   (Format('%0.2f', [StrToCurr(aXml.getAttribute('LIMIT_AMT1'))]) <> '0.00')
                or (Format('%0.2f', [StrToCurr(aXml.getAttribute('LIMIT_AMT2'))]) <> '0.00')
                or (Format('%0.2f', [StrToCurr(aXml.getAttribute('LIMIT_AMT3'))]) <> '0.00'))
              then xOutAPPBASTR := FALSE;

          if NOT xOutAPPBASTR then begin

            // exchange #2631 - заполнение поле суммы нулями
            aData.setAttribute('SUM_BA_1Y', '0.00');
            aData.setAttribute('SUM_BA_2Y', '0.00');
            aData.setAttribute('SUM_BA_3Y', '0.00');
          end else begin

            aData.setAttribute('SUM_BA_1Y', Format('%0.2f', [StrToCurr(aXml.getAttribute('ASSIGN_AMT1'))]));
            aData.setAttribute('SUM_BA_2Y', Format('%0.2f', [StrToCurr(aXml.getAttribute('ASSIGN_AMT2'))]));
            aData.setAttribute('SUM_BA_3Y', Format('%0.2f', [StrToCurr(aXml.getAttribute('ASSIGN_AMT3'))]));

            CreateListKBK_( xL_KBK, xL_Index);
            try
              for j := 0 to aXml.childNodes.length - 1 do begin
                xDocLineXml := aXml.childNodes.items[ j];

                // проверяем на заполненность сумм в каждой из строк
                if (   CurrAttributeIsNotZero_( xDocLineXml, 'ASSIGN_AMT1', xCurr1)
                    or CurrAttributeIsNotZero_( xDocLineXml, 'ASSIGN_AMT2', xCurr2)
                    or CurrAttributeIsNotZero_( xDocLineXml, 'ASSIGN_AMT3', xCurr3))
                  then begin
                    // exchange #3062 - отменен КОСГУ
                    xKBK := GetRuleKBKLine( xDocLineXml,
                                            // в строках тоже есть атрибут бюджета
                                            xDocLineXml.getAttribute('BUDGET_ID'),
                                            '',
                                            FALSE);
                    xADD_KLASS := Get_ADD_KLASS_TFF9( xDocLineXml, param_AddKlass);
                    if CheckDoubleKBK_( aData,
                                        xL_KBK,
                                        xL_Index,
                                        xKBK + xADD_KLASS,
                                        xIndex) then begin
                      // есть одинаковые строки - суммируем суммы в них
                      xDataLineXml := aData.ChildNodes.Items[ xIndex];
                      SummCurrAttribute_( xDataLineXml, 'SUM_BA_Y1', xCurr1);
                      SummCurrAttribute_( xDataLineXml, 'SUM_BA_Y2', xCurr2);
                      SummCurrAttribute_( xDataLineXml, 'SUM_BA_Y3', xCurr3);
                    end else begin
                      // заполняем APBASTR
                      xDataLineXml := aData.appendChild(
                                            FillElementBySchema(
                                                          xDocLineXml, 'APBASTR'));
                      xDataLineXml.setAttribute( 'KBK', xKBK);
                      xDataLineXml.setAttribute( 'ADD_KLASS', xADD_KLASS);
                    end;
                  end;

              end;//for//
              finally
                FreeListKBK_( xL_KBK, xL_Index);
            end;

              {
              // проверяем на заполненность сумм в каждой из строк
              if (   (Format('%0.2f', [StrToCurr(xDocLineXml.getAttribute('ASSIGN_AMT1'))]) <> '0.00')
                  or (Format('%0.2f', [StrToCurr(xDocLineXml.getAttribute('ASSIGN_AMT2'))]) <> '0.00')
                  or (Format('%0.2f', [StrToCurr(xDocLineXml.getAttribute('ASSIGN_AMT3'))]) <> '0.00'))
                then begin
                  // заполняем APBASTR
                  xDataLineXml := aData.appendChild(
                                        FillElementBySchema(
                                                        xDocLineXml, 'APBASTR'));
                  // exchange #3062 - отменен КОСГУ
                  xDataLineXml.setAttribute(
                            'KBK',
                            GetRuleKBKLine( xDocLineXml,
                                            // в строках тоже есть атрибут бюджета
                                            xDocLineXml.getAttribute('BUDGET_ID'),
                                            '',
                                            FALSE));
                  xDataLineXml.setAttribute(
                            'ADD_KLASS',
                            Get_ADD_KLASS_TFF9( xDocLineXml, param_AddKlass));
                end;
            end;//for//
            }
          end;
        end; {End APBASTR}

      except
        ExceptionProc( 'Fill_APPBASTR');
    end;

end;
    *)

function DoFill148_Exch2676( aXml, aDataXml: Variant): boolean;
var
  xACC_ID: string;
  xLinkDocs: Variant;
  n: integer;
begin

    try
      Result := TRUE;

      // проверяем ссылку на счет получателя
      xACC_ID := VarToStr( aXml.GetAttribute( 'REC_ACC_ID'));
      if (LENGTH( xACC_ID) <= 0) then EXIT;
      // проверяем счет получателя:
      // счет с типом «Лицевой счет ФК» и с признаком «Счет иного получателя»
      if (QueryField(  ' select o.OTHER_RECEIVER_FLAG F'
                      +' from orgaccount o where o.id=? and o.orgacctype_id=5',
                       [ xACC_ID],
                       'F') <> '1')
        then EXIT;

      // ищем связного ЭД: PP -> РЗ (распоряд.заявка) -> ЗОР
      xLinkDocs := QueryXml(   ' select distinct b.id ID,  trim(b.doc_number) NN,'
                              +' b.doc_date DD'
                              +' from registerdoc r'
                              +' join document de on de.id=r.master_id'
                              +' join expschedule e on e.document_id=de.id'
                              +' join BudgOrder ex on'
                              +' ex.document_id=r.slave_id and ex.documentclass_id=18'
                              +' join budgorderdoc bd on bd.budgorder_id=ex.id'
                              +' join budgorder b on b.id = bd.doc_id'
                              +' and B.documentclass_id = 11'
                              +' where e.ID=?',
                               [ aXml.getAttribute( 'ID')]);

      xLinkDocs := xLinkDocs.documentElement;
      n := xLinkDocs.childNodes.length;
      if (n <= 0) then EXIT;
{
      if (n > 0) then begin
        Result := FALSE;
        EXIt;
      end;
}
      // берем из первой ЗОР описание ЭД
      xLinkDocs := xLinkDocs.childNodes.items[ 0];

      aDataXml.SetAttribute(
            'NOM_PP',
            VarToStr( xLinkDocs.GetAttribute( 'NN')));

      aDataXml.SetAttribute(
            'DATE_PP',
            FormatDateTime( 'dd.mm.yyyy',
                            XmlToDateTime( xLinkDocs.GetAttribute( 'DD'))));

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

end;

procedure DoFill_APPBASTR_( aXml, aData: Variant);
var
  i: integer;
  IsNotEmpty1, IsNotEmpty2, IsNotEmpty3: Boolean;
  xL_KBK: TStringList;
  xL_Index: TStringList;
  xKBK: String;
  xADD_KLASS: String;
  xIndex: integer;
  xXmlNode: Variant;
  xDataLineXml: Variant;
  xCurr1: Currency;
  xCurr2: Currency;
  xCurr3: Currency;
begin

    try
      CreateListKBK_( xL_KBK, xL_Index);
      try
        for i := 0 to aXml.childNodes.length - 1 do begin
          xXmlNode := aXml.childNodes.items[ i];

          // проверяем на заполненность сумм в каждой из строк
          IsNotEmpty1 :=
            CurrAttributeIsNotZero_( xXmlNode, 'ASSIGN_AMT1', xCurr1);
          IsNotEmpty2 :=
            CurrAttributeIsNotZero_( xXmlNode, 'ASSIGN_AMT2', xCurr2);
          IsNotEmpty3 :=
            CurrAttributeIsNotZero_( xXmlNode, 'ASSIGN_AMT3', xCurr3);
          
          if (IsNotEmpty1 or IsNotEmpty2 or IsNotEmpty3)
            then begin
              // exchange #3062 - отменен КОСГУ
              xKBK := GetRuleKBKLine( xXmlNode,
                                      // в строках тоже есть атрибут бюджета
                                      xXmlNode.getAttribute('BUDGET_ID'),
                                      '',
                                      FALSE);
              xADD_KLASS := Get_ADD_KLASS_TFF9( xXmlNode, param_AddKlass);
              if CheckDoubleKBK_( aData,
                                  xL_KBK,
                                  xL_Index,
                                  xKBK + xADD_KLASS,
                                  xIndex) then begin
                // есть одинаковые строки - суммируем суммы в них
                xDataLineXml := aData.ChildNodes.Items[ xIndex];
                SummCurrAttribute_( xDataLineXml, 'SUM_BA_Y1', xCurr1);
                SummCurrAttribute_( xDataLineXml, 'SUM_BA_Y2', xCurr2);
                SummCurrAttribute_( xDataLineXml, 'SUM_BA_Y3', xCurr3);
              end else begin
                // заполняем APBASTR
                xDataLineXml := aData.appendChild(
                                      FillElementBySchema(
                                                    xXmlNode, 'APBASTR'));
                xDataLineXml.setAttribute( 'KBK', xKBK);
                xDataLineXml.setAttribute( 'ADD_KLASS', xADD_KLASS);
              end;
            end;

        end;//for//
        finally
          FreeListKBK_( xL_KBK, xL_Index);
      end;

      except
        ExceptionProc( 'DoFill_APPBASTR_');
    end;

end;


procedure DoFill_APLBOSTR_( aXml, aData: Variant);
var
  i: integer;
  IsNotEmpty1, IsNotEmpty2, IsNotEmpty3: Boolean;
  xL_KBK: TStringList;
  xL_Index: TStringList;
  xKBK: String;
  xADD_KLASS: String;
  xIndex: integer;
  xXmlNode: Variant;
  xDataLineXml: Variant;
  xCurr1: Currency;
  xCurr2: Currency;
  xCurr3: Currency;
begin

    try
      // блок лимитов бюджетных обязательств APLBOSTR
      CreateListKBK_( xL_KBK, xL_Index);
      try
        for i := 0 to aXml.childNodes.length - 1 do begin
          xXmlNode := aXml.childNodes.items[ i];

          // проверяем на заполненность сумм в каждой из строк
          IsNotEmpty1 :=
            CurrAttributeIsNotZero_( xXmlNode, 'LIMIT_AMT1', xCurr1);
          IsNotEmpty2 :=
            CurrAttributeIsNotZero_( xXmlNode, 'LIMIT_AMT2', xCurr2);
          IsNotEmpty3 :=
            CurrAttributeIsNotZero_( xXmlNode, 'LIMIT_AMT3', xCurr3);

          if (IsNotEmpty1 or IsNotEmpty2 or IsNotEmpty3)
            then begin
              // exchange #3062 - отменен КОСГУ
              xKBK := GetRuleKBKLine( xXmlNode,
                                      // в строках тоже есть атрибут бюджета
                                      xXmlNode.getAttribute('BUDGET_ID'),
                                      '',
                                      FALSE);
              xADD_KLASS := Get_ADD_KLASS_TFF9( xXmlNode, param_AddKlass);
              if CheckDoubleKBK_( aData,
                                  xL_KBK,
                                  xL_Index,
                                  xKBK + xADD_KLASS,
                                  xIndex) then begin
                // есть одинаковые строки - суммируем суммы в них
                xDataLineXml := aData.ChildNodes.Items[ xIndex];
                SummCurrAttribute_( xDataLineXml, 'SUM_LBO_Y1', xCurr1);
                SummCurrAttribute_( xDataLineXml, 'SUM_LBO_Y2', xCurr2);
                SummCurrAttribute_( xDataLineXml, 'SUM_LBO_Y3', xCurr3);
              end else begin
                // заполняем APBASTR
                xDataLineXml := aData.appendChild(
                                      FillElementBySchema(
                                                    xXmlNode, 'APLBOSTR'));
                xDataLineXml.setAttribute( 'KBK', xKBK);
                xDataLineXml.setAttribute( 'ADD_KLASS', xADD_KLASS);
              end;
            end;

        end;//for//
        finally
          FreeListKBK_( xL_KBK, xL_Index);
      end;

      except
        ExceptionProc( 'DoFill_APLBOSTR_');
    end;

end;


procedure DoFill_APPOFSTR_( aXml, aData: Variant);
var
  i: integer;
  xL_KBK: TStringList;
  xL_Index: TStringList;
  xKBK: String;
  xADD_KLASS: String;
  xIndex: integer;
  xXmlNode: Variant;
  xDataLineXml: Variant;
  xCurr1: Currency;
begin

    try
      // блок лимитов бюджетных обязательств APLBOSTR
      CreateListKBK_( xL_KBK, xL_Index);
      try
        for i := 0 to aXml.childNodes.length - 1 do begin
          xXmlNode := aXml.childNodes.items[ i];

          // проверяем на заполненность сумм в каждой из строк
          if CurrAttributeIsNotZero_( xXmlNode, 'AMOUNT', xCurr1)
            then begin
              // exchange #3062 - отменен КОСГУ
              xKBK := GetRuleKBKLine( xXmlNode,
                                      // в строках тоже есть атрибут бюджета
                                      xXmlNode.getAttribute('BUDGET_ID'),
                                      '',
                                      FALSE);
              xADD_KLASS := Get_ADD_KLASS_TFF9( xXmlNode, param_AddKlass);
              if CheckDoubleKBK_( aData,
                                  xL_KBK,
                                  xL_Index,
                                  xKBK + xADD_KLASS,
                                  xIndex) then begin
                // есть одинаковые строки - суммируем суммы в них
                xDataLineXml := aData.ChildNodes.Items[ xIndex];
                SummCurrAttribute_( xDataLineXml, 'SUM_POF_Y1', xCurr1);
              end else begin
                // заполняем APBASTR
                xDataLineXml := aData.appendChild(
                                      FillElementBySchema(
                                                    xXmlNode, 'APPOFSTR'));
                xDataLineXml.setAttribute( 'KBK', xKBK);
                xDataLineXml.setAttribute( 'ADD_KLASS', xADD_KLASS);
              end;
            end;

        end;//for//
        finally
          FreeListKBK_( xL_KBK, xL_Index);
      end;

      except
        ExceptionProc( 'DoFill_APPOFSTR_');
    end;

end;


(*
{~Exch2411_FillData
  Если настройка «Формировать блок Лимиты бюджетных обязательств, при
  доведении ПОФ на ЛСФК» имеет значение «Да»:
  при выгрузке ЭД «Расходное расписание» (148),
  ЭД «Реестр расходных расписаний» (149), смотреть на заполнение
  блока APPOFSTR( * ) - Предельные объемы финансирования,
  в случае если данный блок сформирован, автоматизировано формировать и
  заполнять блок APLBOSTR( * ) - Лимиты бюджетных обязательств данными
  указанными в ФТ – 3.}
procedure Exch2411_FillData( var aData: Variant;
                              var aSource: Variant);
var xData: Variant;
begin

    try
      if NOT param_Exch2411 then EXIT;

      xData := aData.appendChild( FillElementBySchema( aSource, 'APLBOSTR'));
      // exchange #3062 - отменен КОСГУ
      xData.setAttribute( 'KBK',
                          GetRuleKBKLine( aSource,
                                          aSource.getAttribute('BUDGET_ID'),
                                          '',
                                          FALSE));
      xData.setAttribute( 'ADD_KLASS',
                          Get_ADD_KLASS_TFF9( aSource, param_AddKlass));

      // Сумма ЛБО или изменений ранее распределенных ЛБО на текущий
      // финансовый год
      xData.setAttribute( 'SUM_LBO_Y1',
                         Format( '%0.2f',
                                 [StrToCurr(aSource.getAttribute('AMOUNT'))]));
      // Сумма ЛБО или изменений ранее распределенных ЛБО на 1-й год
      // планового периода - Всегда заполняем значением «0»
      xData.setAttribute( 'SUM_LBO_Y2', Format( '%0.2f', [ StrToCurr('0')]));
      // Сумма ЛБО или изменений ранее распределенных ЛБО на 2-й год
      // планового периода - Всегда заполняем значением «0»
      xData.setAttribute( 'SUM_LBO_Y3', Format( '%0.2f', [ StrToCurr('0')]));

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

end;
*)


{~DoFill_APLBOSTR_2411_
  exchange #2411
  Если настройка «Формировать блок Лимиты бюджетных обязательств, при
  доведении ПОФ на ЛСФК» имеет значение «Да»:
  при выгрузке ЭД «Расходное расписание» (148),
  ЭД «Реестр расходных расписаний» (149), смотреть на заполнение
  блока APPOFSTR( * ) - Предельные объемы финансирования,
  в случае если данный блок сформирован, автоматизировано формировать и
  заполнять блок APLBOSTR( * ) - Лимиты бюджетных обязательств данными
  указанными в ФТ – 3.
  exchange #3095
  убраны дубли строк по кбк}
procedure DoFill_APLBOSTR_2411_( aXml, aData: Variant);
var
  i: integer;
  xL_KBK: TStringList;
  xL_Index: TStringList;
  xKBK: String;
  xADD_KLASS: String;
  xIndex: integer;
  xXmlNode: Variant;
  xDataLineXml: Variant;
  xCurr1: Currency;
begin

    try
      if NOT param_Exch2411 then EXIT;

      // блок лимитов бюджетных обязательств APLBOSTR
      CreateListKBK_( xL_KBK, xL_Index);
      try
        for i := 0 to aXml.childNodes.length - 1 do begin
          xXmlNode := aXml.childNodes.items[ i];

          // проверяем на заполненность сумм в каждой из строк
          if CurrAttributeIsNotZero_( xXmlNode, 'AMOUNT', xCurr1)
            then begin
              // exchange #3062 - отменен КОСГУ
              xKBK := GetRuleKBKLine( xXmlNode,
                                      // в строках тоже есть атрибут бюджета
                                      xXmlNode.getAttribute('BUDGET_ID'),
                                      '',
                                      FALSE);
              xADD_KLASS := Get_ADD_KLASS_TFF9( xXmlNode, param_AddKlass);
              if CheckDoubleKBK_( aData,
                                  xL_KBK,
                                  xL_Index,
                                  xKBK + xADD_KLASS,
                                  xIndex) then begin
                // есть одинаковые строки - суммируем суммы в них
                xDataLineXml := aData.ChildNodes.Items[ xIndex];
                SummCurrAttribute_( xDataLineXml, 'SUM_LBO_Y1', xCurr1);
              end else begin
                // заполняем APBASTR
                xDataLineXml := aData.appendChild(
                                      FillElementBySchema(
                                                    xXmlNode, 'APLBOSTR'));
                xDataLineXml.setAttribute( 'KBK', xKBK);
                xDataLineXml.setAttribute( 'ADD_KLASS', xADD_KLASS);
                // Сумма ЛБО или изменений ранее распределенных ЛБО на текущий
                // финансовый год
                xDataLineXml.SetAttribute( 'SUM_LBO_Y1',
                                           Format( '%0.2f', [ xCurr1]));
                // Сумма ЛБО или изменений ранее распределенных ЛБО на 1-й год
                // планового периода - Всегда заполняем значением «0»
                xDataLineXml.setAttribute( 'SUM_LBO_Y2', '0.00');
                // Сумма ЛБО или изменений ранее распределенных ЛБО на 2-й год
                // планового периода - Всегда заполняем значением «0»
                xDataLineXml.setAttribute( 'SUM_LBO_Y3', '0.00');
              end;
            end;

        end;//for//
        finally
          FreeListKBK_( xL_KBK, xL_Index);
      end;

      except
        ExceptionProc( 'DoFill_APLBOSTR_');
    end;

end;



procedure Export_148( aXml: Variant;
                      var aData: Variant;
                      UbpOrg: string;
                      Ufk, Fo: Variant;
                      aMsgInfo: TStringList;
                      var aBreakLoad: boolean);
var
  i, j, z: Integer;
//  UbpOrg,
  Ap_ls: String;
//  Ufk, Fo, XmlOrg: Variant;
  xNode: Variant;
  xData: Variant;
  xDataAPRC: Variant;
  xXmlNodeAPRC: Variant;
  xDocLineXml: Variant;
  xDataLineXml: Variant;
  xCurr: Currency;
  xOutAPPBASTR: boolean;
begin

    try
      // exchange #2631 - проверяем строки РР
      if NOT CheckED148( aXml, aMsgInfo, aBreakLoad)
        then EXIT;

      Ap_ls := '';
      xData := aData.appendChild(FillElementBySchema(aXml, 'AP'));
      // заполняем AP
      xData.setAttribute('NOM_R_RR', Trim(xData.getAttribute('NOM_R_RR')));
      xData.setAttribute('DATE_R_RR', '');
      xData.setAttribute('KOD_UBP', aXml.getAttribute('MAIN_CODE'));
      if (xData.getAttribute('GLAVA_GRS') <> '') and (xData.getAttribute('GLAVA_GRS') <> '0') then
        xData.setAttribute('GLAVA_GRS',
          StringReplace(Format('%3s', [xData.getAttribute('GLAVA_GRS')]), ' ', '0'))
      else
        xData.setAttribute('GLAVA_GRS','');

      if xData.getAttribute('LS_UBP') = ''  then
        xData.setAttribute('LS_UBP', VarToStr( aXml.getAttribute(UbpOrg + '_ACCOUNT')));

      Ap_ls := xData.getAttribute('LS_UBP');

      // exchange #2572 - заполнение раздела AP
      // 4.1.	если заполнен «Счет» блока «РБС/АИФДБ», берем его
      // 4.2.	если заполнен «Счет» блока «ГРБС/ГАИФДБ», берем его
      if NOT FillLS_2572(  aXml.getAttribute( 'BUDGET_ID'),
                           aXml.getAttribute( 'DOCUMENTCLASS_ID'),
                           VarToStr( aXml.GetAttribute( 'ORG_ACC_ID')),
                           VarToStr( aXml.GetAttribute( 'MAIN_ACC_ID')),
                           xData,
                           'NAME_TOFK',
                           'KOD_TOFK')
        then begin
          // счет не найден - прерываем экспорт
          WriteInfo( 'Не найден ЛС в ЭД ' + DocCaptionStr( aXml));
          raise( 'Не найден ЛС в ЭД ' + DocCaptionStr( aXml));
        end;

      //По умолчанию берется из ORG_OFK_CODE (код ТОФК блока "От кого:")
      if xData.getAttribute('KOD_TOFK') = '' then
        if VarToStr( aXml.getAttribute(UbpOrg + '_OFK_CODE')) <> ''
          then xData.setAttribute('KOD_TOFK', aXml.getAttribute(UbpOrg + '_OFK_CODE'))
          else xData.setAttribute('KOD_TOFK', Ufk.getAttribute('NAME'));

      //По умолчанию берется из ORG_OFK_DESCRIPTION (наименование ТОФК блока "От кого:")
      if xData.getAttribute('NAME_TOFK') = '' then
        if VarToStr( aXml.getAttribute(UbpOrg + '_OFK_DESCRIPTION')) <> ''
          then xData.setAttribute('NAME_TOFK', VarToStr( aXml.getAttribute(UbpOrg + '_OFK_DESCRIPTION')))
          else xData.setAttribute('NAME_TOFK', Ufk.getAttribute('DESCRIPTION'));

      // exchange #2344 - задание на доработку
      // exchange #2451 - правка ошибки
      Exch2344_SetAttr_NAME_UBP_PAY_Ex( xData, aXml, 'NAME_UBP');



      xData.setAttribute(
              'NAME_BUD',
              QueryField( sqlBudgId,
                          [ aXml.getAttribute('BUDGET_ID')],
                          'CAPTION'));

      xData.setAttribute('NAME_FO', Fo.getAttribute('DESCRIPTION'));
      xData.setAttribute('DATE_UTV_R_R', '');

      // exchange #2703
      // всвязи с ошибкой названия поля в схеме (при автогенерации схем по
      // описаниям ТФФ) значение поля переносится в скрипт.
      xData.setAttribute( 'DATE_POD_RR',
                          aXml.getAttribute( 'MANAGER_SIG_DATE'));

      xData.setAttribute(
            'DATE_POD_RR',
            IfThen( xData.getAttribute( 'DATE_POD_RR') <> '',
                    FormatDateTime(
                          'dd.mm.yyyy',
                          XmlToDateTime(xData.getAttribute('DATE_POD_RR'))),
                    ''));

      xData.setAttribute(
            'DATA_POD_RR_ISP',
            IfThen( xData.getAttribute( 'DATA_POD_RR_ISP') <> '',
                    FormatDateTime(
                          'dd.mm.yyyy',
                          XmlToDateTime(xData.getAttribute('DATA_POD_RR_ISP'))),
                    ''));



      xData := xData.parentNode;

      // Информация о получателе расходного расписания и о расходном расписании (APRC)
      // exchange #2572 - сохраняем узел ЭД описания APRC
      xXmlNodeAPRC := aXml;
      xData := xData.appendChild(FillElementBySchema(aXml, 'APRC'));
      // exchange #2483 - сохраняем ссылку на раздел APRC
      xDataAPRC := xData;

      { #2344
        если в блоке "Получатель" заполнено поле "Орган, передавший полномочия",
        выгружать наименование организации из этого поля. на ID не смотрим!
        значение при отсутствие явного значения поля берется из схемы}
      if XmlAttrExists( aXml, 'REC_CREDENTIALS_NAME') then
        if (aXml.getAttribute('REC_CREDENTIALS_NAME') <> '')
          then xData.setAttribute( 'NAME_UBP',
                                  aXml.getAttribute('REC_CREDENTIALS_NAME'));

      xData.setAttribute('NOM_RR', Trim(xData.getAttribute('NOM_RR')));
      xData.setAttribute('DATE_FORM_RR', FormatDateTime('dd.mm.yyyy',
        XmlToDateTime(xData.getAttribute('DATE_FORM_RR'))));
      xData.setAttribute('DATE_UTV_RR', FormatDateTime('dd.mm.yyyy',
        XmlToDateTime(xData.getAttribute('DATE_UTV_RR'))));
      xData.setAttribute('KOD_UBP', aXml.getAttribute('REC_CODE'));
      if (aXml.getAttribute('ORG_ID') <> '') and
        ((HasOrgRole(aXml.getAttribute('ORG_ID'), '0')) and (Copy(aXml.getAttribute('ORG_ACCOUNT'),1 ,2) = '03')
        and (HasAccRole(aXml.getAttribute('ORG_ACC_ID'), '0'))) then
      begin
        xData.setAttribute('KOD_TOFK', aXml.getAttribute('REC_OFK_CODE'));
        xData.setAttribute('NAME_TOFK', aXml.getAttribute('REC_OFK_DESCRIPTION'));
      end
      else if (aXml.getAttribute('MAIN_OFK_ID') <> '') and
        (aXml.getAttribute('MAIN_OFK_ID') <> aXml.getAttribute('REC_OFK_ID')) then
        begin
          xData.setAttribute('KOD_TOFK', aXml.getAttribute('REC_OFK_CODE'));
          xData.setAttribute('NAME_TOFK', aXml.getAttribute('REC_OFK_DESCRIPTION'));
        end
      else if (aXml.getAttribute('ORG_OFK_ID') <> '') and
        (aXml.getAttribute('ORG_OFK_ID') <> aXml.getAttribute('REC_OFK_ID')) then
        begin
          xData.setAttribute('KOD_TOFK', aXml.getAttribute('REC_OFK_CODE'));
          xData.setAttribute('NAME_TOFK', aXml.getAttribute('REC_OFK_DESCRIPTION'));
        end
      else if ((aXml.getAttribute('MAIN_OFK_ID') = '') and (aXml.getAttribute('ORG_OFK_ID') = ''))
        and (Ufk.getAttribute('ID') <> aXml.getAttribute('REC_OFK_ID')) then
      begin
        xData.setAttribute('KOD_TOFK', aXml.getAttribute('REC_OFK_CODE'));
        xData.setAttribute('NAME_TOFK', aXml.getAttribute('REC_OFK_DESCRIPTION'));
      end;
      // заполняем поля специальных указаний
      xData.setAttribute('NOTE_RR', aXml.getAttribute('ADDITIONALNOTE'));
      xData.setAttribute('NOTE_CODE', GetNoteCode(aXml.getAttribute('SPECNOTE')));
      xData.setAttribute('TYPE_KBK', GetTypeKBK(aXml, aXml.getAttribute('BUDGET_ID')));

      // exchange #2676
      if NOT DoFill148_Exch2676( aXml, xData) then begin
        aMsgInfo.Add( FORMAT( 'Расходное расписание № %s, дата %s'
                          +' не выгружается: найдено несколько связанных ЗОР.',
                           [ TRIM( aXml.getAttribute( 'DOC_NUMBER')),
                             aXml.getAttribute( 'DOC_DATE')]));
        aBreakLoad := TRUE;
        EXIT;
      end;

      //блок бюджетных ассигнований APBASTR
//      Fill_APPBASTR( aXml, xData, Ap_ls);

      // суммы ассигн.проверяются в шапке ЭД, поскольку суммы ассигн и лимитов
      // в шапке ЭД суммируются из таких же полей в строках, хотя эти
      // суммы шапки ЭД на форме не отображаются.
      if (((Format('%0.2f', [StrToCurr(aXml.getAttribute('ASSIGN_AMT1'))]) <> '0.00') or
        (Format('%0.2f', [StrToCurr(aXml.getAttribute('ASSIGN_AMT2'))]) <> '0.00') or
        (Format('%0.2f', [StrToCurr(aXml.getAttribute('ASSIGN_AMT3'))]) <> '0.00'))
        and (Ap_ls <> aXml.getAttribute('REC_ACCOUNT'))) then
        begin

        // exchange #2631
        // если включена настройка "Выгружать только лимиты по строкам, где
        // доводятся и ассигнования, и лимиты", И блок лимитов бюджетных
        // обязательств (LIMIT_AMT1...LIMIT_AMT3) <>0, то поля
        // SUM_BA_1Y...SUM_BA_3Y заполняем нулями и блок APBASTR не формируем.
        xOutAPPBASTR := TRUE;
        if vCfg_LimByAssign then
          if (    (Format('%0.2f', [StrToCurr(aXml.getAttribute('LIMIT_AMT1'))]) <> '0.00')
               or (Format('%0.2f', [StrToCurr(aXml.getAttribute('LIMIT_AMT2'))]) <> '0.00')
               or (Format('%0.2f', [StrToCurr(aXml.getAttribute('LIMIT_AMT3'))]) <> '0.00'))
            then xOutAPPBASTR := FALSE;

        if NOT xOutAPPBASTR then begin

          // exchange #2631 - заполнение поле суммы нулями
          xData.setAttribute('SUM_BA_1Y', '0.00');
          xData.setAttribute('SUM_BA_2Y', '0.00');
          xData.setAttribute('SUM_BA_3Y', '0.00');
        end else begin


          xData.setAttribute('SUM_BA_1Y', Format('%0.2f', [StrToCurr(aXml.getAttribute('ASSIGN_AMT1'))]));
          xData.setAttribute('SUM_BA_2Y', Format('%0.2f', [StrToCurr(aXml.getAttribute('ASSIGN_AMT2'))]));
          xData.setAttribute('SUM_BA_3Y', Format('%0.2f', [StrToCurr(aXml.getAttribute('ASSIGN_AMT3'))]));

          // exchange #3095
          DoFill_APPBASTR_( aXml, xData);
          (*
          for j := 0 to aXml.childNodes.length - 1 do begin
            xDocLineXml := aXml.childNodes.items[j];
            // проверяем на заполненность сумм в каждой из строк
            if (   (Format('%0.2f', [StrToCurr(xDocLineXml.getAttribute('ASSIGN_AMT1'))]) <> '0.00')
                or (Format('%0.2f', [StrToCurr(xDocLineXml.getAttribute('ASSIGN_AMT2'))]) <> '0.00')
                or (Format('%0.2f', [StrToCurr(xDocLineXml.getAttribute('ASSIGN_AMT3'))]) <> '0.00'))
              then begin
                // заполняем APBASTR
                xDataLineXml := xData.appendChild(
                                      FillElementBySchema(
                                                      xDocLineXml, 'APBASTR'));
                xDataLineXml.setAttribute(
                          'KBK',
                          GetRuleKBKLine( xDocLineXml,
                                          // в строках тоже есть атрибут бюджета
                                          xDocLineXml.getAttribute('BUDGET_ID')));
                xDataLineXml.setAttribute(
                          'ADD_KLASS',
                          Get_ADD_KLASS_TFF9( xDocLineXml, param_AddKlass));
              end;
          end;//for//
          *)
        end;
      end; {End APBASTR}

      // блок лимитов бюджетных обязательств APLBOSTR
      if (Format('%0.2f', [StrToCurr(aXml.getAttribute('LIMIT_AMT1'))]) <> '0.00') or
        (Format('%0.2f', [StrToCurr(aXml.getAttribute('LIMIT_AMT2'))]) <> '0.00') or
        (Format('%0.2f', [StrToCurr(aXml.getAttribute('LIMIT_AMT3'))]) <> '0.00') then
      begin
        xData.setAttribute('SUM_LBO_1Y', Format('%0.2f', [StrToCurr(aXml.getAttribute('LIMIT_AMT1'))]));
        xData.setAttribute('SUM_LBO_2Y', Format('%0.2f', [StrToCurr(aXml.getAttribute('LIMIT_AMT2'))]));
        xData.setAttribute('SUM_LBO_3Y', Format('%0.2f', [StrToCurr(aXml.getAttribute('LIMIT_AMT3'))]));
        DoFill_APLBOSTR_( aXml, xData);
        {
        for j := 0 to aXml.childNodes.length - 1 do
        begin
          aXml := aXml.childNodes.items[j];
          // проверяем на заполненность сумм в каждой из строк
          if (Format('%0.2f', [StrToCurr(aXml.getAttribute('LIMIT_AMT1'))]) <> '0.00') or
            (Format('%0.2f', [StrToCurr(aXml.getAttribute('LIMIT_AMT2'))]) <> '0.00') or
            (Format('%0.2f', [StrToCurr(aXml.getAttribute('LIMIT_AMT3'))]) <> '0.00') then
          // заполняем APLBOSTR
          begin
            xData := xData.appendChild(FillElementBySchema(aXml, 'APLBOSTR'));
            // exchange #3062 - отменен КОСГУ
            xData.setAttribute( 'KBK',
                                GetRuleKBKLine( aXml,
                                                aXml.getAttribute('BUDGET_ID'),
                                                '',
                                                FALSE));
            xData.setAttribute('ADD_KLASS', Get_ADD_KLASS_TFF9(aXml, param_AddKlass));
            xData := xData.parentNode;
            aXml := aXml.parentNode;
          end
          else
            aXml := aXml.parentNode;
        end;
        }
      end;

      {
      if ((Format('%0.2f', [StrToCurr(aXml.getAttribute('AMOUNT'))]) <> '0.00')
        and (Ap_ls <> aXml.getAttribute('REC_ACCOUNT'))) then
        }
      // exchange #3095 - унификация кода
      if (CurrAttributeIsNotZero_( aXml, 'AMOUNT', xCurr)
          and (Ap_ls <> aXml.getAttribute('REC_ACCOUNT'))) then begin
        xData.setAttribute( 'SUM_POF_1Y', Format( '%0.2f', [ xCurr]));//StrToCurr(aXml.getAttribute('AMOUNT'))]));
        // exchange #2507
        // в начале должны идти все APLBOSTR, а потом APPOFSTR
        // т.е. придется выполнять вложенный цикл дважды: в начале для APLBOSTR
        // потом для APPOFSTR.
        // APLBOSTR
        // exchange #3095
        DoFill_APLBOSTR_2411_( aXml, xData);
        {
        for j := 0 to aXml.childNodes.length - 1 do
        begin
          aXml := aXml.childNodes.items[j];
          // проверяем на заполненность сумм в каждой из строк
          if Format('%0.2f', [StrToCurr(aXml.getAttribute('AMOUNT'))]) <> '0.00'
            then Exch2411_FillData( xData, aXml);
          aXml := aXml.parentNode;
        end;}

        // APPOFSTR
        DoFill_APPOFSTR_( aXml, xData);
        {
        for j := 0 to aXml.childNodes.length - 1 do
        begin
          aXml := aXml.childNodes.items[j];
          // проверяем на заполненность сумм в каждой из строк
          if Format('%0.2f', [StrToCurr(aXml.getAttribute('AMOUNT'))]) <> '0.00' then
          begin
            xData := xData.appendChild(FillElementBySchema(aXml, 'APPOFSTR'));
            // exchange #3062 - отменен КОСГУ
            xData.setAttribute( 'KBK',
                                GetRuleKBKLine( aXml,
                                                aXml.getAttribute('BUDGET_ID'),
                                                '',
                                                FALSE));
            xData.setAttribute('ADD_KLASS', Get_ADD_KLASS_TFF9(aXml, param_AddKlass));
            xData := xData.parentNode;

            aXml := aXml.parentNode;
          end
          else
            aXml := aXml.parentNode;
        end;
        }
      end;


      //запполняем APREORG согласно Exchange #1810
      if (Pos('02', GetNoteCode(aXml.getAttribute('SPECNOTE'))) <> 0) then
      begin
        xData := xData.appendChild(FillElementBySchema(aXml, 'APREORG'));
        if xData.getAttribute('DATE_OTR_RR') <> '' then
          xData.setAttribute('DATE_OTR_RR', FormatDateTime('dd.mm.yyyy',
            XmlToDateTime(xData.getAttribute('DATE_OTR_RR'))));
        xData := xData.parentNode;
      end;


      { exchange #2483
        при включенной настройке «Формировать блок Лимиты бюджетных
        обязательств, при доведении ПОФ на ЛСФК» дополнительно к имеющемуся
        функционалу заполнения при выгрузке ЭД «Расходное расписание» (148),
        ЭД «Реестр расходных расписаний» (149) заполнять поле APRC.SUM_LBO_1Y
        суммой поля APRC.SUM_POF_1Y. }
      if param_Exch2411 then begin
  
        if (aXml.GetAttribute( 'DOCUMENTCLASS_ID') in ['148','149'])
          then xDataAPRC.SetAttribute(
                        'SUM_LBO_1Y',
                        VarToStr( xDataAPRC.GetAttribute( 'SUM_POF_1Y')));
  
      end;

      // exchange #2684 - заполнение APRC по другому
      if FillAPRC_2684( aXml, xDataAPRC) then begin
        // exchange #2572 - заполнение раздела APRC
        FillAPRC_2572( xXmlNodeAPRC.GetAttribute( 'DOCUMENTCLASS_ID'),
                        VarToStr( xXmlNodeAPRC.GetAttribute( 'REC_ACC_ID')),
                        xDataAPRC);
      end;
      except
        ExceptionLog( 'Сбой Export_148');
    end;

end;

procedure Export_Other( aXml: Variant;
                        var aData: Variant;
                        UbpOrg: string;
                        Ufk, Fo: Variant;
                        aMsgInfo: TStringList;
                        var aBreakLoad: boolean);
var
  i, j, z: Integer;
//  UbpOrg,
  Ap_ls: String;
//  Ufk, Fo, XmlOrg: Variant;
  xNode: Variant;
  xData: Variant;
  xDataAPRC: Variant;
  xXmlNode: Variant;
  xXmlNodeAPRC: Variant;
  xCurr: Currency;
  xOutAPPBASTR: boolean;
begin

    try
      xXmlNode := aXml;
      for j := 0 to aXml.childNodes.length - 1 do begin

        // exchange #2631 - проверяем строки РР, вложенного в Реестр РР
        if NOT CheckED148( xXmlNode.childNodes.items[j], aMsgInfo, aBreakLoad)
          then begin
            // здесь пишем сообщение, что РРР не выгружается
            WriteInfo( FORMAT( 'Реестр расходных расписаний № %s, дата %s,'
                    +' не выгружено, если хотя бы одно расходное расписание,'
                    +' входящее в реестр не прошло проверку.',
                     [ TRIM( aXml.getAttribute( 'DOC_NUMBER')),
                       aXml.getAttribute( 'DOC_DATE')]));
            EXIT;
          end;

//        xXmlNode := aXml.childNodes.item[j];
        Ap_ls := '';
        // заполняем AP
        xData := aData.appendChild(FillElementBySchema(xXmlNode, 'AP'));

        xData.setAttribute('NOM_R_RR', Trim(xData.getAttribute('NOM_R_RR')));
        xData.setAttribute(
                'DATE_R_RR',
                FormatDateTime( 'dd.mm.yyyy',
                                XmlToDateTime(xData.getAttribute('DATE_R_RR'))));

        if (xData.getAttribute('GLAVA_GRS') <> '')
            and (xData.getAttribute('GLAVA_GRS') <> '0')
          then xData.setAttribute(
                    'GLAVA_GRS',
                    StringReplace(
                          Format( '%3s',
                                  [xData.getAttribute('GLAVA_GRS')]), ' ', '0'))
          else xData.setAttribute('GLAVA_GRS','');

        if xData.getAttribute('LS_UBP') = ''
          then xData.setAttribute(
                        'LS_UBP',
                        VarToStr( xXmlNode.getAttribute(UbpOrg + '_ACCOUNT')));

        Ap_ls := xData.getAttribute('LS_UBP');

        // exchange #2572 - заполнение раздела AP
        // 4.1.	если заполнен «Счет» блока «РБС/АИФДБ», берем его
        // 4.2.	если заполнен «Счет» блока «ГРБС/ГАИФДБ», берем его
        if NOT FillLS_2572(  xXmlNode.getAttribute( 'BUDGET_ID'),
                             xXmlNode.getAttribute( 'DOCUMENTCLASS_ID'),
                             VarToStr( xXmlNode.GetAttribute( 'ORG_ACC_ID')),
                             VarToStr( xXmlNode.GetAttribute( 'MAIN_ACC_ID')),
                             xData,
                             'NAME_TOFK',
                             'KOD_TOFK')
          then begin
            // счет не найден - прерываем экспорт
            WriteInfo( 'Не найден ЛС в ЭД ' + DocCaptionStr( xXmlNode));
            raise( 'Не найден ЛС в ЭД ' + DocCaptionStr( xXmlNode));
          end;

        //По умолчанию берется из ORG_OFK_CODE (код ТОФК блока "От кого:")
        if xData.getAttribute('KOD_TOFK') = '' then
          if VarToStr( xXmlNode.getAttribute(UbpOrg + '_OFK_CODE')) <> ''
            then xData.setAttribute('KOD_TOFK', VarToStr( xXmlNode.getAttribute(UbpOrg + '_OFK_CODE')))
            else xData.setAttribute('KOD_TOFK', Ufk.getAttribute('NAME'));

        //По умолчанию берется из ORG_OFK_DESCRIPTION (наименование ТОФК блока "От кого:")
        if xData.getAttribute('NAME_TOFK') = '' then
          if VarToStr( xXmlNode.getAttribute(UbpOrg + '_OFK_DESCRIPTION')) <> ''
            then xData.setAttribute('NAME_TOFK', VarToStr( xXmlNode.getAttribute(UbpOrg + '_OFK_DESCRIPTION')))
            else xData.setAttribute('NAME_TOFK', Ufk.getAttribute('DESCRIPTION'));

        // exchange #2344 - задание на доработку
        // exchange #2451 - правка ошибки
        Exch2344_SetAttr_NAME_UBP_PAY_Ex( xData, xXmlNode, 'NAME_UBP');

        xData.setAttribute(
                'NAME_BUD',
                QueryField( sqlBudgId,
                            [xXmlNode.getAttribute('BUDGET_ID')],
                            'CAPTION'));

        xData.setAttribute('NAME_FO', Fo.getAttribute('DESCRIPTION'));
        xData.setAttribute(
                'DATE_UTV_R_R',
                FormatDateTime(
                          'dd.mm.yyyy',
                          XmlToDateTime(xData.getAttribute('DATE_UTV_R_R'))));

        // exchange #2703
        // всвязи с ошибкой названия поля в схеме (при автогенерации схем по
        // описаниям ТФФ) значение поля переносится в скрипт.
        xData.setAttribute( 'DATE_POD_RR',
                            xXmlNode.getAttribute( 'EXECUTOR_SIG_DATE'));
        xData.setAttribute(
                'DATE_POD_RR',
                IfThen(
                    xData.getAttribute('DATE_POD_RR') <> '',
                    FormatDateTime(
                            'dd.mm.yyyy',
                            XmlToDateTime(xData.getAttribute('DATE_POD_RR'))),
                    ''));

        //Exchange #2057 поле DATA_POD_RR_ISP
        xData.setAttribute(
                'DATA_POD_RR_ISP',
                IfThen(
                    xXmlNode.childNodes.items[j].getAttribute('EXECUTOR_SIG_DATE') <> '',
                    FormatDateTime(
                            'dd.mm.yyyy',
                            XmlToDateTime(xXmlNode.childNodes.items[j].getAttribute('EXECUTOR_SIG_DATE'))), ''));
        xData := xData.parentNode;
        // Информация о получателе расходного расписания и о расходном расписании (APRC)
        xXmlNode := xXmlNode.childNodes.items[j];
        // exchange #2572 - сохраняем ссылку на раздел APRC в ЭД
        xXmlNodeAPRC := xXmlNode;
        xData := xData.appendChild(FillElementBySchema(xXmlNode, 'APRC'));
        // exchange #2483 - сохраняем ссылку на раздел APRC
        xDataAPRC := xData;

      { #2344
        если в блоке "Получатель" заполнено поле "Орган, передавший полномочия",
        выгружать наименование организации из этого поля.на ID не смотрим!
        значение при отсутствие явного значения поля берется из схемы}
      if XmlAttrExists( xXmlNode, 'REC_CREDENTIALS_NAME') then
        if (xXmlNode.getAttribute('REC_CREDENTIALS_NAME') <> '')
          then xData.setAttribute( 'NAME_UBP',
                                  xXmlNode.getAttribute('REC_CREDENTIALS_NAME'));

        xData.setAttribute('NOM_RR', Trim(xData.getAttribute('NOM_RR')));
        xData.setAttribute('DATE_FORM_RR', FormatDateTime('dd.mm.yyyy',
          XmlToDateTime(xData.getAttribute('DATE_FORM_RR'))));
        xData.setAttribute('DATE_UTV_RR', FormatDateTime('dd.mm.yyyy',
          XmlToDateTime(xData.getAttribute('DATE_UTV_RR'))));

        if (xXmlNode.getAttribute('ORG_ID') <> '') and
          ((HasOrgRole(xXmlNode.getAttribute('ORG_ID'), '0')) and
          (Copy(xXmlNode.getAttribute('ORG_ACCOUNT'),1 ,2) = '03')
          and (HasAccRole(xXmlNode.getAttribute('ORG_ACC_ID'), '0'))) then
        begin
          xData.setAttribute('KOD_TOFK', xXmlNode.getAttribute('REC_OFK_CODE'));
          xData.setAttribute('NAME_TOFK', xXmlNode.getAttribute('REC_OFK_DESCRIPTION'));
        end
        else if (xXmlNode.getAttribute('MAIN_OFK_ID') <> '') and
          (xXmlNode.getAttribute('MAIN_OFK_ID') <> xXmlNode.getAttribute('REC_OFK_ID')) then
          begin
            xData.setAttribute('KOD_TOFK', xXmlNode.getAttribute('REC_OFK_CODE'));
            xData.setAttribute('NAME_TOFK', xXmlNode.getAttribute('REC_OFK_DESCRIPTION'));
          end
        else if (xXmlNode.getAttribute('ORG_OFK_ID') <> '') and
          (xXmlNode.getAttribute('ORG_OFK_ID') <> xXmlNode.getAttribute('REC_OFK_ID')) then
          begin
            xData.setAttribute('KOD_TOFK', xXmlNode.getAttribute('REC_OFK_CODE'));
            xData.setAttribute('NAME_TOFK', xXmlNode.getAttribute('REC_OFK_DESCRIPTION'));
          end
        else if ((xXmlNode.getAttribute('MAIN_OFK_ID') = '') and (xXmlNode.getAttribute('ORG_OFK_ID') = ''))
          and (Ufk.getAttribute('ID') <> xXmlNode.getAttribute('REC_OFK_ID')) then
        begin
          xData.setAttribute('KOD_TOFK', xXmlNode.getAttribute('REC_OFK_CODE'));
          xData.setAttribute('NAME_TOFK', xXmlNode.getAttribute('REC_OFK_DESCRIPTION'));
        end;
        xData.setAttribute('TYPE_KBK', GetTypeKBK(xXmlNode, xXmlNode.getAttribute('BUDGET_ID')));

        //блок бюджетных ассигнований APBASTR
//        Fill_APPBASTR( xXmlNode, xData, Ap_ls);
        if (((Format('%0.2f', [StrToCurr(xXmlNode.getAttribute('ASSIGN_AMT1'))]) <> '0.00') or
          (Format('%0.2f', [StrToCurr(xXmlNode.getAttribute('ASSIGN_AMT2'))]) <> '0.00') or
          (Format('%0.2f', [StrToCurr(xXmlNode.getAttribute('ASSIGN_AMT3'))]) <> '0.00'))
          and (Ap_ls <> xXmlNode.getAttribute('REC_ACCOUNT'))) then
          begin
        // exchange #2631
        // если включена настройка "Выгружать только лимиты по строкам, где
        // доводятся и ассигнования, и лимиты", И блок лимитов бюджетных
        // обязательств (LIMIT_AMT1...LIMIT_AMT3) <>0, то поля
        // SUM_BA_1Y...SUM_BA_3Y заполняем нулями и блок APBASTR не формируем.

        xOutAPPBASTR := TRUE;
        if vCfg_LimByAssign then
          if (   (Format('%0.2f', [StrToCurr(xXmlNode.getAttribute('LIMIT_AMT1'))]) <> '0.00')
              or (Format('%0.2f', [StrToCurr(xXmlNode.getAttribute('LIMIT_AMT2'))]) <> '0.00')
              or (Format('%0.2f', [StrToCurr(xXmlNode.getAttribute('LIMIT_AMT3'))]) <> '0.00'))
            then xOutAPPBASTR := FALSE;

        if NOT xOutAPPBASTR then begin

          // exchange #2631 - заполнение поле суммы нулями
          xData.setAttribute('SUM_BA_1Y', '0.00');
          xData.setAttribute('SUM_BA_2Y', '0.00');
          xData.setAttribute('SUM_BA_3Y', '0.00');
        end else begin


            xData.setAttribute('SUM_BA_1Y', Format('%0.2f', [StrToCurr(xXmlNode.getAttribute('ASSIGN_AMT1'))]));
            xData.setAttribute('SUM_BA_2Y', Format('%0.2f', [StrToCurr(xXmlNode.getAttribute('ASSIGN_AMT2'))]));
            xData.setAttribute('SUM_BA_3Y', Format('%0.2f', [StrToCurr(xXmlNode.getAttribute('ASSIGN_AMT3'))]));

            // exchange #3095
            // исправлена выгрузка блока APPBASTR для РРР
            for j := 0 to xXmlNode.childNodes.length - 1
              do DoFill_APPBASTR_( xXmlNode.childNodes.items[ j], xData);
              {
            for j := 0 to xXmlNode.childNodes.length - 1 do
            begin
              xXmlNode := xXmlNode.childNodes.items[j];
              for z := 0 to xXmlNode.childNodes.length - 1 do
              begin
                xXmlNode := xXmlNode.childNodes.items[z];
                // проверяем на заполненность сумм в каждой из строк
                if (Format('%0.2f', [StrToCurr(xXmlNode.getAttribute('ASSIGN_AMT1'))]) <> '0.00') or
                  (Format('%0.2f', [StrToCurr(xXmlNode.getAttribute('ASSIGN_AMT2'))]) <> '0.00') or
                  (Format('%0.2f', [StrToCurr(xXmlNode.getAttribute('ASSIGN_AMT3'))]) <> '0.00') then
                // заполняем APBASTR
                begin
                  xData := xData.appendChild(FillElementBySchema(xXmlNode, 'APBASTR'));
                  xData.setAttribute('KBK', GetRuleKBKLine(xXmlNode, xXmlNode.getAttribute('BUDGET_ID')));
                  xData.setAttribute('ADD_KLASS', Get_ADD_KLASS_TFF9(xXmlNode, param_AddKlass));
                  xData := xData.parentNode;
                  xXmlNode := xXmlNode.parentNode;
                end
                else
                  xXmlNode := xXmlNode.parentNode;
              end;
              xXmlNode := xXmlNode.parentNode;
            end;
            }
          end;
        end; {End APBASTR}

        // блок лимитов бюджетных обязательств APLBOSTR
        if (Format('%0.2f', [StrToCurr(xXmlNode.getAttribute('LIMIT_AMT1'))]) <> '0.00') or
          (Format('%0.2f', [StrToCurr(xXmlNode.getAttribute('LIMIT_AMT2'))]) <> '0.00') or
          (Format('%0.2f', [StrToCurr(xXmlNode.getAttribute('LIMIT_AMT3'))]) <> '0.00') then
        begin
          xData.setAttribute('SUM_LBO_1Y', Format('%0.2f', [StrToCurr(xXmlNode.getAttribute('LIMIT_AMT1'))]));
          xData.setAttribute('SUM_LBO_2Y', Format('%0.2f', [StrToCurr(xXmlNode.getAttribute('LIMIT_AMT2'))]));
          xData.setAttribute('SUM_LBO_3Y', Format('%0.2f', [StrToCurr(xXmlNode.getAttribute('LIMIT_AMT3'))]));
          for j := 0 to xXmlNode.childNodes.length - 1
            do DoFill_APLBOSTR_( xXmlNode.childNodes.items[j], xData);
            (*
            xXmlNode := xXmlNode.childNodes.items[j];
            for z := 0 to xXmlNode.childNodes.length - 1 do begin
              xXmlNodeZ := xXmlNode.childNodes.items[z];
              // проверяем на заполненность сумм в каждой из строк
              if (Format('%0.2f', [StrToCurr(xXmlNodeZ.getAttribute('LIMIT_AMT1'))]) <> '0.00') or
                (Format('%0.2f', [StrToCurr(xXmlNodeZ.getAttribute('LIMIT_AMT2'))]) <> '0.00') or
                (Format('%0.2f', [StrToCurr(xXmlNodeZ.getAttribute('LIMIT_AMT3'))]) <> '0.00') then
              // заполняем APLBOSTR
              begin
                // exchange #3062 - отменен КОСГУ
                xKBK := GetRuleKBKLine( xXmlNodeZ,
                                        xXmlNodeZ.getAttribute('BUDGET_ID'),
                                        '',
                                        FALSE);
                xADD_KLASS := Get_ADD_KLASS_TFF9(xXmlNodeZ, param_AddKlass);
                // exchange #3095
                // удаляем строки с одинаковым кбк + код цели
                s := xKBK + xADD_KLASS;
                xIndex := xL_APLBOSTR_KBK.IndexOf( s);
                if (xIndex = -1) then begin
                  // если такого кбк в списке нет - сохраняем новый код
                  // и кол-во узлов Data - это укажет индекс узла APLBOSTR
                  // для этого кбк.
                  xL_APLBOSTR_KBK.Add( s);
                  xL_APLBOSTR_IndexData.Add( INTTOSTR( xData.ChildNodes.Length));

                  xData_APLBOSTR := xData.appendChild(
                                         FillElementBySchema( xXmlNodeZ,
                                                              'APLBOSTR'));

                  xData_APLBOSTR.setAttribute( 'KBK', xKBK);

                  xData_APLBOSTR.setAttribute( 'ADD_KLASS', xADD_KLASS);
                end else begin
                  // такой APLBOSTR уже есть - добавляем суммы в этом разделе
                  xData_APLBOSTR := xData.ChildNodes.Items[
                                        STRTOINT( xL_APLBOSTR_IndexData[
                                                                    xIndex])];
                  SummCurrAttribute_( xData_APLBOSTR,
                                      'SUM_LBO_Y1',
                                      xXmlNodeZ.getAttribute('LIMIT_AMT1'));
                  SummCurrAttribute_( xData_APLBOSTR,
                                      'SUM_LBO_Y2',
                                      xXmlNodeZ.getAttribute('LIMIT_AMT2'));
                  SummCurrAttribute_( xData_APLBOSTR,
                                      'SUM_LBO_Y3',
                                      xXmlNodeZ.getAttribute('LIMIT_AMT3'));
                end;
              end;
{
                  xData := xData.parentNode;
                  xXmlNode := xXmlNode.parentNode;
              end
              else
                xXmlNode := xXmlNode.parentNode;
                }
            end;//for//
            xXmlNode := xXmlNode.parentNode;
          end;
          *)
        end;

        {
        if ((Format('%0.2f', [StrToCurr(xXmlNode.getAttribute('AMOUNT'))]) <> '0.00')
          and (Ap_ls <> xXmlNode.getAttribute('REC_ACCOUNT'))) then
          }
        // exchange #3095 - унификация кода
        if (CurrAttributeIsNotZero_( xXmlNode, 'AMOUNT', xCurr)
            and (Ap_ls <> xXmlNode.getAttribute('REC_ACCOUNT'))) then begin
          xData.setAttribute('SUM_POF_1Y', Format('%0.2f', [ xCurr]));//StrToCurr(xXmlNode.getAttribute('AMOUNT'))]));
          // exchange #2507
          // в начале должны идти все APLBOSTR, а потом APPOFSTR
          // т.е. придется выполнять вложенный цикл дважды: в начале для APLBOSTR
          // потом для APPOFSTR.
          // APLBOSTR
          // exchange #3095 - унификация кода
          for j := 0 to xXmlNode.childNodes.length - 1
            do DoFill_APLBOSTR_2411_( xXmlNode.childNodes.items[ j], xData);
            {
          for j := 0 to xXmlNode.childNodes.length - 1 do begin
            xXmlNode := xXmlNode.childNodes.items[j];
            for z := 0 to xXmlNode.childNodes.length - 1 do begin
              xXmlNode := xXmlNode.childNodes.items[z];
              // проверяем на заполненность сумм в каждой из строк
              if (Format('%0.2f', [StrToCurr(xXmlNode.getAttribute('AMOUNT'))]) <> '0.00')
                then Exch2411_FillData( xData, xXmlNode);
              xXmlNode := xXmlNode.parentNode;
            end;//for//
            xXmlNode := xXmlNode.parentNode;
          end;//for//
          }

          // APPOFSTR
          for j := 0 to xXmlNode.childNodes.length - 1
            do DoFill_APPOFSTR_( xXmlNode.childNodes.items[ j], xData);
            {
          begin
            xXmlNode := xXmlNode.childNodes.items[j];
            for z := 0 to xXmlNode.childNodes.length - 1 do
            begin
              xXmlNode := xXmlNode.childNodes.items[z];
              // проверяем на заполненность сумм в каждой из строк
              if (Format('%0.2f', [StrToCurr(xXmlNode.getAttribute('AMOUNT'))]) <> '0.00') then
              begin
                xData := xData.appendChild(FillElementBySchema(xXmlNode, 'APPOFSTR'));
                // exchange #3062 - отменен КОСГУ
                xData.setAttribute( 'KBK',
                                    GetRuleKBKLine( xXmlNode,
                                                    xXmlNode.getAttribute('BUDGET_ID'),
                                                    '',
                                                    FALSE));
                xData.setAttribute('ADD_KLASS', Get_ADD_KLASS_TFF9(xXmlNode, param_AddKlass));
                xData := xData.parentNode;

                xXmlNode := xXmlNode.parentNode;
              end
              else
                xXmlNode := xXmlNode.parentNode;
            end;
            xXmlNode := xXmlNode.parentNode;
          end;}
        end;{End APPOFSTR}

        { exchange #2483
          при включенной настройке «Формировать блок Лимиты бюджетных
          обязательств, при доведении ПОФ на ЛСФК» дополнительно к имеющемуся
          функционалу заполнения при выгрузке ЭД «Расходное расписание» (148),
          ЭД «Реестр расходных расписаний» (149) заполнять поле APRC.SUM_LBO_1Y
          суммой поля APRC.SUM_POF_1Y. }
        if param_Exch2411 then begin
    
          if (xXmlNode.GetAttribute( 'DOCUMENTCLASS_ID') in ['148','149'])
            then xDataAPRC.SetAttribute(
                          'SUM_LBO_1Y',
                          VarToStr( xDataAPRC.GetAttribute( 'SUM_POF_1Y')));
  
        end;

        // exchange #2684 - заполнение APRC по другому
        if FillAPRC_2684( xXmlNode, xDataAPRC) then begin
          // exchange #2572 - заполнение раздела APRC
          FillAPRC_2572( xXmlNodeAPRC.GetAttribute( 'DOCUMENTCLASS_ID'),
                          VarToStr( xXmlNodeAPRC.GetAttribute( 'REC_ACC_ID')),
                          xDataAPRC);
        end;

//        xData := xData.parentNode;
        xXmlNode := xXmlNode.parentNode;
      end;//for//
      except
        ExceptionLog( 'Сбой Export_Other');
    end;

end;


function MakeFormat_TFF9(Xml: Variant): Boolean;
var
  i, j, z: Integer;
  UbpOrg, Ap_ls, ubpCode: String;
  Ufk, Fo, XmlOrg: Variant;
  xNode: Variant;
  xBreakLoad: boolean;
  xMsgInfo: TStringList;
begin

    try
      Result := False;
      Xml := Xml.documentElement;
      Ufk := GetTofkByBuh(Xml.childNodes.item[0].getAttribute('BUDGET_ID'));
      if Ufk.documentElement.childNodes.Length = 0 then
        Raise('Не удалось получить реквизиты организации ТОФК. ' +
          'Проверьте заполение счета в АЦК "Бухгалтерия-Настройка счетов-Счета ФО-' +
          'Основной бюджетный счет".');
      Ufk := Ufk.documentElement.childNodes.Item[0];
      Fo := GetOrgByBudget(Xml.childNodes.item[0].getAttribute('BUDGET_ID'));
      if Fo.documentElement.childNodes.Length <> 1 then
        Fo := QueryXml(sqlOrgByBudget, [Xml.childNodes.item[0].getAttribute('BUDGET_ID')]);
      Fo := Fo.documentElement.childNodes.Item[0];
      UbpOrg := IfThen(Xml.childNodes.Item[0].getAttribute('DOCUMENTCLASS_ID') = '148',
        'MAIN', 'MAINORG');

      if Xml.childNodes.Item[0].getAttribute(UbpOrg + '_CODE') <> '' then
        ubpCode := Xml.childNodes.Item[0].getAttribute(UbpOrg + '_CODE')
      else
        ubpCode := FO.getAttribute('NAME');
      if (LENGTH( ubpCode) <> 8) then
      begin
        WriteInfo( 'Код организации-клиента (KOD_UBP) имеет длину, отличную от допустимой (8 символов). Значение будет очищено');
        ubpCode := '';
      end;

      FileOut := GetFileName(ubpCode, 'AP', XmlToDateTime(Xml.getAttribute('EXCH_DATE')),
      Xml.getAttribute('EXCH_PACKET'), FileOutIsLocalNet, FileOutOrgCodeIsFk);

      WriteLog('Наименование формируемого файла: ' + FileOut, True);
      Data := Data.documentElement;
      WriteLog('Заполнение данных файла: ' + FileOut, True);
      Data := Data.appendChild(FillElementBySchema(Xml, 'FK'));
      Data.setAttribute('FORM_VER', AppVersion);
      Data := Data.parentNode;
      Data := Data.appendChild(FillElementBySchema(Xml.childNodes.Item[0], 'FROM'));

      { #2344
        если Организация в группе полей РБС/ПБС/АИФДБ блока "От кого" имеет роль
        Бюджетное или Автономное учреждение и Счет имеет признак "Переданные
        полномочия ПБС", выгружать в поле значение "6".
        за основу берется первый вложенный документ (согласовано с АО) }
      xNode := Xml.childNodes.Item[0];
      Data.setAttribute(
          'BUDG_LEVEL',
          IfThenElseStr(
              ExistsRolesForOrg( xNode.getAttribute('ORG_ID'), '18,19') AND
              ExistsCredentialsFlagForOrgAccount( xNode.getAttribute('ORG_ACC_ID')),
                '6',
                GetBudgLevel(Xml.childNodes.Item[0].getAttribute('BUDGET_ID'))));

      //По умолчанию заполняется значением ORG_CODE (код РБС/ПБС/АИФ блока "От кого:")
      if Data.getAttribute('KOD_UBP') = '' then
        Data.setAttribute('KOD_UBP', ubpCode);
      //По умолчанию заполняется значением ORG_Description (наименование РБС/ПБС/АИФ блока "От кого:")
      if Data.getAttribute('CNAME_UBP') = '' then
        if Xml.childNodes.Item[0].getAttribute(UbpOrg + '_DESCRIPTION') <> '' then
          Data.setAttribute('CNAME_UBP', Xml.childNodes.Item[0].getAttribute(UbpOrg + '_DESCRIPTION'))
        else
          Data.setAttribute('CNAME_UBP', Fo.getAttribute('DESCRIPTION'));
      Data := Data.parentNode;

      Data := Data.appendChild(FillElementBySchema(Xml.childNodes.Item[0], 'TO'));

      // exchange #2572 - заполнение раздела TO
      // 4.1.	если заполнен «Счет» блока «РБС/АИФДБ», берем его
      // 4.2.	если заполнен «Счет» блока «ГРБС/ГАИФДБ», берем его
      if NOT FillLS_2572(  xNode.getAttribute( 'BUDGET_ID'),
                           xNode.getAttribute( 'DOCUMENTCLASS_ID'),
                           VarToStr( xNode.GetAttribute( 'ORG_ACC_ID')),
                           VarToStr( xNode.GetAttribute( 'MAIN_ACC_ID')),
                           Data,
                           'CNAME_TOFK',
                           'KOD_TOFK')
        then begin
          // счет не найден - прерываем экспорт
          WriteInfo( 'Не найден ЛС в ЭД ' + DocCaptionStr( xNode));
          raise( 'Не найден ЛС в ЭД ' + DocCaptionStr( xNode));
        end;

      //По умолчанию берется из ORG_OFK_CODE (код ТОФК блока "От кого:")
      if Data.getAttribute('KOD_TOFK') = '' then
        if Xml.childNodes.Item[0].getAttribute(UbpOrg + '_OFK_CODE') <> ''
          then Data.setAttribute('KOD_TOFK', Xml.childNodes.Item[0].getAttribute(UbpOrg + '_OFK_CODE'))
          else Data.setAttribute('KOD_TOFK', Ufk.getAttribute('NAME'));

      //По умолчанию берется из ORG_OFK_DESCRIPTION (наименование ТОФК блока "От кого:")
      if Data.getAttribute('CNAME_TOFK') = '' then
        if Xml.childNodes.Item[0].getAttribute(UbpOrg + '_OFK_DESCRIPTION') <> ''
          then Data.setAttribute('CNAME_TOFK', Xml.childNodes.Item[0].getAttribute(UbpOrg + '_OFK_DESCRIPTION'))
          else Data.setAttribute('CNAME_TOFK', Ufk.getAttribute('DESCRIPTION'));

      Data := Data.parentNode;
      ProgressBar.Max := Xml.childNodes.length;

      //Информация об УБП и о реестре расходных расписаний (AP)
      xBreakLoad := FALSE;    // exchange #2631 - флаг прерывания загрузки

      xMsgInfo:= TStringList.Create;
      try
        for i := 0 to Xml.childNodes.length - 1 do
        begin
          ProgressBar.Position := i;
          if Xml.childNodes.Item[i].getAttribute('DOCUMENTCLASS_ID') = 148
            then Export_148( Xml.childNodes.items[i], Data, UbpOrg, Ufk, Fo, xMsgInfo, xBreakLoad)
            else Export_Other( Xml.childNodes.items[i], Data, UbpOrg, Ufk, Fo, xMsgInfo, xBreakLoad);
    {
          // exchange #2631
          // если обнаружено прерывание загрузки - прерываем дальнейшую обработку
          // файла
          if xBreakLoad then begin
            Result := FALSE;
            EXIT;
          end;
          }
        end;//for//
        Data := Data.ownerDocument;

        Xml := Xml.ownerDocument;

    

        // exchange #2631
        // из-за того, что прерывание выгрузки сделано раньше по наличию журнала
        // info, о чтобы добавить сообщения из #2631 в журнал и создать файл,
        // то все сообщения нужно в журнал info дописать после проверки наличия
        // этого файла журнала.
        if FileExists(FileInfo)
          then Result := FALSE
          else Result := True;

        // дописываем строки сообщений в журнал info
        for i := 0 to xMsgInfo.Count - 1
          do WriteInfo( xMsgInfo.Strings[ i]);

        // exchange #2631
        // нельзя выгрузить блок без части ЭД в блоке.
        // поэтому, если по ФТ3 или ФТ4 часть ЭД пропущена, то файл не создаем.
        // иначе, в файл эти ЭД не выгрузатся, а в архив уйдут все выбранные
        // для загрузки ЭД.
        if (xMsgInfo.Count > 0)
          then Result := FALSE;

        // проверяем, если ни одного ЭД не выгрузилось - тогда пишем в журнал
        // об этом и файл не создаем.
        if Result then
          if (Data.documentElement.childNodes.length <= 3) then begin
            WriteInfo( 'Ни один документ не выгружен.');
            Result := FALSE;
          end;
        finally
          xMsgInfo.Free;
      end;
      except
        ExceptionProc( 'MakeFormat_TFF9');
    end;

end;

(*
//Функция возвращает значение поля ADD_KLASS, по правилу описанному в настройке
//param_AddKlass. Xml - должна содержать атрибуты кодов, проверок на существование
//атрибутов в функции нет. Exchange #1970
function getAdd_Klass(Xml: Variant; param_AddKlass: Boolean): String;
begin
  Result := GetPurposeFulgrantCodeOld(Xml.getAttribute('PURPOSEFULGRANT_ID'));
  if not param_AddKlass then Exit;
  //проверка длин доп кодов согласно маске, описанной в настройке.
  //Нельзя проверять один раз, т.к. может не быть фильтра по бюджету,
  //надеемся на программный кэш.
  if (GetLengthCode('KDR', Xml.getAttribute('BUDGET_ID')) <> 3) or
    (GetLengthCode('KDE', Xml.getAttribute('BUDGET_ID')) <> 3) or
    (GetLengthCode('KDF', Xml.getAttribute('BUDGET_ID')) <> 6) or
    ((Length(Result) <> 3) and (Length(Result) <> 0)) then
  begin
    WriteLog('Разрядность доп кодов или длина кода субсидии не соовтетсвует ' +
      'маске, описaнной в настройке "Выгружать в поле "Код субсидии" доп.коды"');
    Exit;
  end;
  //Если все допы заполнены нулями, настройка не работает
  if (Xml.getAttribute('KDR_CODE') = 0) and (Xml.getAttribute('KDE_CODE') = 0)
    and (Xml.getAttribute('KDF_CODE') = 0) and (Result = '') then Exit;
  if Result = '' then
    Result := '000';
  Result := Result + KdrCodeFormat(Xml.getAttribute('KDR_CODE'),
    Xml.getAttribute('BUDGET_ID')) +
    KdeCodeFormat(Xml.getAttribute('KDE_CODE'), Xml.getAttribute('BUDGET_ID')) +
    KdfCodeFormat(Xml.getAttribute('KDF_CODE'), Xml.getAttribute('BUDGET_ID')) +
    '00000';
end;
*)


function Get_ADD_KLASS_TFF9( var aXml: Variant;
                             aParam_AddKlass: Boolean): String;
var
  xPurposeFulgrantCode: string;
  xPurposeFulgrantCodeEmpty: boolean;
  xPurposeFulgrantCodeLength: integer;
  xBudgetID: string;
  xLengthCodeKDR: integer;
  xLengthCodeKDE: integer;
  xLengthCodeKDF: integer;
begin

    try
      Result := '';

//      if NOT XmlAttrExists( aXml, 'PURPOSEFULGRANT_ID') then EXIT;
      // exchange #2412 - выгрузка кода цели с учетом системного параметра
      // и кодов цели
      xPurposeFulgrantCode := GetPurposeFulgrantCodeEx(
                                      aXml.getAttribute('PURPOSEFULGRANT_ID'),
                                      aXml.getAttribute('KDR_CODE'),
                                      aXml.getAttribute('KDE_CODE'),
                                      aXml.getAttribute('KDF_CODE'));


      // флаг пустого кода цели (если =true - код цели имеет пустое значение).
      xPurposeFulgrantCodeLength:= LENGTH( xPurposeFulgrantCode);
      xPurposeFulgrantCodeEmpty := (xPurposeFulgrantCodeLength <= 0);


      { Если параметр «Выгружать в поле «Код цели» доп коды» имеет значение
        «Нет» и поле «Код цели» в ЭД имеет значение 0, «Не указан».}
      if ((not aParam_AddKlass) AND xPurposeFulgrantCodeEmpty)
        then EXIT;

      Result := xPurposeFulgrantCode;
      if not aParam_AddKlass then Exit;

      // код бюджета нужен для ускорения операций
      xBudgetID := aXml.getAttribute('BUDGET_ID');
      // параметры вспомогательных полей - для ускорения операций
      xLengthCodeKDR:= GetLengthCode('KDR', xBudgetID);
      xLengthCodeKDE:= GetLengthCode('KDE', xBudgetID);
      xLengthCodeKDF:= GetLengthCode('KDF', xBudgetID);


      { Если параметр «Выгружать в поле «Код цели» доп коды» имеет значение
         «Да», код цели  имеет значение 0, «Неуказан» и доп коды не заполнены,
         то независимо от параметра конфигурации (param_AddKlass), результат в
         ADD_KLASS должен быть пустым}

      if ( aParam_AddKlass
              AND xPurposeFulgrantCodeEmpty
              AND (xLengthCodeKDR = 0)
              AND (xLengthCodeKDE = 0)
              AND (xLengthCodeKDF = 0))
        then EXIT;

      //проверка длин доп кодов согласно маске, описанной в настройке.
      //Нельзя проверять один раз, т.к. может не быть фильтра по бюджету,
      //надеемся на программный кэш.
      if ((xLengthCodeKDR <> 3) or
          (xLengthCodeKDE <> 3) or
          (xLengthCodeKDF <> 6) or
          ((xPurposeFulgrantCodeLength <> 3) and (xPurposeFulgrantCodeLength > 0)))
        then begin
          // exchange #2389 - исправлен текст код субсидии на код цели
          WriteLog('Разрядность доп кодов или длина кода цели не соответствует ' +
            'маске, описaнной в настройке "Выгружать в поле "Код цели" доп.коды"');
          Exit;
        end;

      if Result = '' then Result := '000';

      Result := Result
                  + KdrCodeFormat( aXml.getAttribute('KDR_CODE'), xBudgetID)
                  + KdeCodeFormat( aXml.getAttribute('KDE_CODE'), xBudgetID)
                  + KdfCodeFormat( aXml.getAttribute('KDF_CODE'), xBudgetID)
                  + '00000';
      except
        ExceptionLog( 'Сбой Exp_Fk_AP.Get_ADD_KLASS_TFF9');
    end;

end;


procedure Initialize(Xml: Variant);
var
  SL: TStringList;
begin
  SL := TStringList.Create;
  with SL do
  try
    CommaText := InitializeDefault(Xml, ChangeFileExt(TestFileName, ''));
    param_AddKlass := Values['Выгружать в поле "Код цели" доп.коды'] = 'Да';
    param_Spec := Values['СпецНастройка1'] = 'Да';
    param_Exch2411 := (Values['Формировать блок Лимиты бюджетных обязательств, при доведении ПОФ на ЛСФК']
                        = 'Да');
    // exchange #2572
    // параметр только для ТФФ11 и выше
    // поскольку ниже тфф уже нет, поэтому тут проверку тфф опускаем
    vCfg_ExpKodUFK:= (LowerCase( Values[ 'Выгружать код и наименование УФК'])
                      = 'да');
    {if (IsVersionSupport( cnVersionTFF_11) OR IsVersionSupport( cnVersionTFF_12))
      then vCfg_ExpKodUFK:= (LowerCase( Values[ 'Выгружать код и наименование УФК'])
                              = 'да')
      else vCfg_ExpKodUFK:= FALSE;}

    // exchange #2631
    vCfg_LimByAssign:=
         (LowerCase( Values[
           'Выгружать только лимиты по строкам, где доводятся и ассигнования, и лимиты'])
          = 'да');

    // exchange #2968
    InitializeExportCfgZip( SL);
    finally
      Free;
  end;
  // инициализируем модуль сообщений
  InitializeMessageValid( 'Exp_Fk_AP', DirIni);
  // Exchange 2336 загружаем схему в зависимости от версии
  // exchange #2542 - переход на тфф11 + переработка модуля проверки версий схем
  LoadSchema( GetFileNameSchemaTFF( 'ap_txap*'));
//  LoadSchema( DirIni + VersionSchemsDir + 'ap_txap100701.xml');
end; {End Initialize}

procedure Finalize(Xml: Variant);
begin
  
  FinalizeDefault(Xml);
  FinalizeMain;
  FinalizeMessageValid;
end; {End Finalize}

begin
  Main(NULL);
end.
