
{~LoadKBK_SqlFilterOption
  добавочная подстрока к запросу выборки КБК из справочников. эта подстрока
  добавляется к строке запроса для всех типов справочников КБК.
  aFormFilter - фильтр из формы. может иметь следующие значения:
      =1: Выгружен - отображаются только строки/коды, у которых Дата последней
          выгрузки больше Даты последнего изменения;
      =2: Не выгружен - отображаются только строки/коды, у которых Дата
          последней выгрузки меньше Даты последнего изменения или не установлена.
  прочие: Пусто - отображаются все строки, независимо от даты последней выгрузки}
function LoadKBK_SqlFilterOption( aFormFilter: integer): string;
begin
  case aFormFilter of
    1: Result :=
           '  and ((line.UNAPPROVED=0) '//   /* только утвержденные строки */
          +'    and ((line.unload_date is not null) and'// /* дата выгрузки указана (был выгружен) */
          +'        (line.change_date<=line.unload_date)))';//  /* и небыло изменений после выгрузки */
    2:  Result :=
           ' and ((line.UNAPPROVED=0) '//   /* только утвержденные строки */
          +'   and ((line.unload_date is null) or'// /* дата выгрузки не указана (не был выгружен) */
          +'        (line.change_date>line.unload_date)))';//  /* было изменение после выгрузки */
   else Result :=
           ' and (line.UNAPPROVED=0)';//   /* только утвержденные строки */
  end;//case//
end;


{~ExecuteQuery_LoadKBK
  выполняет запрос загрузки справочника КБК по SQL запросу  aSQL.
  в этой процедуре расширяется запрос по условию опции конфигурации:
   "Вариант выгрузки КБК".
  в зависимости от варианта значения этой опции селектируются КБК по дате
  окончания действия КБК или по дате последней выгрузки КБК.
  в результате возвращается список загруженных КБК в виде XML. }
function ExecuteQuery_LoadKBK( aSQL: string; aSQL_Params: Variant): Variant;
var
  xSQL: string;
begin

    try
