//АЦК: Заявка на кассовый расход
//Постановка: Exchange #1540, Exchange #1547
// #2344 - убран спец параметр
// #2372 - доработка выгрузки по разным схемам.
// #2377 - доработка выгрузки л/с для классов 11.
// #2389 - доработка получения значения ADD_KLASS_PAY по ТФФ9
// #2399 - ТФФ10
// #2515 - выгрузка поля SUM_V_NDS в ZR по #2372 (для Волгограда)
// #2542 - переход на тфф11 + переработка модуля проверки версий схем
// #2616 - переход на ТФФ12
uses
  'Un_Exch3117',    // exchange #3117
  'Un_Exch2739',    // #2739 - контроль выгрузки
  'Un_Exch2719',    // exchange #2719
  'Un_Exch2675',
  'Un_Exch2372',
  'Un_Exch2616_ExpZR',
  'Un_ExchFAIP',        // exchange #2801
  'Un_Exch2344',
  'Un_Exch2353',
  'Un_Exch2791',      // exchange #2791
  'Un_Export_AuBu',    // exchange #3081
  'Un_Export',
  'Un_Default',
  'Un_Org',
  'Un_OrgAccountGetter',
  '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';

const
  // маркер файла
  cnExportMarker = 'ZR';
  // имя файла (без пути и расширения), в котором будет сохранен входной XML
  cnExportFileName = 'Exp_Fk_' + cnExportMarker;
  // полное имя файла (без пути), в котором будет сохранен входной XML
  TestFileName = cnExportFileName + '.Xml';
  cnCfgTemplateKBKExp = 'Правило формирования значения аналитического кода с типом классификации “Расходы”';
  cnCfgTemplateKBKInc = 'Правило формирования значения аналитического кода с типом классификации “Доходы”';
  cnCfgTemplateKBKSrc = 'Правило формирования значения аналитического кода с типом классификации “Источники”';


var
  // exchange #2478
  // убран код "заполнения наименования банка из справочника"
  // из конфига и как опция конфига.
  param_Spec1, param_SpecS, param_Account, {param_BankName, }FullZr, param_SVR: Boolean;
  
  // Формирование значения КОФК
  param_UFK_TOFK: String;

  // выгрузка ЭД по записи #2372
  param_2372_ExpExt: boolean;

  // exchange #2753
  // список файлов для выгруженных пакетов
  vListFileOut: TStringList;

  // exchange #2753
  // в этой переменной будет =true для первого пакета и =false для последующих
  vFirstPacked: boolean;

  // exchange #2753
  // в этой переменной =true если выгрузка осуществляется по новому
  // алгоритму - #2753 и =false - по старому варианту.
  vPackedOutBy2753: boolean;

  paramTemplateKBKInc, paramTemplateKBKExp, paramTemplateKBKSrc: String;



{~Finalize
  завершение работы скрипта.}
procedure Finalize(Xml: Variant);
begin

  FinalizeDefault(Xml);
  FinalizeMessageValid;
  FinalizeMain;
end; {End Finalize}


procedure AddFileOut( aFileName: string);
begin
  if (vListFileOut <> NIL)
    then vListFileOut.Add( aFileName);
end;


{~Main
  главный скрипт}
function MainEx( aXml: Variant): Boolean;
var
  xXml: Variant;
  i: integer;
  xPackedNumber: integer;
  xExportDate: string;
  SL: TStringList;

  procedure DoCreateXml_( aXmlNode: Variant);
  begin
    xXml.LoadXml( '');
    xXml := CreateOleObject( 'Microsoft.XmlDom');
    xXml.appendChild( aXmlNode.cloneNode( TRUE));
  end;

begin
  Result := False;
  vListFileOut := NIL;
  try
    DoCreateXml_( aXml.documentElement.childNodes.Item[ 0]);

    InitializeMain( xXml, TestFileName);

    vListFileOut := TStringList.Create;
    try
      // загрузка параметров конфигурации из раздела входного задания XML
      try
        SL := TStringList.Create;
        try
          SL.CommaText := InitializeDefault( xXml, cnExportFileName);
          param_UFK_TOFK := SL.Values['Формирование значения КОФК'];
          param_Spec1 := SL.Values['СпецНастройка1'] = 'бюджетополучатель';
          param_SpecS := SL.Values['Заменять КФСР, КЦСР и КВР на нуль'] = 'Нет';
          param_Account := SL.Values['Выгружать "Лицевой счет" и "Расчетный счет" Заявки на кассовый расход'] = 'Да';

          param_SVR := SL.Values['Учет средств во временном распоряжении'] = 'Да';
          param_2372_ExpExt := SL.Values['Выгрузка БУ/АУ'] = 'Да';

          // exchange #2791
          // настройка "Позволять загружать 0 в КБК ИДП"
          DoConfig_2791_LoadKBK0_PI_BUDGET_CODE( SL);

          // exchange #2968
          InitializeExportCfgZip( SL);

          // exchange #3117
          InitializeExportBy3117( SL);
          finally
            SL.Free;
        end;
        except
          ExceptionLog( 'Сбой загрузки параметров конфигурации.');
      end;
      // инициализация модуля описания счета.
      GetOrgAccountGetter_Initialize;
      // инициализация формы критических сообщений
      InitializeMessageValid( 'EXP_FK_ZR', DirIni);
      // Exchange 2336 загружаем схему в зависимости от версии
      // exchange 2399 ТФФ 10.0 пп.3 с удалением кода по ТФФ8
      // exchange #2445 - исправлены версии схем
      // exchange #2542 - переход на тфф11 + переработка модуля проверки версий схем
      LoadSchema( GetFileNameSchemaTFF( 'zr_txzr*'));

        try
          Result := TRUE;
          // выгрузка нескольких пакетов
              for i := 0 to aXml.documentElement.childNodes.length - 1 do begin
                DoCreateXml_( aXml.documentElement.childNodes.Item[ i]);
                try
                  { загружаем номер пакета и дату экспорта. }
                  Export_GetPackedNumberOfDateExp( xXml.documentElement,
                                                   DirIni,
                                                   cnExportMarker,
                                                   xPackedNumber,
                                                   xExportDate);
                  { в зависимости от настроки "Выгрузка БУ/АУ" выполняем экспорт по новой
                    схеме выгрузки (="ДА") или по старой (="НЕТ"). }
                  if param_2372_ExpExt then begin
                    // выгрузка по Exchange #2372 возможна только для ТФФ9 и ТФФ10.
                    // exchange #2399 полное удаление ТФФ8
                    if NOT MakeFormatNew( xXml, xPackedNumber)
                      then Result := FALSE;
                  end else begin
                    //заполнение содержимого файла.
                    if NOT MakeFormatOld( xXml, xPackedNumber)
                      then Result := FALSE;
                  end;
                  finally
                    // при успешной выгрузке сохраняем номер пакета и дату выгрузки
                    // в файле экспорта
                    if Result then Export_SetPackedNumberOfDateExp( DirIni,
                                                                    cnExportMarker,
                                                                    xPackedNumber,
                                                                    xExportDate);
                end;
              end;//for//
          except
            ExceptionLog( 'Сбой MainEx');
        end;

      finally
        // если есть хоть малейшая проблема - открываем журнал info
        // и считаем что выгрузка не выполнена.
        if FileExists(FileInfo) then begin
          ShowJournalEnd;
        end;
        Finalize( xXml);

        if (vListFileOut <> NIL)
          then vListFileOut.Free;
    end;
    except
      ExceptionHandler;
  end;
end;


function MainPacked(Xml: Variant): Boolean;
var
  xPackedNumber: integer;
  xExportDate: string;
begin
  Result := FALSE;

    try
      // этот код выполняется в InitializeDefault.
      // поскольку эта функция вызывается единожды, то здесь придется создавать
      // новый объект заново создается для каждого пакета.
      // при этом первый пакет уже будет создан при инициализации.
      if vFirstPacked
        then vFirstPacked := FALSE
        else begin
          Data := CreateOleObject('Microsoft.XmlDom');
          Data.appendChild(Data.createElement('FORMAT'));
        end;

          try
            { загружаем номер пакета и дату экспорта. }
            Export_GetPackedNumberOfDateExp( Xml.documentElement,
                                             DirIni,
                                             cnExportMarker,
                                             xPackedNumber,
                                             xExportDate);
            { в зависимости от настроки "Выгрузка БУ/АУ" выполняем экспорт по новой
              схеме выгрузки (="ДА") или по старой (="НЕТ"). }
            if param_2372_ExpExt then begin
              // выгрузка по Exchange #2372 возможна только для ТФФ9 и ТФФ10.
              // exchange #2399 полное удаление ТФФ8
              if MakeFormatNew( Xml, xPackedNumber)
                then Result := TRUE;
            end else begin
              //заполнение содержимого файла.
              if MakeFormatOld(Xml, xPackedNumber)
                then Result := TRUE;
            end;
            finally
              // при успешной выгрузке сохраняем номер пакета и дату выгрузки
              // в файле экспорта
              if Result then Export_SetPackedNumberOfDateExp( DirIni,
                                                              cnExportMarker,
                                                              xPackedNumber,
                                                              xExportDate);
          end;

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

