{~DoExportPurposefulgrant
  выгрузка кодов цели
  exchange #2473
  aBudgetID - бюджет
  aCfgOutListKbk - опция конфигурации: "Выгружать КБК из списка"

  если опсия aCfgOutListKbk=true, выгрузка осуществляется из диалога.
  выгружаются только выбранные коды.
  если aCfgOutListKbk=false, выгружаются все записи из справочника "коды цели"
  удовлетворяющие ФТ-3 exchange #2473, а диалог не открывается.

      Для корректного формирования документа рекомендуется для кодов целевых
    назначений заполнить либо откорректировать строку вкладки
    «Правоустанавливающие акты». В строку выбрать нормативный акт,
    регламентирующий действие данного целевого назначения,
    значение поля «Дата вступления в силу» которого будет соответствовать
    значению реквизита «Дата начала действия» выгружаемого документа,
    значение поля «Срок действия» будет соответствовать значению реквизита
    «Дата окончания действия» выгружаемого документа.
    Если значение поля «Дата вступления в силу» будет не заполнена,
    то  реквизиту «Дата начала действия» будет присвоено условное
    значение «31.12.2008». Если значение поля «Срок действия» будет иметь
    пустое значение, то реквизит «Дата окончания действия»
    будет выгружаться пустым.  }
procedure DoExportPurposefulgrant( aBudgetID: string;
                                    aCfgParamRef: boolean;
                                    aCfgOutListKbk: boolean;
                                    aCfg_2851: boolean);
var
  xSL: TStringList;
  xFileNameExport: string;
  xPacketNumber: integer;
begin

    try
      xSL:= TStringList.Create;
      try
        { значение даты последней выгрузки КБК для текущего бюджета.
          получаем его из файла Send.dat для текущего бюджета.
          загрузка параметра даты в файле Send.Dat для бюджета aBudgetID.
          если даты не будет (или такого бюджета), дата должны быть указана
          на 1990/1/1 0:0:0:0}
        vCfgSelectorKBK_LastDate := DateTimeFromStr_YYYYMMDD_HHMMSS(
                                        LoadFromSendDat(
                                            'ВЫГРУЗКА_'+IniSection,
                                            'БЮДЖЕТ_' + aBudgetID,
                                            '1990/01/01 00:00:00'));


        //Загрузка схемы
        // проблема в том, что схема kd_txkd100701.xml и секция KD используется
        // при выгрузке кодов субсидий, поэтому схема называется по другому,
        // раздел inisection - другой, а расширение файла:
        // ОБЯЗАТЕЛЬНО ДОЛЖНО БЫТЬ KD!
        // exchange #2542 - переход на тфф11 + переработка модуля проверки версий схем
        LoadSchema( GetFileNameSchemaTFF( 'kdp_txkdp*'));
//        LoadSchema(DirIni + 'Schems\kdp_txkdp120101.xml');
        // выгрузка КБК
        vExportListID_Action := '';
        if MakeExportPurposefulgrant( aBudgetID,
                                      xSL,
                                      aCfgParamRef,
                                      aCfgOutListKbk,
                                      Schema,
                                      aCfg_2851) then begin
          //валидация схем.
          if param_CtlValidOn then
            if not ValidateFormat then
              if Not ShowMessageValid( FileValidate) then begin
                WriteLog('Выгрузка прервана пользователем');
                Exit;
              end;
          
          // имя файла экспорта XML
          WriteLog('Формирование имени выгружаемого файла', True);
          // Чтение номера посылки.
          xPacketNumber := LoadSendDatPacketNumber( IniSection);
          xFileNameExport :=
                DirOut + GetFileName( Fo.getAttribute('NAME'),
                                      'KD',
                                      Now,
                                      xPacketNumber,
                                      FileOutIsLocalNet,
                                      FileOutOrgCodeIsFk);
          
          // сохраняем XML в текстовом файле
          
          try
            WriteLog( FORMAT( 'Сохранение XML в файле "%s"...', [ xFileNameExport]), TRUE);
            XmlToTextFile( xFileNameExport);
            except
              ExceptionLog( 'Сбой сохранения XML');
          end;

          // фиксируем экспорт на сервере АЦК-финансы
          // exchange #3027
          // здесь фиксируется только дата выгрузки.
          // алгоритм этой даты отличается от принятого с другими кодами.
          // требуется совместимость с АЦК-Ф 2.38 не ниже сборки 77
          FixedExportedListIDEx( xFileNameExport, xSL, 'pg');

          // сохраняем номер выгрузки
          SaveSendDatPacketNumber( IniSection, xPacketNumber);
          { сохраняем дату выполнения операции как дату выгрузки КБК
            сохранение параметра в файле Send.Dat }
          SaveToSendDat(  'ВЫГРУЗКА_'+IniSection,
                          'БЮДЖЕТ_' + aBudgetID,
                          DateTimeToStr_YYYYMMDD_HHMMSS( NOW));
        end;
        finally
          xSL.Free;
      end;
      except
        ExceptionLog( 'Сбой Un_Kbk8.DoExportSubDohIst;');
    end;