//    Result := CreateOleObject('Microsoft.XmlDom');
      if(vCfgOutListKbk) then
        xSQL := aSQL
      else
      begin
        case vCfgSelectorKBK of
          cnCfgSelectorKBK_Changes: begin
                  { выгружаются только те строки КБК и только та история
                    изменения кода, которая не выгружалась относительно
                    последней выгрузки КБК }
                  xSQL := aSQL
                    +'    and ((line.unload_date is null) or'// /* дата выгрузки не указана (не был выгружен) */
                    +'        (line.change_date > line.unload_date))';//  /* и были изменения после выгрузки */
                  
    //              Result.LoadXml( Query.Run( xSql));
                end;

          cnCfgSelectorKBK_Last: begin
                  { выгружаются данные по КБК со строкой истории кода,
                    в которой дата окончания действия больше или равна рабочей
                    даты (дата может быть устанавлена при присоединении
                    AzkExchange к серверу приложений, либо не установлена.}
                  xSQL := aSQL
                    +' and ((line.end_date is null) or (line.end_date >= ?))';
                  
                  AddToVarArray( aSQL_Params, Work_Date);
    //              Result.LoadXml( Query.Run( xSql));
                end;

          else begin
                  xSQL := aSQL;
                  
    //              Result.LoadXml( Query.Run( xSQL));
                end;
        end;//case//
      end;
      Result := QueryXML( xSQL, aSQL_Params);
      except
        ExceptionProc( 'ExecuteQuery_LoadKBK');
    end;

end;


{~LoadKBKFromIncBudget
  загрузка кодов доходов из справочника:
  справочники\бюджет\классификаторы бюджета\коды доходов бюджета}
function LoadKBKFromIncBudget( aBudgetID: String; aCfgSelector: integer; var xResult: Variant): Variant;
var
  i, xNodesCount: Integer;
  sql: String;
  xNode: Variant;
  xSQL_Params: Variant;
begin

    try
      sql :=
       'select'
      +'  kbk.ID KBK_ID,'
      +'  line.ID LINE_ID,'
      +'  line.VERSION LINE_VERSION,'
      +'  20 TYPE_KBK,'
      +'  line.CAPTION CAPTION,'
      +'  line.DESCRIPTION DESCRIPTION,'
      +'  line.begin_date BEGIN_DATE,'
      +'  line.end_date END_DATE,'
      +'  line.change_date CHANGE_DATE,'
      +'  line.unload_date UNLOAD_DATE,'
      +'  kbk.kadmd_code CODE_ADM,'
      +'  kbk.kd_code CODE_K,'
      // exchange #3081
      +IfThen( vCfg_3049, '','  kbk.kesd_code CODE_ES,')//  /* суммировать в CODE */
      +'  0 LIMITED_FLAG'          // exchange #2396
      +' from'
      +'  kbk_inc_budget_lines line'
      +' join'
      +'  KBK_INC_BUDGET kbk on line.master_id=kbk.id'
      +' where'
      +'  line.Budget_Id = ?' //+aBudgetID
      //+'  /* игнорируем коды, имеющие в своем составе "не указан" в какой нибудь части КБК */
      +'  and (kbk.kadmd_code<>?'
      +'  or kbk.kd_code<>?'
      // exchange #3081 - доработка выгрузки кбк
      // по #3049 настройка работает и она остается и дальше, поэтому здесь,
      // если косгу не нужен, то удаляем код из проверки и выгрузки
      +IfThen( vCfg_3049, '', ' or kbk.kesd_code<>?')
      +' ) '
      + LoadKBK_SqlFilterOption( aCfgSelector);
      // добавляем к запросу параметр бюджета.
      xSQL_Params := NULL;
      AddToVarArray( xSQL_Params, aBudgetID);
      AddToVarArray( xSQL_Params, vKBK0_KADM);
      AddToVarArray( xSQL_Params, vKBK0_KD);
      // exchange #3081 - доработка совместно с #3049
      if NOT vCfg_3049
        then AddToVarArray( xSQL_Params, vKBK0_KES);
  //    Query.AddStr( aBudgetID);
      Result := ExecuteQuery_LoadKBK( Sql, xSQL_Params);

      xNodesCount := Result.documentElement.ChildNodes.Length;
      StatusBarSimpleText( 'Загрузка кодов доходов...');
      SetProgress( 0, xNodesCount);
      ShowProgress( 0);
      for i := 0 to xNodesCount - 1 do begin
        xNode := Result.documentElement.ChildNodes.item[i];
        ShowProgress( i + 1);
        // формируем атрибут 20-ти значный код КБК из трех составляющих.
        // каждое из полей расширяется до указанной длины строки, с добавлением
        // нулей слева к подстрокам.
        // exchange #3049
        // коды подстраиваем по длине масок
        // exchange #3081 - совмещено с #3049
        xNode.SetAttribute(
                  'CODE',
                  GetRuleKBKLine_D(
                        xNode.getAttribute('CODE_ADM'),
                        xNode.getAttribute('CODE_K'  ),
                        GetNodeAttributeEx( xNode, 'CODE_ES' ),
                        aBudgetID,
                        NOT( vCfg_3049)));
                  {
                  FormatKbk( 'KADM', xNode.getAttribute('CODE_ADM'), aBudgetID)
                 +FormatKbk( 'KD', xNode.getAttribute('CODE_K'  ), aBudgetID)
                 +FormatKbk( 'KES', xNode.getAttribute('CODE_ES' ), aBudgetID));
                 }
        // добавляем строку к результату
        xResult.documentElement.appendChild( xNode.cloneNode( TRUE));// result.createElement('Elements'));
      end;//for//

      except
        ExceptionProc( 'LoadKBKFromIncBudget');
    end;

end;

{~LoadKBKFromSrcBudget
  загрузка кодов источников из справочника:
  справочники\бюджет\классификаторы бюджета\коды источников финансирования бюджета}
function LoadKBKFromSrcBudget( aBudgetID: String; aCfgSelector: integer; var xResult: Variant): Variant;
var
  i, xNodesCount: Integer;
  sql: String;
  xNode: Variant;
  xSQL_Params: Variant;