end;


{~Main
  главный скрипт}
function Main(Xml: Variant): Boolean;
var
  xPackedNumber: integer;
  xExportDate: string;
  SL: TStringList;
begin
  Result := False;
  vListFileOut := NIL;
  vPackedOutBy2753 := FALSE;   // старый алгоритм выгрузки
  xml := InitializeMain( xml, TestFileName);
  if VarIsNull( xml) then exit;
  try
    try
      // загрузка параметров конфигурации из раздела входного задания XML
      try
        SL := TStringList.Create;
        try
          SL.CommaText := InitializeDefault( Xml, cnExportFileName);
          param_UFK_TOFK := SL.Values['Формирование значения КОФК'];
          param_Spec1 := SL.Values['СпецНастройка1'] = 'бюджетополучатель';
          param_SpecS := SL.Values['Заменять КФСР, КЦСР и КВР на нуль'] = 'Нет';
          param_Account := SL.Values['Выгружать "Лицевой счет" и "Расчетный счет" Заявки на кассовый расход'] = 'Да';

          param_SVR := SL.Values['Учет средств во временном распоряжении'] = 'Да';
          param_2372_ExpExt := SL.Values['Выгрузка БУ/АУ'] = 'Да';

          paramTemplateKBKInc := SL.Values[cnCfgTemplateKbkInc];
          paramTemplateKBKExp := SL.Values[cnCfgTemplateKbkExp];
          paramTemplateKBKSrc := SL.Values[cnCfgTemplateKbkSrc];

          // exchange #2791
          // настройка "Позволять загружать 0 в КБК ИДП"
          DoConfig_2791_LoadKBK0_PI_BUDGET_CODE( SL);
          // exchange #2968
          InitializeExportCfgZip( SL);
          // exchange #3117
          InitializeExportBy3117( SL);
          finally
            SL.Free;
        end;
        except
          ExceptionLog( 'Сбой загрузки параметров конфигурации.');
      end;
      // инициализация модуля описания счета.
      GetOrgAccountGetter_Initialize;
      // инициализация формы критических сообщений
      InitializeMessageValid( 'EXP_FK_ZR', DirIni);
      LoadSchema( GetFileNameSchemaTFF( 'zr_txzr*'));
      // exchange #2719
      ExportOutDirExch2719( Xml.documentElement.getAttribute('EXCH_DATE'), 'ZR');
      if (VarToStr( Xml.documentElement.GetAttribute( 'RunScriptMode')) = '3')
        then begin
          // exchange #2753
          // вызываем функцию эксча для формирования пакетов.
          // в результате будетвызываться скрипт MainPacked();
          // не забываем, что в переменной Data уже создан XML при
          // инициализации, а для последующих пакетов придется создавать заново.
          vFirstPacked := TRUE;
          vPackedOutBy2753 := TRUE;  // новый алгоритм выгрузки по #2753
          Run_Export_Event( Xml);
        end else
          try
            { загружаем номер пакета и дату экспорта. }
            Export_GetPackedNumberOfDateExp( Xml.documentElement,
                                             DirIni,
                                             cnExportMarker,
                                             xPackedNumber,
                                             xExportDate);
            { в зависимости от настроки "Выгрузка БУ/АУ" выполняем экспорт по новой
              схеме выгрузки (="ДА") или по старой (="НЕТ"). }
            if param_2372_ExpExt then begin
              // выгрузка по Exchange #2372 возможна только для ТФФ9 и ТФФ10.
              // exchange #2399 полное удаление ТФФ8
              if MakeFormatNew( Xml, xPackedNumber)
                then Result := TRUE;
            end else begin
              //заполнение содержимого файла.
              if MakeFormatOld(Xml, xPackedNumber)
                then Result := TRUE;
            end;
            finally
              // при успешной выгрузке сохраняем номер пакета и дату выгрузки
              // в файле экспорта
              if Result then Export_SetPackedNumberOfDateExp( DirIni,
                                                              cnExportMarker,
                                                              xPackedNumber,
                                                              xExportDate);
          end;
      finally
        // если есть хоть малейшая проблема - открываем журнал info
        // и считаем что выгрузка не выполнена.
        if FileExists(FileInfo) then begin
          ShowJournalEnd;
        end;
        Finalize(Xml);
    end;
    except
      ExceptionHandler;
  end;
end; {end Main}


{~Exch2447_UpdateGrantinvesmentCode
 exchange #2447
  1.	Если поле "Код субсидии" в ЭД "Заявка БУ/АУ на выплату средств" (195)
      имеет значение отличное от 0-"Не указан" выгружать его в поле
      ADD_KLASS_PAY "Заявки на кассовый расход" (ZR) только в том
      случае, если значение в поле «Счет» блока «Плательщик» ЭД,
      начинается жестко на 21 либо 31.
  2.	Если значение в поле «Счет» блока «Плательщик» начинается на
      21, 31, а поле «Код субсидии» в ЭД «Заявка БУ/АУ на выплату
      средств» (195) имеет значение 0-«Не указан», выгружать жестко
      значение «-» (прочерк).
  3.	В случае, если условия по п1 и п2 не соблюдены, значение поля
      "Код субсидии" не выгружается.
 exchange #2477
  Если поле "Код субсидии" в ЭД "Заявка БУ/АУ на выплату средств" (195)
  имеет значение отличное от 0-"Не указан" выгружать его в поле ADD_KLASS_PAY
  "Заявки на кассовый расход" (ZR) в случаях:
•	если значение в поле «Счет» блока «Плательщик» ЭД, начинается жестко
    на 21 либо 31;
•	 у выгружаемого «Кода субсидии» в справочнике «Коды субсидий» проставлен
    признак «Контроль в ФК».}
procedure Exch2447_UpdateGrantinvesmentCode( var aZRST: variant;
                                             aZR_PAY_ACCOUNT: string;
                                             aGRANTINVESTMENT_ID: string);
var
  xZRST_ADD_KLASS_PAY: string;
begin

    try
      xZRST_ADD_KLASS_PAY :=
            QueryField( 'Select Code From GrantInvestment Where Id = ?'
                       // exchange #2477
                       // нужно вернуть или код=0 или те, для которых
                       // установлен флаг "контроль ФК".
                       // код 0 нужен, поскольку для 0-го кода флаг "контроль ФК"
                       // не устанавлен и контрол заблокирован. а по записи,
                       // для кода = 0 выгружается символ "-"
                       +' and (CONTROLFK=1 or (caption like  '#39'%Не указан%'#39'))',
                        [ aGRANTINVESTMENT_ID],
                        'CODE');
      if ((POS( '21', aZR_PAY_ACCOUNT) = 1) OR (POS( '31', aZR_PAY_ACCOUNT) = 1))
        then begin
          if (StringReplace(xZRST_ADD_KLASS_PAY, '0', '') = '')
            then aZRST.SetAttribute('ADD_KLASS_PAY', '-')
            else aZRST.SetAttribute('ADD_KLASS_PAY', xZRST_ADD_KLASS_PAY);
        end else begin
          aZRST.SetAttribute('ADD_KLASS_PAY', '');
        end;

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

end;


function MakeFormatNew( var aSourceXml: Variant;
                        var aPackedNumber: integer): Boolean;
var
  xDocsGroups: Variant;
  xGroups: TStringList;
  xCount: integer;
  xCountExport: integer;
  xSourceXml: Variant;
  xFilesOut: TStringList;
  i,j: integer;
  xFileName: string;
  xDocHash: integer;
  xDocGroupIndex: integer;
  xDocType: integer;
  xNewDocumentXml: Variant;
  xDataXml: Variant;
  xDataSectionXml: Variant;
  xDocNodeXml: Variant;
  xFlagExportFail: boolean;
  xFoundFileInfoBefore: boolean;