end;


function BuildSqlWhereInFromStringList( aFieldName: string;
                                         aValues: TStringList;
                                         aPackedCount: integer = 300): string;
var
  i,n: integer;
begin

    try
      Result := '';
      n := 0;
      for i := 0 to aValues.Count - 1 do begin
        if (n <= 0) then begin
          if (i > 0) then Result := Result + ' or ';
          Result := Result + aFieldName + ' in (';
        end;
        if (n > 0) then Result := Result + ',';
        Result := Result + aValues.Strings[i];
        INC( n);
        // завершение условия
        if (n >= aPackedCount) then begin
          n := 0;
          Result := Result + ') ';
        end;
      end;//for//
      if (n > 0) then Result := Result + ') ';

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

end;

function MakeExportPurposefulgrant( aBudgetID: string;
                                     aListID: TStringList;
                                     aCfgParamRef: boolean;
                                     aCfgOutListKbk: boolean;
                                     aSchema: Variant;
                                     aCfg_2851: boolean): Boolean;
var
  i,i2: Integer;
  s: string;
  XmlListCodeforCds: Variant; //содержит перечень кодов для выбора из списка.
  xFormCaption: string;
  xXmlQuery: Variant;
  xXmlQueryNode: Variant;
  xXmlQueryKBK: Variant;
  xXmlQueryKBKNode: Variant;
  xXmlOut: Variant;
  xXmlDoc: Variant;
  xXmlData: Variant;
  xFSourceCode, xBudgLevelID, xBudgLevelCode: string;
  xKDSTExists: boolean;
  xPurposefullGrantID: boolean;
  xKbkLineType: Integer;
  xKBKd, xKBKr: String;
  xOrgID_FK: String;

  procedure DoFillKDST_( aKBK_D, aKBK_R: string);
  var
    xLawactXml: variant;
    xDateBegin: string;
    xDateEnd: string;
  begin

      try
        // exchange #2851
        // определяем "правоустанавливающие акты"
        // загружаем все акты, у которых дата окончания либо не указана,
        // либо >= рабочей даты.
        xLawactXml := QueryXml( ' select l.* from pl_lawact l'
                               +' join purposefulgrant_lawact_list pl on'
                               +'  pl.pl_lawact_id=l.id'
                               +' where pl.purposefulgrant_id=?'
                               +' and (l.end_date is null or l.end_date>=?)',
                                [ xPurposefullGrantID,
                                  Work_Date]);
        if (xLawactXml.DocumentElement.ChildNodes.Length <= 0) then begin
          // допускается что таких актов не будет.
          // Если строк нет, то присваиваем значение 31.12.2008.
          xDateBegin  := '31.12.2008';
          // Если значение пустое, то дату окончания не заполнять
          xDateEnd    := '';
        end else begin
          xLawactXml  := xLawactXml.DocumentElement.ChildNodes.Item[0];
          xDateBegin  := xLawactXml.GetAttribute( 'START_DATE');
          xDateEnd    := xLawactXml.GetAttribute( 'END_DATE');
        end;

        // создаем строку для каждого БК кода цели
        xXmlData := xXmlDoc.appendChild(
                            FillElementBySchemaEx( aSchema, 'KDST', NULL));
        // файл выгружается, если есть хотя бы один раздел KDST
        xKDSTExists := TRUE;
        // GUID - Не выгружается
        xXmlData.SetAttribute( 'GUID', '');
        // GUID_PARENT - Не выгружается
        xXmlData.SetAttribute( 'GUID_PARENT', '');
        // Код ОрФК  - Не выгружается
        xXmlData.SetAttribute( 'KOD_TOFK_C', '');
        // Код цели	- Указывается значение поля «Код» карточки
        // «Целевого назначения»
        xXmlData.SetAttribute( 'ADD_KLASS',
                                xXmlQueryNode.GetAttribute( 'CODE'));
        // Краткое наименование кода цели - Не выгружается
        xXmlData.SetAttribute( 'CNAME', '');
        // Полное наименование кода цели - Значение поля «Наименование»
        // карточки целевого назначения.
        // exchange #2629 - замена кавычек
        xXmlData.SetAttribute(
                'NAME',
                ExchangeQuoteChars2629(
                      'KD',
                      VarToStr( xXmlQueryNode.GetAttribute( 'DESCRIPTION'))));
        // Признак отнесения к дополнительной классификации
        // Если в поле «Источник средств» карточки «Целевые назначения»
        // значение М – «Муниципальные средства», П – «Средства поселений»
        // заполняем значением 1 - «дополнительная классификация».
        // Если иное значение не выгружается.
        // exchange #2795
        // переход на тфф 14. пп.4:
        // Если в поле «Источник средств» карточки «Целевые
        // назначения» значение Р- «Региональные средства» или
        // М – «Муниципальные средства» или П – «Средства поселений»
        // заполняем значением 1 - «дополнительная классификация».
        // Если иное значение не выгружается.
        // поскольку на момент доработок осталась только схема тфф13,
        // то проверяем только ее.
        // exchange #2851
        // выгружается 1 по старому или Если KBK_D и KBK_R пустые.
        // В остальных случаях не выгружается.
        if IsVersionSupport( cnVersionTFF_13) then begin
          // тфф13
          if (( xFSourceCode in [ 'М', 'П'])
              OR ((LENGTH( aKBK_D) <= 0) AND (LENGTH( aKBK_R) <= 0)))
            then xXmlData.SetAttribute( 'PRT_TYPE', '1');
        end else begin
          // прочие тфф, отличные от тфф13
          if (( xFSourceCode in [ 'М', 'П', 'Р'])
              OR ((LENGTH( aKBK_D) <= 0) AND (LENGTH( aKBK_R) <= 0)))
            then xXmlData.SetAttribute( 'PRT_TYPE', '1');
        end;
        // Признак отсутствия контроля со стороны ОрФК - Не выгружается
        xXmlData.SetAttribute( 'PRT_CONTR', '');
        { Код уровня бюджета	BUDG_LEVEL
          Если в поле «Источник средств» карточки «Целевые назначения»
            Р – «Региональные средства»
                заполняем значением: 2 - «бюджет субъекта РФ»;

            М – «Муниципальные средства»,
            П – «Средства поселений»
                заполняем значением: 3 - «местный бюджет». }
        if (xFSourceCode = 'Р')
          then xXmlData.SetAttribute( 'BUDG_LEVEL', '2')
          else xXmlData.SetAttribute( 'BUDG_LEVEL', '3');
        // КБК доходов
        xXmlData.SetAttribute( 'KBK_D', aKBK_D);
        // КБК расходов
        xXmlData.SetAttribute( 'KBK_R', aKBK_R);
        // Дата начала действия - Всегда 01.01.2013
        // exchange #2851 - дата берется из "правоустанавливающие акты"
        xXmlData.SetAttribute( 'DATE_BEGIN', xDateBegin);//'01.01.2013');
        // Дата окончания действия  - Не выгружается
        // exchange #2851 - дата берется из "правоустанавливающие акты"
        xXmlData.SetAttribute( 'DATE_END', xDateEnd);
        // Статус: Всегда  1 – «активный»
        xXmlData.SetAttribute( 'STATUS', '1');
        // Дата и время последнего изменения- Значение текущей рабочей даты.
        xXmlData.SetAttribute(
              'DATE_CHANGE',
              FormatDateTime('dd.mm.yyyy hh:nn:ss', NOW));
        except
          ExceptionLog( 'Сбой DoFillKDST_');
      end;

  end;