begin

    try
      sql :=
       'select'
      +'  kbk.ID KBK_ID,'
      +'  line.ID LINE_ID,'
      +'  line.VERSION LINE_VERSION,'
      +'  31 TYPE_KBK,'
      +'  line.CAPTION CAPTION,'
      +'  line.DESCRIPTION DESCRIPTION,'
      +'  line.begin_date BEGIN_DATE,'
      +'  line.end_date END_DATE,'
      +'  line.change_date CHANGE_DATE,'
      +'  line.unload_date UNLOAD_DATE,'
      +'  kbk.kadmi_code CODE_ADM,'
      +'  kbk.ki_code CODE_K,'
      // exchange #3081
      +IfThen( vCfg_3049, '','  kbk.kesi_code CODE_ES,')//  /* суммировать в CODE */
      +'  0 LIMITED_FLAG'          // exchange #2396
      +' from'
      +'  kbk_src_budget_lines line'
      +' join'
      +'  KBK_SRC_BUDGET kbk on line.master_id=kbk.id'
      +' where'
      +'  line.Budget_Id = ?' //+ aBudgetID
      //+'  /* игнорируем коды, имеющие в своем составе "не указан" в какой нибудь части КБК */
      +'  and (kbk.kadmi_code<>?'
      +'  or kbk.ki_code<>?'
      // exchange #3081 - доработка выгрузки кбк
      // по #3049 настройка работает и она остается и дальше, поэтому здесь,
      // если косгу не нужен, то удаляем код из проверки и выгрузки
      +IfThen( vCfg_3049, '', ' or kbk.kesi_code<>?')
      +' ) '
      + LoadKBK_SqlFilterOption( aCfgSelector);
      // добавляем к запросу параметр бюджета.
      xSQL_Params := NULL;
      AddToVarArray( xSQL_Params, aBudgetID);
      AddToVarArray( xSQL_Params, vKBK0_KADM);
      AddToVarArray( xSQL_Params, vKBK0_KI);
      // exchange #3081 - доработка совместно с #3049
      if NOT vCfg_3049
        then AddToVarArray( xSQL_Params, vKBK0_KES);
  //    Query.AddStr( aBudgetID);
      Result := ExecuteQuery_LoadKBK( Sql, xSQL_Params);

      xNodesCount := Result.documentElement.ChildNodes.Length;
      StatusBarSimpleText( 'Загрузка кодов источников финансирования...');
      SetProgress( 0, xNodesCount);
      ShowProgress( 0);
      for i := 0 to xNodesCount - 1 do begin
        xNode := Result.documentElement.ChildNodes.item[i];
        ShowProgress( i + 1);
        // формируем атрибут 20-ти значный код КБК из трех составляющих.
        // каждое из полей расширяется до указанной длины строки, с добавлением
        // нулей слева к подстрокам.
        // exchange #3049
        // коды подстраиваем по длине масок
        // exchange #3081 - совмещено с #3049
        xNode.setAttribute(
                  'CODE',
                  GetRuleKBKLine_I(
                        xNode.getAttribute('CODE_ADM'),
                        xNode.getAttribute('CODE_K'  ),
                        GetNodeAttributeEx( xNode, 'CODE_ES' ),
                        aBudgetID,
                        NOT( vCfg_3049)));
                  {
                  FormatKbk( 'KADM', xNode.getAttribute('CODE_ADM'), aBudgetID)
                 +FormatKbk( 'KI', xNode.getAttribute('CODE_K'  ), aBudgetID)
                 +FormatKbk( 'KES', xNode.getAttribute('CODE_ES' ), aBudgetID);
                 }
        // добавляем строку к результату
        xResult.documentElement.appendChild( xNode.cloneNode( TRUE));// result.createElement('Elements'));
      end;//for//

      except
        ExceptionProc( 'LoadKBKFromSrcBudget');
    end;

end;

{~LoadKBKFromExpBudget
  загрузка кодов доходов из справочника:
  справочники\бюджет\классификаторы бюджета\коды расходов бюджета}
function LoadKBKFromExpBudget( aBudgetID: String; aCfgSelector: integer; var xResult: Variant): Variant;
var
  i, xNodesCount: Integer;
  sql, plan: String;
  Kadm, Kfsr, Kcsr, Kvr, Kes: String;
  xNode: Variant;
  xSQL_Params: Variant;