begin

  try
    Result := FALSE;
    // корневой элемент входных данных. это чисто для удобства.
    xSourceXml := aSourceXml.documentElement;
    // выполяем группировку документов
    if NOT Export_InitializeGroups( xSourceXml, xDocsGroups, xGroups)
      then EXIT;
    try
      // группируем ЭД для экспорта
      xCount       := xSourceXml.childNodes.length;
      xCountExport := Exch2372_Prepare( xSourceXml, xDocsGroups, xGroups);

      // если количество сгруппированных ЭД не совпадает с числом выгружаемых
      // ЭД, то предлагаем пользователю продолжить или прервать экспорт.
      // если пользователь прервет операцию, прерываем дальнейшее выполнение
      // скрипта и возвращаем =FALSE.
      if (xCountExport <> xCount) then begin
        WriteInfo( 'Не все ЭД могут быть экспортированы.');
        if NOT ShowMessageValid( vJournalTmp,
                                 'Группировка ЭД перед выгрузкой')
          then EXIT;
      end;
      // пока считаем что ошибки нет
      xFlagExportFail := FALSE;
      // создаем список имен файлов, которые будут выгружены
      xFilesOut:= TStringList.Create;
      try
        // теперь формируем конечные файлы и для каждого файла выполняем
        // выгрузку ЭД, входящих в группу для этого файла.
        // экспорт считается полностью выполненным, если экспортированы
        // все ЭД во всех группах.
        for i := 0 to xGroups.Count - 1 do begin
          // описание группы ЭД
          Export_StartGroup( i,
                             xGroups,
                             xSourceXML,
                             Schema,
                             cnExportMarker,
                             xFileName,
                             xNewDocumentXml,
                             aPackedNumber);
          // получаем корневой элемент выгружаемого XML.
          // это упростит дальнейшую работу, при обращении к этому документу.
          xDataXml := xNewDocumentXml.documentElement;
          // логируем операцию
          WriteLog( FORMAT( 'Выгрузка ЭД в файл: "%s"...', [ xFileName]), TRUE);
          // теперь выгружаем в этот файл сгруппированные ЭД
          // при этом подсчитываем, сколько ЭД выгружено в этот файл.
          xCountExport := 0;
          SetProgress( 0, xCount);
          for j := 0 to xCount - 1 do begin
            ShowProgress( j);

            xDocHash := xDocsGroups[ j];
            if Export_GetDocumentTypeAndGroup( xDocHash,
                                               xDocType,
                                               xDocGroupIndex) then
              // выгружаем в текущий документ только те ЭД, которые
              // соответсвуеют текущей группе ЭД (по индексу группы в списке
              // групп).
              if (i = xDocGroupIndex) then begin
                // текущий документ XML
                xDocNodeXml := xSourceXml.childNodes.Item[ j];
                // выгружаем документ в текущий файл выгрузки

                case xDocType of
                  // выгрузка по старой схеме ТФФ9
                  0: begin
                      // создаем секцию и заполняем ее значениями из полей
                      // документа по полям, описанным в схеме.
                      xDataSectionXml := xDataXml.appendChild(FillElementBySchema(xDocNodeXml,cnExportMarker));

                      { Exchange #2344
                        описание некоторых параметров выгружаем по ТФФ9
                        Exchange #2434}
                      Exch2344_ZR_TFF9( xDataSectionXml,
                                        xDocNodeXml,
                                        param_Spec1,
                                        param_UFK_TOFK);

                      // exchange #2739 - проверяем ЭД
                      CheckByExch2739(xDocNodeXml, 'ZR');
                      // выгрузка документа
                      if NOT MakeFormat(xDocNodeXml, xDataSectionXml)
                        then xFlagExportFail := TRUE;

                    end;

                  // выгрузка по #2372
                  1: begin
                      // создаем секцию без заполнения
                      xDataSectionXml := xDataXml.AppendChild(FillElementBySchemaEx(Schema, cnExportMarker, NULL));
                      // выгружаем документ в зависимости от класса
                      case xDocNodeXml.getAttribute('DOCUMENTCLASS_ID') of
                        '11': begin
                                // exchange #2739 - проверяем ЭД
                                CheckByExch2739( xDocNodeXml, 'ZR');
                                if NOT Exch2372_Class11( xDocNodeXml,
                                                         xDataSectionXml,
                                                         Schema,
                                                         param_UFK_TOFK)
                                  then xFlagExportFail := TRUE;
                              end;
                        '75': if NOT Exch2372_Class75( xDocNodeXml,
                                                       xDataSectionXml,
                                                       Schema,
                                                       param_UFK_TOFK)
                                then xFlagExportFail := TRUE;
                      end;//case//
                    end;
                end;//case//
                // подсчет числа выгруженных документов
                INC( xCountExport);
              end;
          end;//for//
          { если выгружено в файл хоть что либо, выполняем проверку
            полученного документа, выгружаем документ в файл и сохраняем
            файл в списке готовых файлов.}
          if (xCountExport > 0) then begin
            // exchange #2739 - проверка ошибок
            if NOT FinalizeByExch2739( param_CtlValidOn)
              then EXIT;

            // exchange #3062
            // здесь накладка. при ошибке валидации в журнал info попадает
            // описание ошибок валидации, а в дальнейшем, наличие журнала
            // info свидетельствует о критических ошибках выгрузки.
            // поэтому если валидация не прошла, но это игнорируют
            // выгрузка не выполняется.
            // для этого проверяем, если ошибка была до валидации, тогда это
            // верно, а если только при валидации - тогда файл формируем.
            // видимо была ошибочно поправлена доработка #2791.
            xFoundFileInfoBefore := FileExists(FileInfo);

            // если при проверке схемы возникнут проблемы и пользователь
            // откажется от продолжения - выходим из функции.
            if NOT Export_ValidateDocument( FileValidate,
                                             xNewDocumentXml,
                                             Schema,
                                             RegExp,
                                             param_CtlValidOn,
                                             param_StopAllUnloadDocNotValid)
              then EXIT;


            // exchange #2791
            // если есть журнал info, то выгрузку считаем невыполненной

            if xFoundFileInfoBefore then EXIT;
//            if FileExists(FileInfo) then EXIT;

            // сохраняем документ XML в файле
            SaveXmlToFormatTextFile( xNewDocumentXml, DirTmp + xFileName);
            // сохраняем файл в списке созданных файлов
            xFilesOut.Add( xFileName);

            // exchange #2753
            // в данном случае сохраняем все создаваемые файлы, даже если
            // в результате будет ошибка валидации.
            AddFileOut( xFileName);
          end;
        end;//for//

        // выгрузка выполнена.
        // остается перенести документы в архив, скопировать файлы в конечные
        // каталоги и выполнить изменение статусов выгруженных документов
        if NOT Export_EndFiles( aSourceXml,
                                 xFilesOut,
                                 DirTmp,
                                 DirOut,
                                 DirArh,
                                 cnExtStatusID_UnLoaded,
                                 xDocsGroups)
          then begin
            Result := FALSE;
            EXIT;
          end;
        finally
          // удаляем временные файлы. при успешной выгрузки эти файлы должны
          // быть скопированы в архив, а при неуспешной выгрузке - стерты.
          DeleteFiles( DirTmp, xFilesOut, 'Удаляются временные файлы...');
          xFilesOut.Free;
      end;
      finally
        // разрушаем все данные о группах
        Export_FinalizeGroups( xDocsGroups, xGroups);
    end;
    Result := TRUE;
    except
      ExceptionLog( 'Сбой Exp_FK_ZR.MakeFormatNew');
  end;

end;


function MakeFormatOld( var aSourceXml: Variant;
                        var aPackedNumber: integer): Boolean;

  procedure FileOut_TFF9( xDocXml: Variant);
  var
    xRow: Variant;
    ubpFieldName, kodUbp: String;
  begin
    try
      
      xRow := xDocXml.childNodes.items[ 0];

      case xRow.getAttribute('DOCUMENTCLASS_ID') of
        // exchange #2399 отменяется ТФФ8, а по ТФФ10 аналогично ТФФ9
        11: ubpFieldName := 'ORG_CODE';
        194: ubpFieldName := 'CLIENT_CODE';
        195: ubpFieldName := 'CLIENT_CODE'
        else ubpFieldName := 'PAY_CODE';
      end;//case//
      

      kodUbp := xRow.getAttribute(ubpFieldName);
      if (LENGTH(kodUbp) <> 8) and (LENGTH(kodUbp) <> 5) then
      begin
        WriteInfo( 'Код организации-клиента (KOD_UBP) имеет длину, отличную от допустимой (либо 8 символов, либо 5 символов). Значение будет очищено');
        kodUbp := '';
        xRow.setAttribute(ubpFieldName, kodUbp);
      end;

      if (LENGTH(kodUbp) = 8) then
        kodUbp := Copy(kodUbp, 4, 5); //с 4 по 8 символ

      FileOut := GetFileName(
        kodUbp,
        'ZR',
        XmlToDateTime(xDocXml.getAttribute('EXCH_DATE')),
        aPackedNumber,
        FileOutIsLocalNet,
        FileOutOrgCodeIsFk);

      except
        ExceptionLog( 'Сбой скрипта: "Exp_FK_ZR.MakeFormat.FileOut_TFF9".');
    end;
  end;
  
var
  i,i2: Integer;
  xDocXml: Variant;
  xDataXml: Variant;
  xDocumentXml: Variant;
  xDocNodeXml: Variant;
  xDataSectionXml: Variant;
  xXml: Variant;
begin

  try
    Result := FALSE;

    INC( aPackedNumber);

    xDocumentXml := Data;
    xDataXml     := xDocumentXml.documentElement;
    xDocXml      := aSourceXml.documentElement;

    // обязательно проверяем, есть что выгружать?
    if (xDocXml.childNodes.length <= 0) then EXIT;

  { имя формируемого файла (файла результата)
    проблема в том, что это нужно делать по старому для ТФФ8 и по новому для ТФФ9
    переделка в том, что если версия 2.28 и выше - заполняется как по ТФФ9
      если ниже - как раньше - по ТФФ8}
    // exchange #2399 переход на ТФФ 10.0 с удалением кода ТФФ8
    FileOut_TFF9( xDocXml);
    WriteLog('Наименование формируемого файла: ' + FileOut, True);

    // описание заголовка определяется по первому ЭД в списке
    xDocNodeXml := xDocXml.childNodes.items[ 0];


    // exchange #2399 удаление кода ТФФ8, а операция ТФФ9 одинакова с ТФФ10
    if NOT CompareVersionAZK_Finance(
              FORMAT( 'Выгрузка ЭД "%s" по ТФФ 9/ТФФ 10',
                      [ GetDocumentNameByClass(
                            xDocNodeXml.getAttribute('DOCUMENTCLASS_ID'))]),
              '2.28', FALSE, TRUE)
      then EXIT;

    WriteLog('Заполнение данных файла: ' + FileOut, True);
    Data := xDataXml.appendChild(FillElementBySchema(xDocXml, 'FK'));
    Data.setAttribute('FORM_VER', AppVersion);

    Data := xDataXml.appendChild(
                FillElementBySchema( xDocNodeXml, 'FROM'));

    if xDocNodeXml.getAttribute('DOCUMENTCLASS_ID') = 195
      then Data.setAttribute('BUDG_LEVEL', 6)
      else Data.setAttribute('BUDG_LEVEL',
                 GetBudgLevel( xDocNodeXml.getAttribute('BUDGET_ID')));

    // exchange #2399 отменяется ТФФ8
    Exch2344_FromZRZS_TFF9( Data, xDocNodeXml);

    Data := xDataXml.appendChild(FillElementBySchema( xDocNodeXml, 'TO'));
    case xDocNodeXml.getAttribute('DOCUMENTCLASS_ID') of
      11: begin
            Data.setAttribute('KOD_TOFK', QueryField( sqlTofkAcc, [xDocNodeXml.getAttribute('ORGACCOUNT_ID')], 'NAME'));
            Data.setAttribute('NAME_TOFK', QueryField( sqlTofkAcc, [xDocNodeXml.getAttribute('ORGACCOUNT_ID')], 'DESCRIPTION'));
          end;
      75, 118, 195:
          begin
            Data.setAttribute('KOD_TOFK', QueryField( sqlTofkAcc, [xDocNodeXml.getAttribute('PAY_ACC_ID')], 'NAME'));
            Data.setAttribute('NAME_TOFK', QueryField( sqlTofkAcc, [xDocNodeXml.getAttribute('PAY_ACC_ID')], 'DESCRIPTION'));
          end;
    end;

    SetProgressBarMax( xDocXml.childNodes.length);



    //Шапка заявки (ZR)
    for i := 0 to xDocXml.childNodes.length - 1 do begin
      ShowProgress( i);
      xDocNodeXml := xDocXml.childNodes.items[i];



      xDataSectionXml  := xDataXml.appendChild(
                                      FillElementBySchema( xDocNodeXml, 'ZR'));



      { exchange #3034:
        Изменить выгрузку по форматам ZR следующим образом:
        Если  в поле КПП в блоке Получатель (для 11, 195 классов)/Расходование
        (для 75,118 классов) пусто, в блоке KPP_RCP выгружать значение «0»
        поскольку это нужно делать для всех классов, проверка класса не выполняется.
        поле KPP_RCP выгружается по схеме из поля REC_KPP для всех ЭД.}
      if (LENGTH( GetNodeAttributeEx( xDataSectionXml, 'KPP_RCP')) <= 0)
        then xDataSectionXml.SetAttribute( 'KPP_RCP', '0');

      // выгрузка документа
      case xDocNodeXml.getAttribute('DOCUMENTCLASS_ID') of
        '11': begin
              // exchange #2739 - проверяем ЭД
              CheckByExch2739( xDocNodeXml, 'ZR');

              // exchange #2434
              Exch2434_ZR_ZS_11( xDataSectionXml,
                                  xDocNodeXml,
                                  param_Spec1,
                                  param_UFK_TOFK,
                                  'LS_UBP_PAY',
                                  'KOD_TOFK',
                                  'NAME_TOFK');

              // exchange #2791
              // если будет ошибка выгрузки - прерываем всю выгрузку
              if NOT MakeFormat_11( xDocNodeXml, xDataSectionXml)
                then EXIT;
            end;

        '195': begin
                // exchange #2739 - проверяем ЭД
                CheckByExch2739( xDocNodeXml, 'ZR');
                setTOFKProps(param_UFK_TOFK, xDataSectionXml, xDocNodeXml.getAttribute('PAY_ACC_ID'), 'KOD_TOFK', 'NAME_TOFK');


              // exchange #2791
              // если будет ошибка выгрузки - прерываем всю выгрузку
              if NOT MakeFormat(xDocNodeXml, xDataSectionXml)
                then EXIT;

              // exchange 3117 - только для ау/бу
              // только для старого алгоритма, поскольку в новом алг
              // (для Волгограда), эд ау/бу не выгружаются.
              UpdateXmlOutBy3117( xDocumentXml);
            end;

        '75', '118': begin
                setTOFKProps(param_UFK_TOFK, xDataSectionXml, xDocNodeXml.getAttribute('PAY_ACC_ID'), 'KOD_TOFK', 'NAME_TOFK');
                if NOT MakeFormat(xDocNodeXml, xDataSectionXml)
                  then EXIT;
              end;

        else
            // exchange #2791
            // если будет ошибка выгрузки - прерываем всю выгрузку
            if NOT MakeFormat(xDocNodeXml, xDataSectionXml)
              then EXIT;
      end; //case


    end;//for//

    // если есть критические сообщения, прерываем экспорт
    // exchange #2753
    // в случае выгрузки по новому алгоритму, игнорируем проверку журнала info
    if NOT vPackedOutBy2753 then
      if FileExists(FileInfo) then EXIT;

    // exchange #2739 - проверка ошибок
    if NOT FinalizeByExch2739( param_CtlValidOn)
      then EXIT;

    // сохраняем документ XML в файле
    SaveXmlToFormatTextFile( aSourceXml, DirTmp + FileOut);



    // валидация схем и выгрузка файла
    if NOT Export_End( aSourceXml,
                       FileOut,
                       FileValidate,
                       xDocumentXml,
                       Schema,
                       RegExp,
                       DirTmp,
                       DirOut,
                       DirArh,
                       param_CtlValidOn,
                       param_StopAllUnloadDocNotValid,
                       '',
                       NULL)
      then begin
        // экспорт не выполнен.
        // удаляем временный файл
        DeleteFile( DirTmp + FileOut);
        EXIT;
      end;

    // exchange #2753
    // сохраняем имя файла, если файл успешно создан
    AddFileOut( FileOut);

    Result := TRUE;
    except
      ExceptionLog( 'Сбой Exp_FK_ZR.MakeFormatOld');
  end;

end;


function MakeFormat( var xDocNodeXml: Variant;
                     var xDataXml: Variant): Boolean;
var
  j: Integer;
  Ground: Variant;
  KesXml: Variant;
  xDocItemXml : Variant;
  xDataZRST   : Variant;
  xDataZROSN  : Variant;
  xGroundItemXml: Variant;
  xZR_TYPE: string;     // exchange #2616
  xDocClass: string;
  xDocInfo: string;
  xDocPayID: string;
  xDocPayKPP: string;
  xPayID: string;
  xREC_ID: string;
  xKBKType, xKBKTemplate, xKBK: string;
begin

    try
      Result := False;

      // exchange #3021
      // класс эд сохраняем в локальной переменной
      xDocClass := GetNodeAttributeEx( xDocNodeXml, 'DOCUMENTCLASS_ID');




      // exchange #2616 - сохраняем значение поля ZR.TYPE
      // exchange #3021 - перенесено в начало кода
      xZR_TYPE := GetNodeAttributeEx( xDataXml, 'TYPE');

      FullZr := (xZR_TYPE = '1');


      xDataXml.setAttribute('NOM_ZR', Trim(xDataXml.getAttribute('NOM_ZR')));
      xDataXml.setAttribute('DATE_ZR', FormatDateTime('dd.mm.yyyy',
        XmlToDateTime(xDataXml.getAttribute('DATE_ZR'))));

      if FullZr then
      begin
        xDataXml.setAttribute('INN_UBP', '');
        xDataXml.setAttribute('KPP_UBP', '');
      end;
      xDataXml.setAttribute('DATE_POD_UBP', IfThen(xDataXml.getAttribute('DATE_POD_UBP') <> '',
        FormatDateTime('dd.mm.yyyy', XmlToDateTime(xDataXml.getAttribute('DATE_POD_UBP'))), ''));
      // exchange #3021 - применение локальной переменной
      if xDocClass = '195' then
      begin
        //в предзаполнении записываем Id нужной организации
        if xDataXml.getAttribute('NAME_UBP_GRS') <> '' then
          xDataXml.setAttribute('NAME_UBP_GRS', QueryField(sqlOrgId,
            [xDataXml.getAttribute('NAME_UBP_GRS')], 'DESCRIPTION'));
      end
      else begin
        xDataXml.setAttribute('GLAVA_GRS',
          StringReplace(Format('%3s', [xDataXml.getAttribute('GLAVA_GRS')]), ' ', '0'));
        xDataXml.setAttribute('NAME_BUD', QueryField(sqlBudgId, [xDocNodeXml.getAttribute('BUDGET_ID')],
          'CAPTION'));
        xDataXml.setAttribute('NAME_FO', QueryField(sqlFoNameByBudg,
          [xDocNodeXml.getAttribute('BUDGET_ID')], 'DESCRIPTION'));
        xDataXml.setAttribute('DATE_ISP', IfThen(xDataXml.getAttribute('DATE_ISP') <> '',
          FormatDateTime('dd.mm.yyyy', XmlToDateTime(xDataXml.getAttribute('DATE_ISP'))), ''));
      end;

      //Exchange #1616
      xDataXml.setAttribute('VID_PL', PayKindSetAsFk(xDocNodeXml.getAttribute('PAYKIND')));
      if Trim(xDocNodeXml.getAttribute('AUTHOR_ID')) <> '' then
        xDataXml.setAttribute('PAYSTATUS',
          StringReplace(Format('%2s', [xDocNodeXml.getAttribute('AUTHOR_ID')]),' ', '0'));

  
      if xDocNodeXml.getAttribute('REC_ACC_ID') = '' then
        //Exchange#1946
        if (xDocNodeXml.getAttribute('DOCUMENTCLASS_ID') <> 195) and
            (xDocNodeXml.getAttribute('REC_ID') <> '')
            and HasOrgRole(xDocNodeXml.getAttribute('REC_ID'), '6')
            and (xDocNodeXml.getAttribute('REC_ACCOUNT') = '00000000000000000000') then
          xDataXml.setAttribute('BS_RCP', '')
        else
          xDataXml.setAttribute('BS_RCP', xDocNodeXml.getAttribute('REC_ACCOUNT'))
      else begin
        if GetAccType(xDocNodeXml.getAttribute('REC_ACC_ID')) in ['2','3'] then
          //Exchange#1946
          if (xDocNodeXml.getAttribute('DOCUMENTCLASS_ID') <> 195) and
              (xDocNodeXml.getAttribute('REC_ID') <> '')
              and HasOrgRole(xDocNodeXml.getAttribute('REC_ID'), '6')
              and (xDocNodeXml.getAttribute('REC_ACCOUNT') = '00000000000000000000') then
            xDataXml.setAttribute('BS_RCP', '')
          else
            xDataXml.setAttribute('BS_RCP', xDocNodeXml.getAttribute('REC_ACCOUNT'));
        if GetAccType(xDocNodeXml.getAttribute('REC_ACC_ID')) in ['5', '7', '8', '9'] then
          if param_Account then
          begin
            xDataXml.setAttribute('LS_UBP_RCP', xDocNodeXml.getAttribute('REC_ACCOUNT'));
            xDataXml.setAttribute('BS_RCP', xDocNodeXml.getAttribute('REC_UFK_ACCOUNT'));
          end
          else
            xDataXml.setAttribute('LS_UBP_RCP', xDocNodeXml.getAttribute('REC_ACCOUNT'))
        else if (xDocNodeXml.getAttribute('DOCUMENTCLASS_ID') = 195) and
          (GetAccType(xDocNodeXml.getAttribute('REC_ACC_ID')) in ['1', '6']) then
            xDataXml.setAttribute('BS_RCP', xDocNodeXml.getAttribute('REC_UFK_ACCOUNT'))
        // exchange #2377
        { Если счет в поле «Счет» блока «Плательщик» имеет тип 1,6 - поле BS_RCP
          заполнять значением банковского счета из поля "Счет УФК" блока
          «Расходование».}
        else
          if (xDocNodeXml.getAttribute('DOCUMENTCLASS_ID') = 11) and
              (GetAccType(xDocNodeXml.getAttribute('REC_ACC_ID')) in ['1', '6'])
            then xDataXml.setAttribute('BS_RCP', xDocNodeXml.getAttribute('REC_UFK_ACCOUNT'));
      end;
  

      //затираем данные для сокращенной заявки.
      if not FullZr then
      begin

        xDataXml.setAttribute('NAME_UBP_GRS', '');
        xDataXml.setAttribute('NAME_FO', '');

        xDataXml.setAttribute('LS_UBP_RCP', '');
        xDataXml.setAttribute('DOL_RUK_UBP', '');
        xDataXml.setAttribute('DOL_BUH_UBP', '');

        // exchange #3021
        // только для эд 195го
        if (xDocClass = '195') then begin
          xDataXml.SetAttribute( 'KOD_ISP', '');
          xDataXml.SetAttribute( 'PR_ISP', '');
          xDataXml.SetAttribute( 'KOD_V', '643');
          // выгружается значение "назначение платежа
          xDataXml.SetAttribute( 'PURPOSE',
                                 GetNodeAttributeEx( xDocNodeXml,
                                                     'DESCRIPTION'));
          xDataXml.SetAttribute( 'LS_UBP_RCP', '');

          xDataXml.setAttribute( 'INN_UBP', '');
          // KPP_UBP - выгружать значение поля КПП, если оно отличается от КПП
          // на закладке Общая информация в карточке организации, указанной
          // в поле Плательщик.
          // в начале получаем значением КПП плательщика из ЭД 195го
          xDocPayKPP := GetNodeAttributeEx( xDocNodeXml, 'PAY_KPP');

          // если орг.плательщик указана, то проверяем значение КРР орг.
          // плательщика и КПП орг. плательщика эд 195го в шапке
          xDocPayID := GetNodeAttributeEx( xDocNodeXml, 'PAY_ID');
          if (LENGTH( xDocPayID) > 0) then
            if (QueryField( 'select KPP from org where id=?',
                            [ xDocPayID],
                            'KPP') = xDocPayKPP)
              then xDocPayKPP := '';
          xDataXml.SetAttribute( 'KPP_UBP', xDocPayKPP);
        end;
      end;

      // exchange #2616 - ТФФ 12 - заполнение поля ZR.OKPO_FO
      DoFill2616_ZR_OKPO_FO( xDocNodeXml, xDataXml);
  

      // exchange #2801, #2803
      // заполнение поля ФАИП в поле ZR.FAIP_CODE с проверкой класса
      ExchExport_FAIP( xDocNodeXml, xDataXml, 'FAIP_CODE', TRUE);

      // exchange #3021 - применение локальной переменной класса эд
      // описание эд на случай сбоя выгрузки
      xDocInfo := FORMAT( '№ %s от %s на сумму %s',
                        [ GetNodeAttributeEx( xDataXml, 'NOM_ZR'),
                          GetNodeAttributeEx( xDataXml, 'DATE_ZR'),
                          GetNodeAttributeEx( xDataXml, 'SUM_V')]);

      // exchange #3081
      // если ид.платежа =доходы - ид.платежа выгружается
      // если тип <>доходы - поле не выгружать
      // проверяем значение ид.платежа на выход за 20 символов
      //--
      // Да, все было так, пока не появилась запись Exchange, #3171
      // В ОА сказали, что это - придумки ОР и решили удалить это уловие
      CheckField_PI_BUDGET_CODE( xDataXml, 'KDOH', vCfg_2791_LoadKBK0_PI_BUDGET_CODE);

      // exchange #2791 - проверка КБК в ид.платежа
      if NOT DoCheck_2791_LoadKBK0_PI_BUDGET_CODE(
                                    GetNodeAttributeEx( xDataXml, 'KDOH'),
                                    xDocInfo,
                                    xDocClass)
        then EXIT;

      Ground := QueryXml('Select * From Ground_Doc Where Link_Document_Id = ?',
        [xDocNodeXml.getAttribute('DOCUMENT_ID')]);
  
      if Ground.documentElement.childNodes.length > 0 then
      begin
        Ground := Ground.documentElement;
        for j := 0 to Ground.childNodes.length - 1 do begin
          xGroundItemXml := Ground.childNodes.items[j];



          xDataZROSN := xDataXml.appendChild(
                            FillElementBySchema(xGroundItemXml, 'ZROSN'));

          xDataZROSN.setAttribute(
                'DATE_OSN',
                IfThen( xGroundItemXml.getAttribute('DOC_DATE') <> '',
                        FormatDateTime(
                              'dd.mm.yyyy',
                              XmlToDateTime( xGroundItemXml.getAttribute('DOC_DATE'))),
                        ''));

          if (not FullZr) then begin
            xDataZROSN.setAttribute('OSN', '');
            // Exchange #2336  выгрузка поля ZROSN.OSN_PLAT с закладки
            // Документ-основание из поля Признак основания платежа
            // exchange #2399 отменяется ТФФ8, а по ТФФ10 аналогично ТФФ9
            // exchange #3021
            // Если значение ZR:TYPE=2, то:
            //   - выгружать «1» , если значение поля «Признак основания
            //     платежа» вкладки «Документ основание» = «Основание платежа»
            //   - выгружать «2», если значение  поля «Признак основания
            //     платежа» вкладки «Документ основание» = «Документ основание»
            // Если значение ZR:TYPE=2 и значение поля пустое,
            // то формировать лог с ошибкой.
            case GetNodeAttributeEx( xGroundItemXml, 'BASE_PAYMENT_FLAG') of
              '1': xDataZROSN.SetAttribute( 'OSN_PLAT', '1');
              '2': xDataZROSN.SetAttribute( 'OSN_PLAT', '2');
            end;//case//
            if (xDocClass = '195') then begin
              if (GetNodeAttributeEx( xDataZROSN, 'OSN_PLAT') = '') then begin
                WriteInfo( FORMAT( 'ЭД %s не выгружен - не заполнено поле «Признак основания платежа» вкладки «Документ основание»',
                                   [ xDocInfo]));
                // при краткой выгрузки это поле обязательно для заполнения,
                // поэтому прерываем выгрузку эд.
                EXIT;
              end;
            end;
          end;//for//

        end;//for//
      end;

      // exchange #3081
      // сохраняем ид.плательщика из шапки эд 194го
      // здесь эд не проверяем. если есть атрибут - его и сохраним
      xPayID := GetNodeAttributeEx( xDocNodeXml, 'PAY_ID');
      xREC_ID := GetNodeAttributeEx( xDocNodeXml, 'REC_ID');

      //строки заявки (ZRST)

      for j := 0 to xDocNodeXml.childNodes.length - 1 do
      begin
        xDocItemXml := xDocNodeXml.childNodes.items[j];
        // exchange #3096
        // создаем, но не выгружаем раздел ZRST
        // это делается в конце цикла - см. ниже.
        xDataZRST   := FillElementBySchema( xDocItemXml, 'ZRST');


        case xDocItemXml.getAttribute('DOCUMENTCLASS_ID') of
          11: begin
              // exchange #3062
              // убран косгу при выгрузке эд не ау/бу
              // переделано форматирование под одну функцию
              if (not param_SpecS) and (xDataZRST.getAttribute('KOD_IST_KBK') = 2)
                then xDataZRST.setAttribute(
                              'KBK_PAY',
                              GetRuleKBKLine_R(
                                    xDocItemXml.getAttribute('KADMR_CODE'),
                                    '0',
                                    '0',
                                    '0',
                                    xDocItemXml.getAttribute('KESR_CODE'),
                                    xDocItemXml.getAttribute('BUDGET_ID'),
                                    FALSE))
              else
                if param_SVR and (xDataZRST.getAttribute('KOD_IST_KBK') = 3)
                  then begin
                    xDataZRST.setAttribute('KBK_PAY', '');
                    xDataZRST.setAttribute('TYPE_KBK_PAY', '');
                    xDataZRST.setAttribute('KOD_IST_KBK', '5');
                  end else
                        xDataZRST.setAttribute(
                              'KBK_PAY',
                              GetRuleKBKLine_R(
                                    xDocItemXml.getAttribute('KADMR_CODE'),
                                    xDocItemXml.getAttribute('KFSR_CODE'),
                                    xDocItemXml.getAttribute('KCSR_CODE'),
                                    xDocItemXml.getAttribute('KVR_CODE'),
                                    xDocItemXml.getAttribute('KESR_CODE'),
                                    xDocItemXml.getAttribute('BUDGET_ID'),
                                    FALSE));
  
              // exchange #2399 отменяется ТФФ8, а по ТФФ10 аналогично ТФФ9
              xDataZRST.setAttribute(
                            'ADD_KLASS_PAY',
                            GetPurposeFulgrantCodeEx(
                                 xDocItemXml.getAttribute('PURPOSEFULGRANT_ID'),
                                 xDocItemXml.getAttribute( 'KDR_CODE' ),
                                 xDocItemXml.getAttribute( 'KDE_CODE' ),
                                 xDocItemXml.getAttribute( 'KDF_CODE' )));
              if (xDocItemXml.getAttribute('REC_ACC_ID') <> '') and
                (GetAccType(xDocItemXml.getAttribute('REC_ACC_ID')) = '5') then
              begin
                if xDocItemXml.getAttribute('PI_ANAL_KIND') <> '' then
                  xDataZRST.setAttribute('TYPE_KBK_RCP', GetTypeKBKIdentificator(xDocItemXml));
                xDataZRST.setAttribute('KBK_RCP', xDocItemXml.getAttribute('PI_BUDGET_CODE'));

                  // exchange #2791
                  // п.1.2: если ZR.KDOH=0, не заполнять поля ZRST.KBK_RCP и
                  // ZRST.TYPE_KBK_RCP. поле ZR.KDOH заполняется из PI_BUDGET_CODE.
                  if (VarToStr( xDataZRST.GetAttribute( 'KBK_RCP')) = '0')
                    then begin
                      xDataZRST.setAttribute( 'KBK_RCP', '');
                      xDataZRST.setAttribute( 'TYPE_KBK_RCP', '');
  
                    end;
              end;
              // Exchange #2353:
  //            Exch2353_SetPurposeGrantToADD_KLASS_RCP( xDataZRST, xDocItemXml);
            end;
        118: begin
              xDataZRST.setAttribute('TYPE_KBK_PAY', IfThen(Copy(KiCodeFormat(xDocItemXml.getAttribute('KI_CODE'),
                xDocItemXml.getAttribute('BUDGET_ID')), 1, 2) = '01', '31', '32'));

              xDataZRST.setAttribute(
                        'KBK_PAY',
                        GetRuleKBKLine_I(
                                    xDocItemXml.getAttribute('KADMI_CODE'),
                                    xDocItemXml.getAttribute('KI_CODE'),
                                    xDocItemXml.getAttribute('KESI_CODE'),
                                    xDocItemXml.getAttribute('BUDGET_ID'),
                                    FALSE));

              if (xDocItemXml.getAttribute('REC_ACC_ID') <> '') and
                (GetAccType(xDocItemXml.getAttribute('REC_ACC_ID')) in ['5', '7', '8', '9']) then
              begin
                if xDocItemXml.getAttribute('PI_ANAL_KIND') <> '' then
                  xDataZRST.setAttribute('TYPE_KBK_RCP', GetTypeKBKIdentificator(xDocItemXml));
                xDataZRST.setAttribute('KBK_RCP', xDocItemXml.getAttribute('PI_BUDGET_CODE'));

                  // exchange #2791
                  // п.1.2: если ZR.KDOH=0, не заполнять поля ZRST.KBK_RCP и
                  // ZRST.TYPE_KBK_RCP. поле ZR.KDOH заполняется из PI_BUDGET_CODE.
                  if (VarToStr( xDataZRST.GetAttribute( 'KBK_RCP')) = '0')
                    then begin
                      xDataZRST.setAttribute( 'KBK_RCP', '');
                      xDataZRST.setAttribute( 'TYPE_KBK_RCP', '');
  
                    end;
              end;
            end;
        195: begin
              { exchange #3081
                Изменить формирование значения полей блока ZSKBK:
                  TYPE_KBK – определять по правилу 1 ФТ-1.
                  KBK – определять по правилу 2 ФТ-1.}
              xKBKType := ExportTypeKbk_LineED_AuBu( xDocItemXml);
              xDataZRST.setAttribute(
                      'TYPE_KBK_PAY',
                      xKBKType);
              case xKBKType of
                '20' :
                  xKBKTemplate := paramTemplateKBKInc;
                '10' :
                  xKBKTemplate := paramTemplateKBKExp;
                else
                  xKBKTemplate := paramTemplateKBKSrc;
              end;

              xKBK := ExportKbk_Rule( xDocItemXml.getAttribute('BUDGET_ID'), xDocItemXml,
                                      xKBKTemplate, xDocItemXml.getAttribute('DOCUMENTCLASS_ID'));
              xDataZRST.setAttribute(
                      'KBK_PAY',
                      xKBK);
              if(Length(StringReplace(xKBK, '0', '')) = 0) then
                xDataZRST.setAttribute('TYPE_KBK_PAY', '');

              // exchange #2447
              Exch2447_UpdateGrantinvesmentCode(
                        xDataZRST,
                        xDocNodeXml.getAttribute('PAY_ACCOUNT'),
                        xDocItemXml.getAttribute('GRANTINVESTMENT_ID'));
  
              // exchange #3081
              Export_KBK_RCP_AuBu( xDocItemXml.getAttribute('BUDGET_ID'),
                                   xDataZRST,
                                   xDocItemXml.parentNode,
                                   xREC_ID,
                                   'KBK_RCP',
                                   'TYPE_KBK_RCP');

              xKBKType := xDataZRST.getAttribute('TYPE_KBK_RCP');
              case xKBKType of
                '20' :
                  xKBKTemplate := paramTemplateKBKInc;
                '10' :
                  xKBKTemplate := paramTemplateKBKExp;
                else
                  xKBKTemplate := paramTemplateKBKSrc;
              end;
                                   
              xDataZRST.setAttribute(
                      'KBK_RCP',
                      ExportKbk_Rule( xDocItemXml.getAttribute('BUDGET_ID'), xDocItemXml,
                                      xKBKTemplate, 1));

            end;
        else begin
              // здесь видимо эд 75й
              if param_SVR and (xDataZRST.getAttribute('KOD_IST_KBK') = 3) then
              begin
                xDataZRST.setAttribute('TYPE_KBK_PAY', '');
                xDataZRST.setAttribute('KBK_PAY', '');
                xDataZRST.setAttribute('KOD_IST_KBK', '5');
              end
              else begin
                xDataZRST.setAttribute('TYPE_KBK_PAY', '20');
                // exchange #3062
                // убран косгу при выгрузке эд не ау/бу
                // переделано форматирование под одну функцию
                xDataZRST.setAttribute(
                        'KBK_PAY',
                        GetRuleKBKLine_D(
                                    xDocItemXml.getAttribute('KADMD_CODE'),
                                    xDocItemXml.getAttribute('KD_CODE'),
                                    xDocItemXml.getAttribute('KESD_CODE'),
                                    xDocItemXml.getAttribute('BUDGET_ID'),
                                    FALSE));
              end;
              if (xDocItemXml.getAttribute('REC_ACC_ID') <> '') and
                (GetAccType(xDocItemXml.getAttribute('REC_ACC_ID')) in ['5', '7', '8', '9']) then
              begin
                if xDocItemXml.getAttribute('PI_ANAL_KIND') <> '' then
                  xDataZRST.setAttribute('TYPE_KBK_RCP', GetTypeKBKIdentificator(xDocItemXml));
                xDataZRST.setAttribute('KBK_RCP', xDocItemXml.getAttribute('PI_BUDGET_CODE'));

                // exchange #2791
                // п.1.2: если ZR.KDOH=0, не заполнять поля ZRST.KBK_RCP и
                // ZRST.TYPE_KBK_RCP. поле ZR.KDOH заполняется из PI_BUDGET_CODE.
                if (VarToStr( xDataZRST.GetAttribute( 'KBK_RCP')) = '0')
                  then begin
                    xDataZRST.setAttribute( 'KBK_RCP', '');
                    xDataZRST.setAttribute( 'TYPE_KBK_RCP', '');
  
                  end;
              end;
            end;
        end;//case//

        // Exchange #2353:
        Exch2353_SetPurposeGrantToADD_KLASS_RCP( xDataZRST, xDocItemXml);
        Exch2353_SetGrantInvestmentToADD_KLASS_RCP( xDataZRST, xDocItemXml);

        if (not FullZr) then begin
          xDataZRST.setAttribute('PURPOSE_KBK', '');
          xDataZRST.setAttribute('NOTE_KBK', '');
        end;

        // exchange #2616 - ТФФ 12
        DoFill2616_ZRST_KBK_RCP( xZR_TYPE, xDocItemXml, xDataZRST);

        // exchange #3081
        // проверяем значение KBK_RCP на выход за 20 символов
        CheckField_PI_BUDGET_CODE( xDataZRST, 'KBK_RCP', vCfg_2791_LoadKBK0_PI_BUDGET_CODE);

        // exchange #2747
        // для всех классов
        // проверяем, если поле KBK_RCP заполнено 20ю нулями,
        // то поля KBK_RCP и TYPE_KBK_RCP очищаем (оставлять пустым).
        if KBK_is_0( GetNodeAttributeEx( xDataZRST, 'KBK_RCP')) then begin
          xDataZRST.SetAttribute( 'KBK_RCP', '');
          xDataZRST.SetAttribute( 'TYPE_KBK_RCP', '');
        end;

        // exchange #3021
        // для краткой выгрузки чистим некоторые поля эд 195го
        if (not FullZr) then
          if (xDocClass = '195') then begin
            xDataZRST.SetAttribute( 'KBK_RCP', '');
            xDataZRST.SetAttribute( 'TYPE_KBK_RCP', '');
            xDataZRST.SetAttribute( 'ADD_KLASS_RCP', '');
            xDataZRST.SetAttribute( 'SUM_R_KBK', '');
            xDataZRST.SetAttribute( 'PURPOSE_KBK', '');
            xDataZRST.SetAttribute( 'NOTE_KBK', '');
          end;


        // exchange #3096
        // добавляем раздел ZRST в список разделов.
        DoAppendZRST_( xDataXml, xDataZRST);
      end;//for//
      Result := True;
      except
        ExceptionProc( 'MakeFormat');
    end;

end; {end MakeFormat}


function DoFill11_Exch2676( aXml, aDataXml: Variant): boolean;
var
  xACC_ID: string;
  xOrgXML: Variant;
  xNAME_UBP_PAY: string;
begin

    try
      Result := TRUE;

      // 1.	Если в поле «Счет для финансирования»  ЭД класса 11 указан
      // лицевой счет с типом «Лицевой счет ФК» и с признаком
      // «Счет иного получателя», то поля формируемого для выгрузки документа
      // «Заявка на кассовый расход» заполняем значениями из таблицы 1
      if ( aXml.getAttribute('DOCUMENTCLASS_ID') <> '11') then EXIT;

      // проверяем ссылку на счет получателя
      xACC_ID := VarToStr( aXml.getAttribute( 'ORGACCOUNT_ID'));

      if (QueryField(  ' select o.OTHER_RECEIVER_FLAG F'
                      +' from orgaccount o where o.id=? and o.orgacctype_id=5',
                       [ aXml.getAttribute( 'ORGACCOUNT_ID')],
                       'F') <> '1')
        then EXIT;

      // получаем описание организации-оператора владельца бланка расходов
      if NOT GetOrgXML_By_EstimateID( aXml.getAttribute( 'ESTIMATE_ID'),
                                      xOrgXML)
        then EXIT;

      // полная выгрузка
      aDataXml.setAttribute( 'TYPE', '1');

      // Наименование клиента - Значение из поля «Официальное название»
      // справочника Организаций Владелец определяется Организация-оператор.
      xNAME_UBP_PAY := GetNodeAttributeValue( xOrgXML, '//*/@MANAGER_DESCRIPTION');
      aDataXml.setAttribute( 'NAME_UBP_PAY', xNAME_UBP_PAY);
      aDataXml.setAttribute( 'NAME_UBP_GRS', xNAME_UBP_PAY);


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

end;



function MakeFormat_11( var xDocNodeXml: Variant; var xDataXml: Variant): boolean;
var
  j: Integer;
  Ground: Variant;
  KesXml: Variant;
  xDocItemXml : Variant;
  xDataZRST   : Variant;
  xDataZROSN  : Variant;
  xGroundItemXml: Variant;
  xZR_TYPE: string;
  xOKATO: String;
begin


  Result := FALSE;

  // exchange #2676
  DoFill11_Exch2676( xDocNodeXml, xDataXml);


    FullZr := (xDataXml.getAttribute('TYPE') = 1);
    xDataXml.setAttribute('NOM_ZR', Trim(xDataXml.getAttribute('NOM_ZR')));
    xDataXml.setAttribute('DATE_ZR', FormatDateTime('dd.mm.yyyy',
      XmlToDateTime(xDataXml.getAttribute('DATE_ZR'))));

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

      xDataXml.setAttribute('GLAVA_GRS',
        StringReplace(Format('%3s', [xDataXml.getAttribute('GLAVA_GRS')]), ' ', '0'));
      xDataXml.setAttribute('NAME_BUD', QueryField(sqlBudgId, [xDocNodeXml.getAttribute('BUDGET_ID')],
        'CAPTION'));
      xDataXml.setAttribute('NAME_FO', QueryField(sqlFoNameByBudg,
        [xDocNodeXml.getAttribute('BUDGET_ID')], 'DESCRIPTION'));
      xDataXml.setAttribute('DATE_ISP', IfThen(xDataXml.getAttribute('DATE_ISP') <> '',
        FormatDateTime('dd.mm.yyyy', XmlToDateTime(xDataXml.getAttribute('DATE_ISP'))), ''));

    // exchange #2675 - заполнение поля DATE_ISP при выгрузке ЗОР
    DoExch2675( xDataXml, 'DATE_ISP', xDocNodeXml.getAttribute('BUDGET_ID'));

    xDataXml.setAttribute('VID_PL', PayKindSetAsFk(xDocNodeXml.getAttribute('PAYKIND')));

    if Trim(xDocNodeXml.getAttribute('AUTHOR_ID')) <> '' then
      xDataXml.setAttribute('PAYSTATUS',
        StringReplace(Format('%2s', [xDocNodeXml.getAttribute('AUTHOR_ID')]),' ', '0'));


    if xDocNodeXml.getAttribute('REC_ACC_ID') = '' then
      //Exchange#1946
      if (xDocNodeXml.getAttribute('REC_ID') <> '')
          and HasOrgRole(xDocNodeXml.getAttribute('REC_ID'), '6')
          and (xDocNodeXml.getAttribute('REC_ACCOUNT') = '00000000000000000000')
        then xDataXml.setAttribute('BS_RCP', '')
        else xDataXml.setAttribute('BS_RCP', xDocNodeXml.getAttribute('REC_ACCOUNT'))
    else
      case GetAccType(xDocNodeXml.getAttribute('REC_ACC_ID')) of
        '2','3':
              //Exchange#1946
              if (xDocNodeXml.getAttribute('REC_ID') <> '')
                  and HasOrgRole(xDocNodeXml.getAttribute('REC_ID'), '6')
                  and (xDocNodeXml.getAttribute('REC_ACCOUNT') = '00000000000000000000')
                then xDataXml.setAttribute('BS_RCP', '')
                else xDataXml.setAttribute('BS_RCP', xDocNodeXml.getAttribute('REC_ACCOUNT'));


        '5', '7', '8', '9':
              if param_Account then begin
                xDataXml.setAttribute('LS_UBP_RCP', xDocNodeXml.getAttribute('REC_ACCOUNT'));
                xDataXml.setAttribute('BS_RCP', xDocNodeXml.getAttribute('REC_UFK_ACCOUNT'));
              end else begin
                xDataXml.setAttribute('LS_UBP_RCP', xDocNodeXml.getAttribute('REC_ACCOUNT'))
              end;

        else begin
              // exchange #2377
              { Если счет в поле «Счет» блока «Плательщик» имеет тип 1,6 - поле BS_RCP
                заполнять значением банковского счета из поля "Счет УФК" блока
                «Расходование».}
              if (GetAccType(xDocNodeXml.getAttribute('REC_ACC_ID')) in ['1', '6'])
                then xDataXml.setAttribute('BS_RCP', xDocNodeXml.getAttribute('REC_UFK_ACCOUNT'));
            end;
      end;//case//


    if FullZr then begin
      xDataXml.setAttribute('INN_UBP', '');
      xDataXml.setAttribute('KPP_UBP', '');
    end else begin
      //затираем данные для сокращенной заявки.
      xDataXml.setAttribute('NAME_UBP_GRS', '');
      xDataXml.setAttribute('NAME_FO', '');

      xDataXml.setAttribute('LS_UBP_RCP', '');
      xDataXml.setAttribute('DOL_RUK_UBP', '');
      xDataXml.setAttribute('DOL_BUH_UBP', '');
    end;

    // exchange #2616 - ТФФ 12 - заполнение поля ZR.OKPO_FO
    DoFill2616_ZR_OKPO_FO( xDocNodeXml, xDataXml);


    // exchange #2801
    // заполнение поля ФАИП в поле ZR.FAIP_CODE только для 11го класса
    ExchExport_FAIP( xDocNodeXml, xDataXml, 'FAIP_CODE');

    // exchange #2616 - сохраняем значение поля ZR.TYPE
    xZR_TYPE := VarToStr( xDataXml.GetAttribute( 'TYPE'));

    // exchange #3081
    // проверяем значение ид.платежа на выход за 20 символов
    CheckField_PI_BUDGET_CODE( xDataXml, 'KDOH', vCfg_2791_LoadKBK0_PI_BUDGET_CODE);

    // exchange #2791 - проверка КБК в ид.платежа
    if NOT DoCheck_2791_LoadKBK0_PI_BUDGET_CODE(
                VarToStr( xDataXml.getAttribute( 'KDOH')),
                FORMAT( '№ %s от %s на сумму %s',
                      [ VarToStr( xDataXml.GetAttribute( 'NOM_ZR')),
                        VarToStr( xDataXml.GetAttribute( 'DATE_ZR')),
                        VarToStr( xDataXml.GetAttribute( 'SUM_V'))]),
                xDocNodeXml.getAttribute('DOCUMENTCLASS_ID'))
      then EXIT;

    //(ZROSN)
    Ground := QueryXml('Select * From Ground_Doc Where Link_Document_Id = ?',
      [xDocNodeXml.getAttribute('DOCUMENT_ID')]);

    if Ground.documentElement.childNodes.length > 0 then begin
      Ground := Ground.documentElement;
      for j := 0 to Ground.childNodes.length - 1 do begin
        xGroundItemXml := Ground.childNodes.items[j];
        xDataZROSN := xDataXml.appendChild(
                          FillElementBySchema(xGroundItemXml, 'ZROSN'));

        xDataZROSN.setAttribute(
              'DATE_OSN',
              IfThen( xGroundItemXml.getAttribute('DOC_DATE') <> '',
                      FormatDateTime(
                            'dd.mm.yyyy',
                            XmlToDateTime( xGroundItemXml.getAttribute('DOC_DATE'))),
                      ''));

        if (not FullZr) then begin
          xDataZROSN.setAttribute('OSN', '');
          // Exchange #2336  выгрузка поля ZROSN.OSN_PLAT с закладки
          // Документ-основание из поля Признак основания платежа
          // exchange #2399 отменяется ТФФ8, а по ТФФ10 аналогично ТФФ9
          xDataZROSN.setAttribute(
                            'OSN_PLAT',
                            xGroundItemXml.getAttribute('BASE_PAYMENT_FLAG'));
        end;
      end;//for//
    end;

    //строки заявки (ZRST)

    for j := 0 to xDocNodeXml.childNodes.length - 1 do begin
      xDocItemXml := xDocNodeXml.childNodes.items[j];
      xDataZRST   := FillElementBySchema( xDocItemXml, 'ZRST');


            // exchange #3062
            // отмена косгу + приведение форматирвоания к единой функции
            if (not param_SpecS) and (xDataZRST.getAttribute('KOD_IST_KBK') = 2)
              then xDataZRST.setAttribute(
                              'KBK_PAY',
                              GetRuleKBKLine_R(
                                    xDocItemXml.getAttribute('KADMR_CODE'),
                                    '0',
                                    '0',
                                    '0',
                                    xDocItemXml.getAttribute('KESR_CODE'),
                                    xDocItemXml.getAttribute('BUDGET_ID'),
                                    FALSE))
              else
                if param_SVR and (xDataZRST.getAttribute('KOD_IST_KBK') = 3)
                  then begin
                    xDataZRST.setAttribute('KBK_PAY', '');
                    xDataZRST.setAttribute('TYPE_KBK_PAY', '');
                    xDataZRST.setAttribute('KOD_IST_KBK', '5');
                  end else
                    xDataZRST.setAttribute(
                              'KBK_PAY',
                              GetRuleKBKLine_R(
                                    xDocItemXml.getAttribute('KADMR_CODE'),
                                    xDocItemXml.getAttribute('KFSR_CODE'),
                                    xDocItemXml.getAttribute('KCSR_CODE'),
                                    xDocItemXml.getAttribute('KVR_CODE'),
                                    xDocItemXml.getAttribute('KESR_CODE'),
                                    xDocItemXml.getAttribute('BUDGET_ID'),
                                    FALSE));

            // exchange #2399 отменяется ТФФ8, а по ТФФ10 аналогично ТФФ9
            xDataZRST.setAttribute(
                          'ADD_KLASS_PAY',
                          GetPurposeFulgrantCodeEx(
                               xDocItemXml.getAttribute('PURPOSEFULGRANT_ID'),
                               xDocItemXml.getAttribute( 'KDR_CODE' ),
                               xDocItemXml.getAttribute( 'KDE_CODE' ),
                               xDocItemXml.getAttribute( 'KDF_CODE' )));
      // Exchange #2353:
      Exch2353_SetPurposeGrantToADD_KLASS_RCP( xDataZRST, xDocItemXml);
      Exch2353_SetGrantInvestmentToADD_KLASS_RCP( xDataZRST, xDocItemXml);

      if (not FullZr) then begin
        xDataZRST.setAttribute('PURPOSE_KBK', '');
        xDataZRST.setAttribute('NOTE_KBK', '');
      end;

      // exchange #2616 - ТФФ 12
      DoFill2616_ZRST_KBK_RCP( xZR_TYPE, xDocItemXml, xDataZRST);



      // exchange #3096
      // добавляем раздел ZRST в список разделов.
      DoAppendZRST_( xDataXml, xDataZRST);
    end;//for//
  xOKATO := xDataXml.getAttribute('OKATO');
  if (KBK_is_0(xOKATO)) then
  begin
    IsCriticalError := true;
    WriteLog('Значение OKATO не может состоять из всех нулей');
  end;
  Result := TRUE;

end;


begin
  Main(NULL);
end.