begin

    try
      Result := False;
      xKDSTExists := FALSE;

      WriteLog('Получение данных по кодам цели...', True);
      if NOT DoExportPurposefulgrandChoice( aBudgetID,
                                            aCfgOutListKbk,
                                            aListID,
                                            aCfg_2851)
        then begin
          WriteInfo( 'Коды цели не выгружаются.', TRUE);
          EXIT;
        end;

      WriteLog('Выгрузка кодов цели...', True);

      // теперь нужно построить большой запрос с перечислением всех ID
      // в группы in (...) or in (...)
      // для начала формируем строку с таким условием, а потом будем
      // формировать запрос.
{отладка
      showmessage( alistid.text);
{отладка}
      xXmlQuery := QueryXml( ' select K.*, KS.code KSCODE_, bl.id BL_ID, bl.code BL_CODE '
                              +' from PURPOSEFULGRANT K '
                              +' join budget b on b.id = k.budget_id '
                              +' join budglevel bl on bl.id = b.budglevel_id '
                              +' left join PURPOSEFULGRANT_FSOURCE KS '
                              +'   on KS.id=K.purposefulgrant_fsource_id '
                              +' Where '
                              + BuildSqlWhereInFromStringList( 'K.ID', aListID));

      // формируем XML для выгрузки
      try
        xXmlOut := CreateOleObject('Microsoft.XmlDom');
        xXmlDoc := xXmlOut.appendChild( xXmlOut.createElement('FORMAT'));

        // FK
        xXmlData := xXmlDoc.appendChild(
                                  FillElementBySchemaEx( aSchema, 'FK', NULL));
        xXmlData.setAttribute('FORM_VER', AppVersion);

        // FROM
        xXmlData := xXmlDoc.appendChild(
                                  FillElementBySchemaEx( aSchema, 'FROM', NULL));
        // Код ОрФК Не выгружается
        xXmlData.SetAttribute('KOD_TOFK', '');
        // Наименование ОрФК Не выгружается
        xXmlData.SetAttribute('NAME_TOFK', '');
        // Код уровня бюджета - Определяется из поля  «Код типа бюджета»
        // уровня бюджета, указанного в «Справочники/Бюджет/Бюджеты/Карточка
        // бюджета/Уровень бюджета».
        xXmlData.SetAttribute('BUDG_LEVEL', GetBudgLevel( aBudgetID));
        // описание организации фин.органа бюджета
        // код клиента - Значение из поля «Код организации» карточки организации.
        xXmlData.SetAttribute(
              'KOD_UBP',
              QueryField( ' Select O.*, Coalesce(Ob.Code_Fk, O.Name) Org_Code From Org O '
                          +' join budget b on b.org_id=o.id ' +
                          ' left join OrgBudgetDet Ob on Ob.Org_Id = O.Id and Ob.Budget_Id = b.id ' +
                          ' where b.id=?',
                          [ aBudgetId],
                          'ORG_CODE'));

        if xXmlData.GetAttribute('KOD_UBP') = '' then
          WriteLog('Не указан код организации клиента', True);
                          
        // наименование клиента - оффициальное Наименование Финансового органа
        // осуществляющего выгрузку справочника.
        // Определяется из карточки бюджета, по значению поля «Финансовый орган».
        xXmlData.SetAttribute(
              'NAME_UBP',
              QueryField( ' select o.name, o.description from org o '
                          +' join budget b on b.org_id=o.id where b.id=?',
                          [ aBudgetId],
                          'DESCRIPTION'));

        // TO
        xXmlData := xXmlDoc.appendChild(
                              FillElementBySchemaEx( aSchema, 'TO', NULL));
        // BUDG_LEVEL - не выгружается
        xXmlData.SetAttribute('BUDG_LEVEL', '');
        // Код клиента - не выгружается
        xXmlData.SetAttribute('KOD_UBP', '');
        // Наименование клиента - не выгружается
        xXmlData.SetAttribute('NAME_UBP', '');
        // Код и оффициальное наименование организации, указанной
        // в системных настройках УФК «Сервис/Системные параметры/УФК» поле «УФК»
        // в начале заполняем поля пустым значением, а потом выгружаем в них
        // поля из организации, если она прописана в настройках.
        // если в настройках организация не указана - поля заполняются
        // пустым значением.
        xXmlData.SetAttribute('KOD_TOFK', '');
        xXmlData.SetAttribute('NAME_TOFK', '');
        
        WriteLog('Определение данных ТОФК (ОрФК)', True);
        // по этим данным при выгрузке заполняются KOD_TOFK и NAME_TOFK в разделе TO

        // Exchange, #3217      ТОФК м.б. из парам. конфига
        if (LENGTH( TRIM( vCfg_OrgID_FK)) > 0) then
          xOrgID_FK := vCfg_OrgID_FK
        else
          xOrgID_FK := SysParam_UFG_OrgID(aBudgetId);
        
        FillXmlOrgNameAndOfficialDescr( xXmlData,
                                        'KOD_TOFK',
                                        'NAME_TOFK',
                                        xOrgID_FK);

        // KD
        xXmlData := xXmlDoc.appendChild(
                                FillElementBySchemaEx( aSchema, 'KD', NULL));
        // Глобальный уникальный идентификатор -	Не выгружается
        xXmlData.SetAttribute('GUID_FK', '');
        // Наименование бюджета - Значение поля «Название» из карточки бюджета.
        xXmlData.SetAttribute(
              'NAME_BUD',
              QueryField( sqlBudgId, [ aBudgetID], 'CAPTION'));
        // Дата формирования файла - заполняется системной датой на момент выгрузки
        xXmlData.setAttribute(
              'DATE_FORM',
              FormatDateTime('dd.mm.yyyy', NOW));
        // Должность ответственного исполнителя - берется из конфигурации
        xXmlData.setAttribute('DOL_ISP', DolIsp);
        // ФИО ответственного исполнителя  - берется из конфигурации
        xXmlData.setAttribute('NAME_ISP', FioIsp);
        // Телефон ответственного исполнителя - берется из конфигурации
        xXmlData.setAttribute('TEL_ISP', TelIsp);

        // строки
        // особенность в том, что при выгрузке каждая строка KD выгружается
        // по списку КБК каждого кода цели. в результате для каждого кода
        // будет столько строк, сколько в описании кода цели строк КЦСР,КВР.
        // делаем так: перебираем все коды цели и для каждой строки отдельно
        // запрашиваем список КБК. это медленнее, зато понятнее.
        try
          xXmlQuery := xXmlQuery.DocumentElement;
          SetProgress( 0, xXmlQuery.ChildNodes.Length);
          for i := 0 to xXmlQuery.ChildNodes.Length - 1 do begin
            ShowProgress( i);
            xXmlQueryNode := xXmlQuery.ChildNodes.Item[i];

            // сохраняем ID кода цели
            xPurposefullGrantID := xXmlQueryNode.GetAttribute( 'ID');

            // код источника средств кода цели
            xFSourceCode := UPPERCASE( xXmlQueryNode.GetAttribute( 'KSCODE_'));
            // уровень бюджета
            xBudgLevelID := VarToStr(xXmlQueryNode.GetAttribute('BL_ID'));
            // код элемента бюджета
            xBudgLevelCode := VarToStr(xXmlQueryNode.GetAttribute('BL_CODE'));

            // Определяем, из какого списка будем запрашивать - "Предоставление МБТ" или "Получение МБТ"
            xKbkLineType := -1; // инициализируем этим значением, т.к. если не удастся определить, то КБК выгружать не нужно
            // условия для тех кодов, у которых КБК будем искать в списке "Предоставление МБТ"
            
            if (    ((xBudgLevelID = '2') and (xFSourceCode = 'Р'))
                 or (     (xBudgLevelID = '3')
                      and (    ((xFSourceCode = 'М') and ((xBudgLevelCode = '05') or (xBudgLevelCode = '11')))
                            or ((xFSourceCode = 'П') and ((xBudgLevelCode = '10') or (xBudgLevelCode = '12') or (xBudgLevelCode = '13')))
                          )
                    )
               ) then xKbkLineType := 1 // предоставление
            else
            // условия для тех кодов, у которых КБК будем искать в списке "Получение МБТ"
            if (     (xBudgLevelID = '3')
                 and (    (xFSourceCode = 'Р')
                       or ((xFSourceCode = 'М') and ((xBudgLevelCode = '10') or (xBudgLevelCode = '12') or (xBudgLevelCode = '13')))
                     )
               ) then xKbkLineType := 0; // получение


            
            // из списка "предоставление МБТ"
            xXmlQueryKBK := QueryXml( ' select K.* from purposefulgrant_aims k '
                                      +' where k.purposefulgrant_id=? '
                                      +' and k.LINE_TYPE=?',
                                      [ xPurposefullGrantID, xKbkLineType]);
            xXmlQueryKBK := xXmlQueryKBK.DocumentElement;
            // exchange #2851
            // если выгружаются все коды цели, то допускается, что у некоторых
            // КЦ может не быть строк "предоставление МБТ", тогда для них
            // заполняется одна строка
            if (xXmlQueryKBK.ChildNodes.Length <= 0)
              then DoFillKDST_('','')
              else
                for i2 := 0 to xXmlQueryKBK.ChildNodes.Length - 1 do begin
                  xXmlQueryKBKNode := xXmlQueryKBK.ChildNodes.Item[i2];
                  // для уровня бюджета "2" с "источником средств" равным "Р" доходную классификаию не выгружаем
                  if ((xBudgLevelID = '2') and (xFSourceCode = 'Р')) then
                    xKBKd := ''
                  // во всех остальных случаях выгружаем
                  else
                    xKBKd := GetRuleKBKLine_D(
                              xXmlQueryKBKNode.GetAttribute( 'KADMD_CODE'),
                              xXmlQueryKBKNode.GetAttribute( 'KD_CODE'),
                              xXmlQueryKBKNode.GetAttribute( 'KESD_CODE'),
                              aBudgetID,
                              NOT( vCfg_3049));
                  // расходную классификацию выгружаем для всех
                  xKBKr :=  GetRuleKBKLine_R(
                            xXmlQueryKBKNode.GetAttribute( 'KADMR_CODE'),
                            xXmlQueryKBKNode.GetAttribute( 'KFSR_CODE'),
                            xXmlQueryKBKNode.GetAttribute( 'KCSR_CODE'),
                            xXmlQueryKBKNode.GetAttribute( 'KVR_CODE'),
                            xXmlQueryKBKNode.GetAttribute( 'KESR_CODE'),
                            aBudgetID,
                            NOT( vCfg_3049));
                    DoFillKDST_(xKBKd, xKBKr);
              end;//for//
          end;//for//
          finally
            SetProgress( 0, 0);   // чистим прогрессбар
        end;
        except
          ExceptionLog( 'Сбой формирования XML');
      end;

      // документ выгруженого XML
      Data := xXmlOut;

      // файл выгружается, если есть хотя бы один раздел KDST
      if NOT xKDSTExists then begin
        WriteInfo( 'Нет ни одного раздела KDST для выгрузки. Файл кодов цели не будет создан.', TRUE);
        EXIT;
      end;

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

end;


{~DoExportPurposefulgrandChoice
  определение списка выгружаемых кодок целей.
  результат:
    =true - что то нужно выгрузить.
    =false - ничего не будет выгружено.
  список выгружаемых кодов (идентификаторов) в списке aListID.}
function DoExportPurposefulgrandChoice( aBudgetID: string;
                                        aOpenDialog: boolean;
                                        var aListID: TStringList;
                                        aCfg_2851: boolean): boolean;
var
  xForm: TFormCustomList;
  xXml: Variant;
  i: integer;
  xCdsList: TClientDataSet;
  xDBGrid: TDBGridEh;
  xEdtCdsId: TEdit;

  {~QueryXml_
    запрос ид.кодов целей для выгрузки
    объединенный как для таблицы списка выборки, так и для случая, кодга
    список не отображается и нужно получить только список всех КЦ для выгрузки.}
  procedure QueryXml_( aSelect: string);
  var
    xSubSQL: string;
  begin

      try
        // проверяем настройку "Формировать KD по всем кодам цели" и в зависимости от ее значения накладываем условия
        if aCfg_2851
          // если настройка включена - дополнительных условий не накаладываем
          then xSubSQL := ''
          // если настройка выключена - условия в зависимости от уровня бюджета и прочей хрени
          else xSubSQL := ' and '
                  +'( '
                  // выгружаем коды только для бюджета уровня "2" с источником средств "Р" и если есть запись в справочнике "Предоставление МБТ"
                  +'     (     b.budglevel_id = 2 '
                  +'      and  k.PURPOSEFULGRANT_FSOURCE_ID = (select pfs.id from purposefulgrant_fsource pfs where pfs.code = '#39'Р'#39') '
                  +'      and  exists (select null from purposefulgrant_aims pa where pa.line_type=1 and pa.purposefulgrant_id=k.id) '
                  +'     ) '
                  +' or '
                  // или для бюджета уровня "3"
                  +'    (      b.budglevel_id = 3 '
                          // в котором
                  +'      and '
                  +'          ( '
                                // источник средств "Р" и есть запись в справочнике "Получение МБТ"
                  +'            ( '
                  +'               k.PURPOSEFULGRANT_FSOURCE_ID = (select pfs.id from purposefulgrant_fsource pfs where pfs.code = '#39'Р'#39') '
                  +'               and  exists (select null from purposefulgrant_aims pa where pa.line_type=0 and pa.purposefulgrant_id=k.id) '
                  +'            ) '
                                // или
                  +'            or '
                               // источник средств "М" и значение "Код элемента" бюджета соответствует одному из значений "05","11"
                               // и есть запись в справочнике "Предоставление МБТ"
                  +'            ( '
                  +'                k.PURPOSEFULGRANT_FSOURCE_ID = (select pfs.id from purposefulgrant_fsource pfs where pfs.code = '#39'М'#39') '
                  +'                and bl.code in ('#39'05'#39', '#39'11'#39') '
                  +'                and  exists (select null from purposefulgrant_aims pa where pa.line_type=1 and pa.purposefulgrant_id=k.id) '
                  +'            ) '
                                // или
                  +'            or '
                               // источник средств "М" и значение "Код элемента" бюджета соответствует одному из значений "10","12","13"
                               // и есть запись в справочнике "Получение МБТ"
                  +'            ( '
                  +'                k.PURPOSEFULGRANT_FSOURCE_ID = (select pfs.id from purposefulgrant_fsource pfs where pfs.code = '#39'М'#39') '
                  +'                and bl.code in ('#39'10'#39', '#39'12'#39', '#39'13'#39') '
                  +'                and  exists (select null from purposefulgrant_aims pa where pa.line_type=0 and pa.purposefulgrant_id=k.id) '
                  +'            ) '
                  +'            or '
                               // источник средств "П" и значение "Код элемента" бюджета соответствует одному из значений "10","12","13"
                               // и есть запись в справочнике "Предоставление МБТ"
                  +'            ( '
                  +'                k.PURPOSEFULGRANT_FSOURCE_ID = (select pfs.id from purposefulgrant_fsource pfs where pfs.code = '#39'П'#39') '
                  +'                and bl.code in ('#39'10'#39', '#39'12'#39', '#39'13'#39') '
                  +'                and  exists (select null from purposefulgrant_aims pa where pa.line_type=1 and pa.purposefulgrant_id=k.id) '
                  +'            ) '
                  +'          )'
                  +'     )'
                  +') ';

        // exchange #3027
        // в режиме выгрузки «Выгружать КБК из списка» = «Нет»
        // требуется автоматически формировать список строк для выгрузки
        // следующим образом:
        // включать в список все строки, отвечающие отвечающим условиям
        // отбора реализации, и с пустой датой выгрузки;
     //   if NOT aOpenDialog
     //     then xSubSQL := xSubSQL + ' and k.SEND_DATE is null';

        xXml := QueryXml(
                   ' Select ' + aSelect
                  +' From PURPOSEFULGRANT K '
                  +' join budget b on b.id = k.budget_id '
                  +' join budglevel bl on bl.id = b.budglevel_id '
                  +' left join purposefulgrant_fsource pfgs'
                  +'      on pfgs.id=K.purposefulgrant_fsource_id'
                  +' Where K.Budget_Id = ?'
                  +'       and K.CONTROLFK_FLAG = 1 and K.BLOCK_FLAG = 0'
                  +'       and (k.PURPOSEFULGRANT_FSOURCE_ID in (select pfs.id '
                  +'                                             from purposefulgrant_fsource pfs'
                  +'                                             where pfs.code in ('#39'М'#39','#39'Р'#39','#39'П'#39')))'                  // exchange #2851
                  // добавлена проверка на наличие "правоустанавливающих актов"
                  // если есть хотя бы один акт у которого дата окончания
                  // указана и меньше рабочей даты, такой КЦ не должен
                  // выгружаться.
                  // в результате, если у КЦ нет ни одного акта, либо
                  // нет ни одного акта с датой окончания <раб.даты,
                  // то такой КЦ выгружаем.
                  +'   and not exists('
                  +' select null from pl_lawact l'
                  +' join purposefulgrant_lawact_list pl on'
                  +'  pl.pl_lawact_id=l.id'
                  +' where pl.purposefulgrant_id=k.id'
                  +' and (l.end_date is not null and l.end_date<?))'
                  +xSubSQL,
                   [ aBudgetID,
                     Work_Date]);
        except
          ExceptionLog( 'Сбой QueryXml_');
      end;

  end;


  // функция заполняет указанную таблицу aDBGrid, с набором данных: aCdsList
  // по запросу из справочника кодок целей
  function DoUpdateCDS( var aCdsList: TClientDataSet;
                        var aDBGrid: TDBGridEh): boolean;
  var
    xNode: Variant;
    i: integer;
  begin
    
      try
        QueryXml_( ' Cast(K.id As VarChar(20)) CODE, '
                  +' K.CODE Caption, K.description DESCRIPTION, '
                  +' pfgs.caption SOURCEDESC,'
                  // exchange #3027
                  // добавлена дата выгрузки кода цели
                  // работает с ацк-ф не ниже 2.38.0.77
                  +' K.send_date ' );
        if (xXml.documentElement.childNodes.Length <= 0) then begin
          Result := FALSE;
          EXIT;
        end;

        xXml := xXml.documentElement;

        aCdsList.DisableControls;
        aDBGrid.BookmarkUnCheckAll;
        aDBGrid.Enabled := False;
        try
          // чистка таблицы
          try
            aCdsList.First;
            while not aCdsList.Eof do begin
              aCdsList.Delete;
              aCdsList.First;
            end;
            except
              ExceptionLog( 'Сбой чистки таблицы.');
          end;

          // заполнение таблицы
          for i := 0 to xXml.childNodes.Length - 1 do  begin
            xNode := xXml.childNodes.Item[i];
            try
              aCdsList.Append;

              // идентификатор и код - это одно и то же поле - ид.кода цели
              aCdsList.FieldByName('ID'          ).AsString :=
                  xNode.getAttribute('CODE');
              aCdsList.FieldByName('CODE'        ).AsString :=
                  xNode.getAttribute('CODE');

              aCdsList.FieldByName('CAPTION'     ).AsString :=
                  xNode.getAttribute('CAPTION');
              aCdsList.FieldByName('DESCRIPTION' ).AsString :=
                  xNode.getAttribute('DESCRIPTION');
              aCdsList.FieldByName('SOURCEDESC' ).AsString :=
                  xNode.getAttribute('SOURCEDESC');

              // exchange #3027 - добавлена дата выгрузки
              if (VarToStr( xNode.getAttribute('SEND_DATE')) <> '')
                then aCdsList.FieldByName('SEND_DATE').AsDateTime :=
                        XmlToDateTime( xNode.getAttribute('SEND_DATE'));

              aCdsList.Post;
              except
                ExceptionLog( 'Сбой заполнения строки.');
            end;
          end;//for//
          finally
    //        aCdsList.First;
            aDBGrid.Enabled := True;
            aCdsList.EnableControls;
        end;
        Result := TRUE;
        except
          ExceptionLog( 'Сбой DoUpdateCDS');
      end;
    
  end;

begin

    try
      Result := FALSE;

      // если форму открывать не нужно, сразу формируем запрос с нужным
      // фильтром и получаем список ID
      if NOT aOpenDialog then
        try
          QueryXml_( 'k.id');
          if (xXml.documentElement.childNodes.Length > 0) then begin
            xXml := xXml.documentElement;
            for i := 0 to xXml.childNodes.Length - 1
              do aListID.Add( xXml.childNodes.Item[i].GetAttribute( 'ID'));
            Result := TRUE;
            EXIT;
          end;
          WriteInfo( 'Нет кодов целевых назначений для выгрузки.');
          EXIT;
          except
            ExceptionLog( 'Сбой получения кодов цели без открытия диалога.');
        end;

      // открываем диалог с выбором коов из справочника
      // справочник древовидный, а поскольку выгружать нужно коды по условию,
      // то возникает кривизна в отображении древовидных кодов, поэтому
      // коды отображаем линейным списком.
      xForm:= TFormCustomList.Create( Application);
      try
        LoadForm(DirIni + 'Forms\Fm_Purposefullgrant.dfm', xForm);

        xCdsList  := TClientDataSet( xForm.FindComponent('CdsData'));
        xDbGrid   := TDBGridEh( xForm.FindComponent('DbGrid'));

        // непонятно что это - взято копипастом из КБК
        xEdtCdsId     := TEdit.Create(xForm);
        xForm.Edit    := xEdtCdsId;
        xForm.SQLText := '';

        xForm.Caption := 'Список выгружаемых кодов целевых назначений...';

        // открытие таблицы только таким образом!
        xForm.Show;
        xForm.Close;

        // загружаем таблицу и открываем форму
        if NOT DoUpdateCDS( xCdsList, xDbGrid) then begin
          WriteInfo( 'Нет кодов целевых назначений для выгрузки.');
          EXIT;
        end;
        if (xForm.ShowModal <> MrOk) then begin
          WriteInfo( 'Выгрузка кодов целевых назначений отменена пользователем.');
          EXIT;
        end;

        // если ни выбрано ни одного кода, но нажато выгрузить, то
        // выгружаются все коды, иначе - только отмеченные галочками.

        if (xDBGrid.Bookmark.Count > 0) then begin
          
          for i:= 0 to xDBGrid.Bookmark.Count-1 do
            if xCdsList.Locate( xDBGrid.FieldKey.FieldName,
                                xDBGrid.Bookmark[i],
                                nil)
              then aListID.Add( xCdsList.FieldByName('ID').AsString);
        end else begin
          
          xCdsList.First;
          while NOT xCdsList.EOF do begin
            aListID.Add( xCdsList.FieldByName('ID').AsString);
            xCdsList.Next;
          end;//while//
        end;
        Result := (aListID.Count > 0);
        finally
          xForm.Free;
      end;
      except
        ExceptionLog( 'Сбой Un_Kbk8.DoExportPurposefulgrandChoice');
    end;

end;

begin
end.