begin

    try
      sql :=
       'select'
      +'  kbk.ID KBK_ID,'
      +'  line.ID LINE_ID,'
      +'  10 TYPE_KBK,'
      +'  line.VERSION LINE_VERSION,'
      +'  line.CAPTION CAPTION,'
      +'  line.DESCRIPTION DESCRIPTION,'
      +'  line.begin_date BEGIN_DATE,'
      +'  line.end_date END_DATE,'
      +'  line.change_date CHANGE_DATE,'
      +'  line.unload_date UNLOAD_DATE,'
      +'  kbk.kadmr_code CODE_ADM,'
      +'  kbk.kfsr_code CODE_KFSR,'
      +'  kbk.kcsr_code CODE_KCSR,'
      +'  kbk.kvr_code CODE_KVR,'
      // exchange #3081
      +IfThen( vCfg_3049, '','  kbk.kesк_code CODE_ES,')//  /* суммировать в CODE */
      +'  kbk.LIMITED_FLAG LIMITED_FLAG'          // exchange #2396
      +' from'
      +'  kbk_exp_budget_lines line'
      +' join'
      +'  kbk_exp_budget kbk on line.master_id=kbk.id'
      +' where'
      +'  line.budget_id = ?' //+ aBudgetID
    //  /* игнорируем коды, имеющие в своем составе "не указан" в какой нибудь части КБК */
      +'  and (kbk.kadmr_code<>?'
      +'  or kbk.kfsr_code<>?'
      +'  or kbk.kcsr_code<>?'
      +'  or kbk.kvr_code<>?'
      // exchange #3081 - доработка выгрузки кбк
      // по #3049 настройка работает и она остается и дальше, поэтому здесь,
      // если косгу не нужен, то удаляем код из проверки и выгрузки
      +IfThen( vCfg_3049, '', '  or kbk.kesr_code<>?')
      +' ) '
      + LoadKBK_SqlFilterOption( aCfgSelector);
      // добавляем к запросу параметр бюджета.
      xSQL_Params := NULL;
      AddToVarArray( xSQL_Params, aBudgetID);
      AddToVarArray( xSQL_Params, vKBK0_KADM);
      AddToVarArray( xSQL_Params, vKBK0_KFSR);
      AddToVarArray( xSQL_Params, vKBK0_KCSR);
      AddToVarArray( xSQL_Params, vKBK0_KVR);
      // exchange #3081 - доработка совместно с #3049
      if NOT vCfg_3049
        then AddToVarArray( xSQL_Params, vKBK0_KES);
  //    Query.AddStr( aBudgetID);
      Result := ExecuteQuery_LoadKBK( Sql, xSQL_Params);

      xNodesCount := Result.documentElement.ChildNodes.Length;
      StatusBarSimpleText( 'Загрузка кодов доходов...');
      SetProgress( 0, xNodesCount);
      ShowProgress( 0);
      for i := 0 to xNodesCount - 1 do begin
        xNode := Result.documentElement.ChildNodes.item[i];
        ShowProgress( i + 1);
        // формируем атрибут 20-ти значный код КБК из трех составляющих.
        // каждое из полей расширяется до указанной длины строки, с добавлением
        // нулей слева к подстрокам.
        // exchange #3049
        // коды подстраиваем по длине масок
        // exchange #3081 - совмещено с #3049
        xNode.setAttribute(
                  'CODE',
                  GetRuleKBKLine_R(
                        xNode.getAttribute('CODE_ADM' ),
                        xNode.getAttribute('CODE_KFSR'),
                        xNode.getAttribute('CODE_KCSR'),
                        xNode.getAttribute('CODE_KVR' ),
                        GetNodeAttributeEx( xNode, 'CODE_ES' ),
                        aBudgetID,
                        NOT( vCfg_3049)));
                        {
                  FormatKbk( 'KADM', xNode.getAttribute('CODE_ADM' ), aBudgetID)
                 +FormatKbk( 'KFSR', xNode.getAttribute('CODE_KFSR'), aBudgetID)
                 +FormatKbk( 'KCSR', xNode.getAttribute('CODE_KCSR'), aBudgetID)
                 +FormatKbk( 'KVR', xNode.getAttribute('CODE_KVR' ), aBudgetID)
                 +FormatKbk( 'KES', xNode.getAttribute('CODE_ESR' ), aBudgetID);
                 }
        // добавляем строку к результату
        xResult.documentElement.appendChild( xNode.cloneNode( TRUE));// result.createElement('Elements'));
      end;//for//

      except
        ExceptionProc( 'LoadKBKFromExpBudget');
    end;

end;

{~LoadKBKFromDictionaries
  загрузка КБК из трех справочников для бюджета aBudgetID:
   справочники\бюджет\классификаторы бюджета\
     1) коды доходов бюджета;
     2) коды расходов бюджета;
     3) коды источников финансирования бюджета.}
function LoadKBKFromDictionaries( aBudgetID: string;
                                  aCfgSelector: integer = 0;
                                  aLoadInc: boolean = TRUE;
                                  aLoadSrc: boolean = TRUE;
                                  aLoadExp: boolean = TRUE): variant;
begin

    try
      Result := CreateOleObject('Microsoft.XmlDom');
      Result.appendChild( Result.createElement('Elements'));
      if aLoadInc then LoadKBKFromIncBudget( aBudgetID, aCfgSelector, Result);
      if aLoadSrc then LoadKBKFromSrcBudget( aBudgetID, aCfgSelector, Result);
      if aLoadExp then LoadKBKFromExpBudget( aBudgetID, aCfgSelector, Result);
      ShowProgress( 0);
      except
        ExceptionProc( 'LoadKBKFromDictionaries');
    end;

end;

{~SelectionsKBKListCreate
 создание промежуточных списков хранения КБК }
procedure SelectionsKBKListCreate( var aSLInc,aSLSrc,aSLExp: TStringList);
begin
  try
    
    aSLInc := TStringList.Create;
    aSLSrc := TStringList.Create;
    aSLExp := TStringList.Create;
    aSLInc.Delimiter := ',';
    aSLSrc.Delimiter := ',';
    aSLExp.Delimiter := ',';
    
    except
      ExceptionLog( 'Сбой скрипта: "Un_Kbk1.SelectionsKBKListCreate".');
  end;
end;

{~SelectionsKBKListFree
 разрушение промежуточных списков хранения КБК }
procedure SelectionsKBKListFree( var aSLInc,aSLSrc,aSLExp: TStringList);
begin
  try
    
    aSLInc.Free;
    aSLSrc.Free;
    aSLExp.Free;
    aSLInc := NIL;
    aSLSrc := NIL;
    aSLExp := NIL;
    
    except
      ExceptionLog( 'Сбой скрипта: "Un_Kbk1.SelectionsKBKListFree".');
  end;
end;

{~GetSelectionsKBKFromList
 формируются списки выбранных КБК в таблице aDBGrid (aCdsList)
  в соответствующих объектах:
    aSLInc-доходы
    aSLSrc-источники
    aSLExp-расходы}
function GetSelectionsKBKFromList(
                    var aCdsList: TClientDataSet;
                    var aDBGrid: TDBGridEh;
                    var aSLExp,aSLSrc,aSLInc: TStringList;
                    aSelected: boolean): variant;
                    
  procedure DoSelected( xRoot: variant);
  var
    xID: string;
    xNode: variant;
  begin
    xID := aCdsList.FieldByName('LINE_ID').AsString;
    case aCdsList.FieldByName('TYPE_KBK').AsString of
      '20': aSLInc.Add( xID);
      '10': aSLExp.Add( xID);
      '31',
      '32': aSLSrc.Add( xID);
    end;//case//

    xNode := xRoot.appendChild( Result.createElement('ROW'));
    xNode.setAttribute( 'CODE'       , aCdsList.FieldByName('CODE').AsString);
    xNode.setAttribute( 'CAPTION'    , aCdsList.FieldByName('CAPTION').AsString);
    xNode.setAttribute( 'DESCRIPTION', aCdsList.FieldByName('DESCRIPTION').AsString);
    xNode.setAttribute( 'BEGIN_DATE' , DateTimeToXml(
                                        aCdsList.FieldByName('BEGIN_DATE').AsDateTime));
    xNode.setAttribute( 'CHANGE_DATE', DateTimeToXml(
                                        aCdsList.FieldByName('CHANGE_DATE').AsDateTime));
{    xNode.setAttribute( 'UNLOAD_DATE', DateTimeToXml(
                                        aCdsList.FieldByName('UNLOAD_DATE').AsDateTime));}
    xNode.setAttribute( 'END_DATE'   , IfThen(
                                        aCdsList.FieldByName('END_DATE').AsString <> '',
                                        DateTimeToXml(aCdsList.FieldByName('END_DATE').AsDateTime),
                                        ''));
    xNode.setAttribute( 'TYPE_KBK'   , aCdsList.FieldByName('TYPE_KBK').AsString);
    xNode.setAttribute( 'LIMIT'      , aCdsList.FieldByName('LIMIT').AsString);
    // exchange #2396
    xNode.setAttribute( 'LIMITED_FLAG', aCdsList.FieldByName('LIMITED_FLAG').AsString);
  end;
                    
var
  i: integer;
  xRoot: variant;
  xEmpty: boolean;
begin

    try
      if aSelected then begin
        
        xEmpty := (aDBGrid.Bookmark.Count <= 0);
      end else begin
        
        aCdsList.First;
        xEmpty := aCdsList.EOF;
      end;
      if xEmpty then begin
        
        Result := NULL;
        EXIT;
      end;

      
      Result := CreateOleObject('Microsoft.XmlDom');
      Result.appendChild(Result.createElement('EXCHQUERY'));
      xRoot := Result.documentElement;

      
      if aSelected then begin
//        aCdsList.DisableControls;
//        aDBGrid.Enabled := False;
        
        for i:= 0 to aDBGrid.Bookmark.Count-1 do begin

          aCdsList.First;
          while NOT aCdsList.EOF do begin
            if (aCdsList.FieldByName( aDBGrid.FieldKey.FieldName).AsString
                = aDBGrid.Bookmark[i])
              then begin
                DoSelected( xRoot);
                BREAK;
              end;
            aCdsList.Next;
          end;//

            {
          if aCdsList.Locate( aDBGrid.FieldKey.FieldName,
                              aDBGrid.Bookmark[i],
                              nil)
            then DoSelected( xRoot);
            }
        end;//for//
//        aDBGrid.Enabled := True;
//        aCdsList.EnableControls;
      end else begin
        
        while NOT aCdsList.EOF do begin
          DoSelected( xRoot);
          aCdsList.Next;
        end;//while//
      end;
      
      except
        ExceptionProc( 'GetSelectionsKBKFromList');
    end;

end;


{~InsertKBKListToCds
  добавляет данные отобранные КБК в Dataset
  Kbk20 - флаг 20-тизначного КБК (кодов доходов бюджета, кодов расходов и
  кодов источников финансирования дефицитов бюджетов)
  вынесено отдельно из Exp_FK_KBK поскольку добавлены дополнительные поля.
  во время обновления таблицы контрол блокируется.}
procedure InsertKBKListToCds( var aCdsList: TClientDataSet;
                              var aDBGrid: TDBGridEh;
                              aXml: Variant;
                              aBudgetID: string;
                              aFiltered: boolean = TRUE);
begin
  try
    
    try
      aCdsList.DisableControls;
      aDBGrid.Enabled := False;
      aCdsList.First;
      InsertKBKListToCdsEx( aCdsList, aDBGrid, aXml, aBudgetID, aFiltered);
      finally
//        aCdsList.First;
        aDBGrid.Enabled := True;
        aCdsList.EnableControls;
    end;
    
    except
      ExceptionLog( 'Сбой скрипта: "Un_Kbk1.InsertKBKListToCds".');
  end;
end;

{~InsertKBKListToCdsEx
  обновление списка КБК в Dataset.
  при добавлению в таблицу выполняется фильтрация КБК.}
procedure InsertKBKListToCdsEx( var aCdsList: TClientDataSet;
                                var aDBGrid: TDBGridEh;
                                aXml: Variant;
                                aBudgetID: string;
                                aFiltered: boolean = TRUE);
var
  xLengthKADM: integer;
  xLengthKES: integer;
  xLengthKES2: integer;

  { фильтр строк КБК.
    нужно отфильтровать только те КБК, которые удовлетворяют фильтру.
    результат: =true - запись удовлетворят фильтру.}
  function DoFilterKBK( var aNode: Variant; aCode: string): boolean;
  var
    n: integer;
  begin
    Result := FALSE;
    { проверка типа КБКЖ входит ли подстрока типа КБК в строку фильтра.
      для точного соответствия добавляется к концу подстроки "," а в фильтре
      стоит, например, "20,". это нужно чтобы проверить тип КБК на множество:
      "31,32,".}
    if (vFilterKBK_TypeKBK <> '') then
      if ( POS( aNode.getAttribute('TYPE_KBK') + ',', vFilterKBK_TypeKBK) <= 0)
        then EXIT;
    { коды проверяются аналогично, но тут добавляются два добавочных символа
      по обоим сторонам строк. это дает надежную проверку значения в начале
      строки фильтра.
      например, если значение 3, а фильтр 30,... то будет ложное срабатывание.
      exchange #2895
      поправлена ошибка проверки фильтра КАДМ/КОСКУ в КБК.
      здесь нужно учитывать что в строке фильтра коды обрамлены в кавычки.
      а символы запятых при этом учитывать не обязательно.
      exchange #3049
      коды подстраиваем по длине масок.
      если параметр конфига (vCfg_3049) выставлен нет, значит косгу выгружается
      (по старому) и косгу участвует в фильтрации.
      если настройка =да, значит косгу не выгружается, код в списке отображается
      без косгу, и фильтровать по нему безсмысленно. }
    if (vFilterKBK_KadmCode <> '') then
      if (POS( #39 + Copy( aCode, 1, xLengthKADM) + #39,
               vFilterKBK_KadmCode) <= 0)
        then EXIT;
    if (vFilterKBK_KesCode <> '') then
      if NOT vCfg_3049 then
        if (POS( #39 + Copy( aCode, LENGTH( aCode) - xLengthKES2, xLengthKES) + #39,
                 vFilterKBK_KesCode) <= 0)
          then EXIT;
    Result := TRUE;
  end;

var
  i: Integer;
//  s1,s2,s3: string;
  xNode: variant;
  xCode: string;
  xListKBK: TStringList;
begin

    try
      xLengthKADM := LENGTH( FormatKbk( 'KADM', '0', aBudgetID));
      xLengthKES  := LENGTH( FormatKbk( 'KES', '0', aBudgetID));
      xLengthKES2 := xLengthKES - 1;



      aCdsList.First;
      while not aCdsList.Eof do begin
        aCdsList.Delete;
        aCdsList.First;
      end;

      if VarIsNull( aXml) then EXIT;

      xListKBK:= TStringList.Create;
      try
        for i := 0 to aXml.documentElement.childNodes.Length - 1 do  begin
          xNode := aXml.documentElement.childNodes.Item[i];
          xCode := xNode.getAttribute('CODE');

        // exchange #3049
        // если настройка конфига =да, удаляем последние 3 цифры КБК (КОСГУ)
        // exchange #3081
        // здесь больше ничего зарезать не нужно, поскольку теперь код из бд
        // уже заполняется либо с/без косгу по настройке.
        {
        if vCfg_3049 then begin
          if (LENGTH( xCode) >= xLengthKES)
            then DELETE( xCode, LENGTH( xCode) - xLengthKES2, xLengthKES);
        end;
        }
        
          // т.к. сейчас КОСГУ нет в справочнике 20-х КБК, то код по отсеву дублей - не нужен
          {
          // exchange #3092
          // нужно отфильтровать дубли кодов КБК (отсев дублей кодов с одинаковыми косгу)
          if (xListKBK.IndexOf( xCode) <> -1) then begin
            WriteLog(
                FORMAT( 'Найдено дублирование кода для выгрузки %s - не выгружается.',
                        [ xCode]));
            CONTINUE;
          end; }
          
          xListKBK.Add( xCode);

        { если нужно фильтровать, а строка не удовлетворяет фильтру,
          пропускаем эту строку без добавления в таблицу.
          если делать как в delphi (по событию OnFilterRecord) или через
          свойство aCdsList.Filter, будет мелькание или задвоение данных.
          это видимо проблемы с общением DataSet с FastScript.}
        if aFiltered then
          if NOT DoFilterKBK( xNode, xCode)
            then CONTINUE;
      
        aCdsList.Append;
        aCdsList.FieldByName('CDSID'       ).AsString := INTTOSTR( i + 1);
        aCdsList.FieldByName('LINE_ID'     ).AsString := xNode.getAttribute('LINE_ID');
        aCdsList.FieldByName('CODE'        ).AsString := xCode;
        aCdsList.FieldByName('CAPTION'     ).AsString :=
            IfThen( xNode.getAttribute('CAPTION') <> '',
                    xNode.getAttribute('CAPTION'),
                    '');
        aCdsList.FieldByName('DESCRIPTION' ).AsString :=
            IfThen( xNode.getAttribute('DESCRIPTION') <> '',
                    xNode.getAttribute('DESCRIPTION'),
                    '');
        aCdsList.FieldByName('BEGIN_DATE').AsDateTime :=
            XmlToDateTime( xNode.getAttribute('BEGIN_DATE'));
        aCdsList.FieldByName('CHANGE_DATE').AsDateTime :=
            XmlToDateTime( xNode.getAttribute('CHANGE_DATE'));
        if (xNode.getAttribute('UNLOAD_DATE') <> '')
          then aCdsList.FieldByName('UNLOAD_DATE').AsDateTime :=
                  XmlToDateTime( xNode.getAttribute('UNLOAD_DATE'));
        if (xNode.getAttribute('END_DATE') <> '')
          then aCdsList.FieldByName('END_DATE').AsDateTime :=
                  XmlToDateTime( xNode.getAttribute('END_DATE'));
        if not VarIsNull( xNode.getAttribute('TYPE_KBK'))
          then aCdsList.FieldByName('TYPE_KBK').AsString :=
                  xNode.getAttribute('TYPE_KBK');
        if not VarIsNull( xNode.getAttribute('LIMIT'))
          then aCdsList.FieldByName('LIMIT').AsString :=
                  xNode.getAttribute('LIMIT');
        // exchange #3049 - коды подстраиваем по длине масок
        aCdsList.FieldByName('KADMCODE').AsString := Copy( xCode, 1, xLengthKADM);//Copy( xCode, 1, 3);
        aCdsList.FieldByName('KESCODE' ).AsString := Copy( xCode, LENGTH( xCode) - xLengthKES2, xLengthKES);//Copy( xCode, 18, 3);
        // exchange #2396
        // если поля нет - заполняем значение нулем
        aCdsList.FieldByName('LIMITED_FLAG'     ).AsString:=
            IfThen( VarToStr( xNode.getAttribute('LIMITED_FLAG')) <> '',
                    xNode.getAttribute('LIMITED_FLAG'),
                    '0');

        
        aCdsList.Post;
      end;//for//
        finally
          xListKBK.Free;
      end;
      except
        ExceptionProc( 'InsertKBKListToCdsEx');
    end;

end;


{~FixedExportedKBKList
  фиксируем список идентификаторов экспортируемых КБК.
  здесь отсылается задание на сервер.
  если на сервере фиксация КБК не выполняется, то удаляется выгруженный файл КБК}
procedure FixedExportedKBKList( aFileOut: string;
                                var aSLExp,aSLSrc,aSLInc: TStringList);
var xRaiseMsg: string;
begin
  try
    
    try


        begin
          ExecProc( 'KBKEXPORTFROMEXCHANGE',
                    [ 'action', 'export',
                      'id_inc', aSLInc.CommaText,
                      'id_src', aSLSrc.CommaText,
                      'id_exp', aSLExp.CommaText]);
          
        end;
      
      except
        begin
          xRaiseMsg := LastException.Message;
          DeleteFile( aFileOut);
          RaiseLog( FORMAT(       'Сбой фиксации выгруженных КБК.'
                           +#13#10'Файл с выгруженными КБК "%s" удален.',
                           [ aFileOut]),
                    xRaiseMsg);
        end;
    end;
    
    except
      ExceptionLog( 'Сбой скрипта: "Un_Kbk1.FixedExportedKBKList".');
  end;
end;


begin
end.
