{~GetEstimateId_3024
  exchange #3024
  При формировании ЭД класса 11 на основании блока ZR по конфигурации
  загрузки Imp_FK_IK значение поля «Бланк расходов»
  формируется следующим образом:
    1. По значениям IK.INN_UBP и IK.KPP_UBP определяется организация в
        системе (Ищется актуальная организация в справочнике «Организации»
        с соответствующими значениями ИНН и КПП в карточке,
        либо с соответствующим значением КПП во вкладке дополнительно)
        и определяется Бланк расходов (далее по тексту БР)
        с типом «Смета» или «ПНО», оператором которого является
        данная организация.
        Если БР определен однозначно, то поле «Бланк расходов» заполняется
        найденным значением и перейти к п.5.
        Если найдено более одного БР, то п.2, иначе п.4.
    2. Из списка БР, определенного по условию п.1, требуется определить БР
        со значением поля «Лицевой счет», равный значению IK.LS_UBP.
        Если БР определен однозначно, то поле «Бланк расходов» заполняется
        найденным значением, перейти к п.5.
        Иначе перейти к п.3.
    3.Фильтровать строки РЧБ по значениям кодов бюджетной классификации,
        входящих в 20й КБК, равный IK.ZRST.KBK_PAY  + «Код цели», равный
        IK.ZRST.ADD_KLASS_PAY(если поле в структурированном файле пустое,
        то принимать как «0») + БР, определенные по п.1.
        Если в РЧБ найдена одна строка или несколько строк, но с одинаковым БР,
        то заполнять БР из найденной строки, перейти к п.5.
        Иначе см. п.4
    4. БР не удалось определить, ЭД класса 11 не формировать.
    5. Поиск БР завершен, переходим к ФТ-3 (поиску РЧБ).

  exchange #3062
  отмена косгу - удалить косгу из поиска}
function GetEstimateId_3024( aBudgetID, aIK_INN_UBP, aIK_KPP_UBP, aIK_LS_UBP: string;
                             aKADMR_CODE, aKCSR_CODE, aKFSR_CODE, aKVR_CODE, aKESR_CODE: string;
                             aPURPOSEFULGRANT_ID: string;
                             aWriteMsg: boolean;
                             var aFoundEstimateID: string;
                             aOrgID: string = ''): boolean;
var
  xXml: Variant;

  {~DoFound_ESTIMATE_ID_
    возвращает найденный ид.БР из запроса поиска БР.}
  function DoFound_ESTIMATE_ID_: string;
  begin

      try
        Result := xXml.childNodes.item[0].getAttribute( 'ID');
        except
          ExceptionProc( 'DoFound_ESTIMATE_ID_');
      end;

  end;


  {~_GetQueryEstimate_
       По значениям IK.INN_UBP, IK.KPP_UBP и IK.LS_UBP формируется запрос
       поиска БР:
       определяется организация в системе (Ищется актуальная организация
       в справочнике «Организации» с соответствующими значениями ИНН и КПП
       в карточке, либо с соответствующим значением КПП во вкладке дополнительно)
        и определяется Бланк расходов (далее по тексту БР)
        с типом «Смета» или «ПНО», оператором которого является
        данная организация.
        если КПП не указано - ищем без КПП.
        если указан счет - БР ищется с учетом счета поля БР "Лицевой счет"
      результат:
        запрос без "select ... "
      обновляются aParams - новые значения добавляются в конец списка variant.}
  function _GetQueryEstimate_(aLS: string; var aParams: variant): string;
  var
    xSubQueryOrgW: string;
    xSubQueryAccJ: string;
    xSubQueryAccW: string;
  begin
  
      try
        AddToVarArray( aParams, aBudgetID);

        // подзапрос проверки счета
        if (LENGTH( aLS) <= 0) then begin
          xSubQueryAccJ := '';
          xSubQueryAccW := '';
        end else begin
          xSubQueryAccJ := ' join orgaccount o on o.id = e.Face_Acc';
          xSubQueryAccW := ' and o.account_number = ?';
          AddToVarArray( aParams, aLS);
        end;

        AddToVarArray( aParams, aBudgetID);

        if (LENGTH( aOrgID) > 0) then begin
          // ищем по ид.орг
          xSubQueryOrgW := ' and ooo.id=?';
          AddToVarArray( aParams, aOrgID);
        end else begin
          // инн+(кпп или среди дополнительных кпп)
          xSubQueryOrgW := ' and ooo.TAXCODE=?';
          AddToVarArray( aParams, aIK_INN_UBP);
          // подзапрос проверки КПП
          if (LENGTH( aIK_KPP_UBP) > 0) then begin
            xSubQueryOrgW :=
                      xSubQueryOrgW
                     +' and (ooo.KPP=? or exists(select * from orgkpp ok'
                     +' where ok.org_id=ooo.id and ok.kpp=?))';
            AddToVarArray( aParams, aIK_KPP_UBP);
            AddToVarArray( aParams, aIK_KPP_UBP);
          end;
        end;

        Result := 'select E.ID From Estimate e'
                 +xSubQueryAccJ
                 +' Where e.EstKind_Id in (1, 7) and e.Actual_Flag = 1'
                 +' and e.Budget_Id = ?'
                 +xSubQueryAccW
                 +' and e.Org_Id in ('
                 +' select ooo.id from ORG ooo '
                  // здесь проверяется галка "актуальная" у организации
                 +' Join Contractor C on C.Org_Id = ooo.Id'
                 +' Join Budget b on b.Org_Id = C.Inspector_Id'
                 +' where b.ID=?'
                 // у орг не должно быть даты закрытия
                 +' and ooo.Close_Date is null'
                 + xSubQueryOrgW
                 +')';
        except
          ExceptionProc( '_GetQueryEstimate_');
      end;
  
  end;

  {~_GetQueryEstimate_Step1_2_
    1. По значениям IK.INN_UBP и IK.KPP_UBP определяется организация в
        системе (Ищется актуальная организация в справочнике «Организации»
        с соответствующими значениями ИНН и КПП в карточке,
        либо с соответствующим значением КПП во вкладке дополнительно)
        и определяется Бланк расходов (далее по тексту БР)
        с типом «Смета» или «ПНО», оператором которого является
        данная организация.
        если КПП не указано - ищем без КПП.
     2. если указан счет - БР ищется с учетом счета поля БР "Лицевой счет"}
  function _GetQueryEstimate_Step1_2_(aLS: string): integer;
  var
    xQueryStr: string;
    xQueryParams: variant;
  begin
  
      try
        xQueryParams := NULL;
        xQueryStr := _GetQueryEstimate_( aLS, xQueryParams);
        xXml := QueryXml( {aQueryStr + }xQueryStr, xQueryParams);
        xXml := xXml.documentElement;
        Result := xXml.childNodes.Length;

        except
          ExceptionProc( '_GetQueryEstimate_Step1_2_');
      end;
  
  end;


  function _GetQueryEstimate_Step3_: integer;
  var
    xQueryStr: string;
    xQueryParams: variant;
  begin
  
      try
        xQueryParams := NULL;

        AddToVarArray( xQueryParams, aBudgetID);
        AddToVarArray( xQueryParams, aKFSR_CODE);
        AddToVarArray( xQueryParams, aKVR_CODE);
        // exchange #3062
        //AddToVarArray( xQueryParams, aKESR_CODE);
        AddToVarArray( xQueryParams, aKCSR_CODE);
        AddToVarArray( xQueryParams, aKADMR_CODE);

        if (LENGTH( aPURPOSEFULGRANT_ID) <= 0)
          then AddToVarArray(
                      xQueryParams,
                      Exch2389_GetPURPOSEFULGRANT_ID_NULL_ByBudget( aBudgetID))
          else AddToVarArray(
                      xQueryParams,
                      aPURPOSEFULGRANT_ID);

        xQueryStr := _GetQueryEstimate_( {aIK_LS_UBP}'', xQueryParams);

        // ищем в РЧБ с учетом кбк+код цели бланки расходов
        xXml := QueryXml( ' Select distinct EE.Estimate_Id Id'
                         +' From Expbudget EE'
                         +' Where EE.Budget_Id = ?'
                         +'  and EE.Kfsr_Code = ?'
                         +'  and EE.Kvr_Code = ?'
                         // exchange #3062
//                         +'  and EE.Kesr_Code = ?'
                         +'  and EE.Kcsr_Code = ?'
                         +'  and EE.Kadmr_Code = ?'
                         +'  and EE.PURPOSEFULGRANT_ID=?'
                         +' and EE.Estimate_Id in (' + xQueryStr + ')',
                          [ xQueryParams]);

        xXml := xXml.documentElement;
        Result := xXml.childNodes.Length;
        except
          ExceptionProc( '_GetQueryEstimate_Step3_');
      end;
  
  end;

  function DoGetOrgInfo_: string;
  begin

      try
        if (LENGTH( aOrgID) > 0)
          then Result := FORMAT( 'ид.организации = %s', [ aOrgID])
          else
            if (LENGTH( aIK_KPP_UBP) > 0)
              then Result := FORMAT( 'ИНН=%s и КПП=%s',
                                     [ aIK_INN_UBP, aIK_KPP_UBP])
              else Result := FORMAT( 'ИНН=%s',
                                     [ aIK_INN_UBP]);
        except
          ExceptionProc( 'DoGetOrgInfo_');
      end;

  end;


begin

    try
      Result := FALSE;
      aFoundEstimateID := '';

      // п.1: поиск бр с орг по ИНН+КПП
      case _GetQueryEstimate_Step1_2_( '') of
        1: begin
              // однозначно найден
              aFoundEstimateID := DoFound_ESTIMATE_ID_;
              Result := TRUE;
              EXIT;
            end;

        0: begin
              if aWriteMsg
                then WriteInfo(
                            FORMAT(
                                'Не удалось определить БР по организации с %s.',
                                [ DoGetOrgInfo_]));
              EXIT;
            end;
      end;

      // п.2: найдено несколько БР. ищем с учетом ИНН+КПП+счет
      if (_GetQueryEstimate_Step1_2_( aIK_LS_UBP) = 1)
        then begin
          // однозначно найден
          aFoundEstimateID := DoFound_ESTIMATE_ID_;
          Result := TRUE;
          EXIT;
        end;

      // п.3: не найдено несколько БР - ищем строки в РЧБ: по КБК, КЦ, списку БР
      case _GetQueryEstimate_Step3_ of
        1: begin
              // однозначно найден
              aFoundEstimateID := DoFound_ESTIMATE_ID_;
              Result := TRUE;
              EXIT;
            end;

        0: begin
              if aWriteMsg
                then WriteInfo(
                          FORMAT(
                              'Не удалось определить БР в РЧБ по организации с %s и счетом=%s.',
                              [ DoGetOrgInfo_,
                                aIK_LS_UBP]));
              EXIT;
            end;
      end;//case//

      // найдено несколько БР
      if aWriteMsg
        then WriteInfo(
                  FORMAT(
                      'Найдено несколько (%s) БР в РЧБ по организации с %s и счетом=%s.',
                      [ INTTOSTR( xXml.childNodes.Length),
                        DoGetOrgInfo_,
                        aIK_LS_UBP]));
      except
        ExceptionProc( 'GetEstimateId_3024');
    end;

end;

function GetEstimateId_3024_ED( aED11, aXmlZR, aXmlIK: Variant): boolean;
var
  xEstimateID: string;
  xZRLine: Variant;
begin

    try
      // берем первую строку ZRST, если есть
      xZRLine := aXmlZR.SelectSingleNode('ZRST');
      if VarIsNULL( xZRLine) then begin
        WriteInfo( 'Не найден раздел ZRST.');
        Result := FALSE;
        EXIT;
      end;

      Result := GetEstimateId_3024(
                      GetNodeAttributeEx( aED11, 'BUDGET_ID'),
                      GetNodeAttributeEx( aXmlIK, 'INN_UBP'),
                      GetNodeAttributeEx( aXmlIK, 'KPP_UBP'),
                      GetNodeAttributeEx( aXmlIK, 'LS_UBP'),
                      GetNodeAttributeEx( xZRLine, 'KADMR_CODE'),
                      GetNodeAttributeEx( xZRLine, 'KCSR_CODE'),
                      GetNodeAttributeEx( xZRLine, 'KFSR_CODE'),
                      GetNodeAttributeEx( xZRLine, 'KVR_CODE'),
                      GetNodeAttributeEx( xZRLine, 'KESR_CODE'),
                      GetNodeAttributeEx( xZRLine, 'PURPOSEFULGRANT_ID'),
                      TRUE,
                      xEstimateID);

      if Result
        then aED11.SetAttribute( 'ESTIMATE_ID', xEstimateID);
      except
        ExceptionProc( 'GetEstimateId_3024_ED');
    end;

end;


{~FillLineED_3024_ByZR
  exchange #3024

  ФТ-2: Поиск строки РЧБ
  Фильтровать строки РЧБ по значениям кодов бюджетной классификации,
  входящих в 20й КБК, равный IK.ZRST.KBK_PAY  + «Код цели»,
  равный IK.ZRST.ADD_KLASS_PAY(если поле в структурированном файле пустое,
  то принимать как «0») + БР, определенный по ФТ-1.

    Если количество строк, отвечающих условиям отбора, в списке РЧБ:
  - одна, то подставлять в строку ЭД ее реквизиты: Бюджетополучатель, КБК,
    Код цели, КВФО, доп.коды;
  - нуль, то заполнять в ЭД коды БК из IK.ZRST.KBK_PAY,
    Код цели из IK.ZRST.ADD_KLASS_PAY, КВФО =1, доп.коды = нули.

      Бюджетополучатель определять в зависимости от наличия признака
      «Межбюджетные трансферты» в найденном бланке:
      - если признак не установлен, то ставить
        Бюджетополучатель=Организация-оператор бланка расходов;
      - если признак установлен, то Бюджетополучатель = Контрагент.

      Контрагента определять так: искать в справочнике организаций организацию
      по ИНН= IK.ZR.INN_RSP, актуальную, если не найдена, то по ИНН+КПП
      (с учетом КПП во вкладке «Дополнительно»), равным соответственно
      IK.ZR.INN_RSP, IK.ZR.KPP_RCP, актуальную.
      Организация должна иметь счет:
        - с типом 5 или 8  с номером, равным ZR.LS_UBP_RCP,
        ИЛИ
        - с типом 2, равным ZR.BS_RCP (если поле ZR.LS_UBP_RCP пустое).

      Если организация найдена однозначно, устанавливать ее в Бюджетополучателя.
      Если организация не найдена или найдена не однозначно,
      то в Бюджетополучателя устанавливать «Не указана».

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

  aEDLine - строка в создаваемом эд (11,195)
  aXmlZRST - исходная строка файла ZRST

  exchange #3062
  отмена косгу - удалить косгу из поиска}
procedure FillLineED_3024_ByZR( aBudgetId: string;
                               aESTIMATE_ID: string;
                                aINN: string;
                                aKPP: string;
                                aLS, aLSType: string;
                               aEDLine, aXmlZRST: Variant);
var
  xXml: Variant;
  xPURPOSEFULGRANT_ID: string;
  xKFSR_CODE: string;
  xKVR_CODE: string;
  xKESR_CODE: string;
  xKCSR_CODE: string;
  xKADMR_CODE: string;


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

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

  end;

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

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

        aEDLine.SetAttribute( 'KDF_CODE',
                                GetNodeAttributeEx( xExpBudget, 'KDF_CODE'));
        aEDLine.SetAttribute( 'KDE_CODE',
                                GetNodeAttributeEx( xExpBudget, 'KDE_CODE'));
        aEDLine.SetAttribute( 'KDR_CODE',
                                GetNodeAttributeEx( xExpBudget, 'KDR_CODE'));
        aEDLine.SetAttribute( 'FSR_ID',
                                GetNodeAttributeEx( xExpBudget, 'FSR_ID'));
        // exchange #3111 теперь косгу вытягивается из рчб как доп код
        aEDLine.setAttribute( 'KESR_CODE',
                                GetNodeAttributeEx( xExpBudget, 'KESR_CODE'));

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

  end;


  {~QueryExpBudget2_
    запрос поиска бюджетополучателей в РЧБ с бюджетополучателем,
    равным контрагенту (параметр aRecipientID).
    возвращает число записей результата запроса.
    это дает проверить, в РЧБ с указанным фильтром, есть один бюджетополучатель
    или несколько ?
    если несколько, значит в РЧБ есть строки, отличающиеся доп.кодами и КВФО. }
  function QueryExpBudget2_( aRecipientID: string): integer;
  begin

      try
        xXml := QueryXml( 'select E.RECIPIENT_ID ID'
                         +' From Expbudget E'
                         +' Where E.Budget_Id = ?'
                         +'  and E.Estimate_Id = ?'
                         +'  and E.Kfsr_Code = ?'
                         +'  and E.Kvr_Code = ?'
                         // exchange #3062
//                         +'  and E.Kesr_Code = ?'
                         +'  and E.Kcsr_Code = ?'
                         +'  and E.Kadmr_Code = ?'
                         +'  and E.PURPOSEFULGRANT_ID=?'
                         +'  and E.RECIPIENT_ID=?',
                          [ aBudgetId,
                            aESTIMATE_ID,
                            xKFSR_CODE,
                            xKVR_CODE,
                            //xKESR_CODE,
                            xKCSR_CODE,
                            xKADMR_CODE,
                            xPURPOSEFULGRANT_ID,
                            aRecipientID]);
        xXml := xXml.documentElement;
        Result := xXml.childNodes.Length;

        except
          ExceptionProc( 'QueryExpBudget2_');
      end;

  end;


  {~QueryReceipient_
    Контрагента определять так: искать в справочнике организаций организацию
    по ИНН= IK.ZR.INN_RSP, актуальную, если не найдена, то по ИНН+КПП
    (с учетом КПП во вкладке «Дополнительно»), равным соответственно
    IK.ZR.INN_RSP, IK.ZR.KPP_RCP, актуальную.
    Организация должна иметь счет:
      - с типом 5 или 8  с номером, равным ZR.LS_UBP_RCP,
    ИЛИ
      - с типом 2, равным ZR.BS_RCP (если поле ZR.LS_UBP_RCP пустое).
    Если организация найдена однозначно, устанавливать ее в Бюджетополучателя.
    Если организация не найдена или найдена не однозначно,
    то в Бюджетополучателя устанавливать «Не указана».

    результат
      контрагент (ид.орг) или =0

    exchange #3063
    убрано условие проверки счета с типом.}
  function QueryReceipient_: string;
  var
    xSQL: string;
  begin

      try
        Result := '0';

        xSQL :=  'select distinct ooo.id from ORG ooo '
                 // здесь проверяется галка "актуальная" у организации
                +' Join Contractor C on C.Org_Id = ooo.Id'
                +' Join Budget Obd on Obd.Org_Id = C.Inspector_Id'
                +' join ORGACCOUNT OA on OA.ORG_ID = ooo.ID'
                +' where Obd.ID=?'
                // у орг не должно быть даты закрытия
                +' and ooo.Close_Date is null'
                +' and OA.CLOSE_DATE is null'
                {
                // орг. должна иметь указанный счет с типом
                +' and (OA.ACCOUNT_NUMBER = ?'
                +'   and OA.ORGACCTYPE_ID in (' + aLSType + '))'
                }
                // инн+(кпп или среди дополнительных кпп)
                +' and ooo.TAXCODE=?';

        if (LENGTH( aKPP) > 0) then begin
          xSQL := xSQL +' and (ooo.KPP=? or exists(select * from orgkpp ok'
                       +' where ok.org_id=ooo.id and ok.kpp=?))';
          xXML := QueryXml( xSQL,
                            [ aBudgetId,
                              //aLS,
                              aINN,
                              aKPP,
                              aKPP]);
        end else begin
          xXML := QueryXml( xSQL,
                            [ aBudgetId,
                              //aLS,
                              aINN]);
        end;

        xXml := xXml.documentElement;
        case xXml.childNodes.Length of
          1: Result := xXml.childNodes.item[0].getAttribute( 'ID');
          0: WriteInfo( 'Контрагент не найден. Бюджетополучатель будет подставлен "Не указан".');
        else WriteInfo( 'Контрагент найден неоднозначно. Бюджетополучатель будет подставлен "Не указан".');
        end;//case//
        except
          ExceptionProc( 'QueryReceipient_');
      end;

  end;

var
  xFound: string;
  xRECIPIENT_ID: string;
  xOrgID: string;
begin

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

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

      // проверяем, сколько есть строк в РЧБ с учетом райденного бланка расходов
      // и кбк+код цели текущей строки ZRST
      xFound := QueryField( ' Select count( * ) N From Expbudget E'
                           +' Where E.Budget_Id = ?'
                           +'  and E.Estimate_Id = ?'
                           +'  and E.Kfsr_Code = ?'
                           +'  and E.Kvr_Code = ?'
                           // exchange #3062
//                           +'  and E.Kesr_Code = ?'
                           +'  and E.Kcsr_Code = ?'
                           +'  and E.Kadmr_Code = ?'
                           +'  and E.PURPOSEFULGRANT_ID=?',
                            [ aBudgetId,
                              aESTIMATE_ID,
                              xKFSR_CODE,
                              xKVR_CODE,
                              //xKESR_CODE,
                              xKCSR_CODE,
                              xKADMR_CODE,
                              xPURPOSEFULGRANT_ID],
                            'N');

      case xFound of
        '0': begin
              // заполнение КВФО, доп кодов по умолчанию
              DoLineFillDefault_;
              // описание бланка расходов в справочнике
              xXml := QueryXml( ' Select INTER_BUDG_TRANS_FLAG MBT, ORG_ID'
                               +' From Estimate Where Id = ?',
                                [ aESTIMATE_ID]);
              // на всякий случай проверяем, найден ли БР в бд
              if (xXml.documentElement.childNodes.Length <= 0) then begin
                WriteInfo( 'Не найден бланк расходов в БД.');
                xRECIPIENT_ID := QueryReceipient_;
              end else begin
                xXml := xXml.documentElement.childNodes.item[0];
              // проверяем признак МБТ

                if (GetNodeAttributeEx( xXml, 'MBT') = '0')
                  then xRECIPIENT_ID := GetNodeAttributeEx( xXml, 'ORG_ID')
                  else xRECIPIENT_ID := QueryReceipient_;
              end;
              // заполняем бюджетополучателя в строке ЭД 11го
              aEDLine.SetAttribute( 'RECIPIENT_ID', xRECIPIENT_ID);
              EXIT;
            end;

        '1': begin
              // п.1 а) если в РЧБ найдена одна строка
              // заполняем доп коды из строки РЧБ
              DoLineFill_ExpBudget_;
              EXIT;
            end;
      end;//case//

      // проверяем, сколько есть строк в РЧБ с учетом райденного бланка расходов
      // и кбк+код цели текущей строки ZRST
      // а бюджетополучатель определяем как контрагент
      xOrgID := QueryReceipient_;

      case QueryExpBudget2_( xOrgID) of
        1: begin
              //aEDLine.SetAttribute( 'RECIPIENT_ID', xOrgID);//xRECIPIENT_ID);
              DoLineFill_ExpBudget_( xOrgID);//xRECIPIENT_ID);
              EXIT;
            end;

        0: if (xOrgID = '0') then begin
              DoLineFillDefault_;       // заполнение строки по умолчанию
              EXIT;
            end else begin
              xOrgID := '0';

              case QueryExpBudget2_( xOrgID) of
                1: begin
                      DoLineFill_ExpBudget_( xOrgID);//xRECIPIENT_ID);
                      EXIT;
                    end;
                0: begin
                      DoLineFillDefault_;       // заполнение строки по умолчанию
                      EXIT;
                    end;
              end;//case//
            end;
      end;//case//

      // найдено несколько строк РЧБ, в которых бюджетополучатель одинаковый,
      // а отличие в доп кодах или КВФО
      // в этом случае значение доп.кодов и КВФО по умолчанию,
      // а бюджетополучатель подставляем из РЧБ
      DoLineFillDefault_;       // заполнение строки по умолчанию
      aEDLine.SetAttribute( 'RECIPIENT_ID', xOrgID);
      except
        ExceptionProc( 'FillLineED_3024_ByZR');
    end;

end;



{~DoFillLineED11_3024
  заполнение строки ЭД 11го класса (aED11Line) исходя из параметров ЭД 11го
  класса (aED11) и исходных данных из разделов IK.ZR (aXmlZR)
  и IK.ZRST (aXmlZRST)}
procedure DoFillLineED11_3024( aED11, aED11Line, aXmlZR, aXmlZRST: Variant);
var
  xAccount: string;
  xAccountType: string;
  xRECIPIENT_ID: string;
  xZR_LS_UBP_RCP: string;
begin

    try
      xZR_LS_UBP_RCP := GetNodeAttributeEx( aXmlZR, 'LS_UBP_RCP');
      { Контрагента определять так: искать в справочнике организаций
        организацию по ИНН= IK.ZR.INN_RSP, актуальную, если не найдена,
        то по ИНН+КПП (с учетом КПП во вкладке «Дополнительно»),
        равным соответственно IK.ZR.INN_RSP, IK.ZR.KPP_RCP, актуальную.
        Организация должна иметь счет:
          - с типом 5 или 8  с номером, равным ZR.LS_UBP_RCP,
        ИЛИ
          - с типом 2, равным ZR.BS_RCP (если поле ZR.LS_UBP_RCP пустое)}
      xAccount := xZR_LS_UBP_RCP;
      if (LENGTH( xAccount) > 0)
        then xAccountType := '5,8'    // для ZR.LS_UBP_RCP
        else begin
          xAccount    := GetNodeAttributeEx( aXmlZR, 'BS_RCP');
          xAccountType:= '2';
        end;

      FillLineED_3024_ByZR( GetNodeAttributeEx( aED11, 'BUDGET_ID'),
                            GetNodeAttributeEx( aED11, 'ESTIMATE_ID'),
                            GetNodeAttributeEx( aXmlZR, 'INN_RCP'),
                            GetNodeAttributeEx( aXmlZR, 'KPP_RCP'),
                            xAccount,
                            xAccountType,
                            aED11Line,
                            aXmlZRST);

      { exchange #3063
        ФТ-3. Требуется осуществлять дополнительную проверку соответствия
        организации и лицевого счета следующим образом:
        После заполнения РЧБ по ФТ-2, если поле «Бюджетополучатель» отлично
          от значения «Не указана» и организация – бюджетополучатель имеет
          роль «БУ» или «АУ», и ZR_LS_UBP_RCP имеет непустое значение,
          то искать в справочнике «Счета организации» карточку счета со
          значением поля «Счет», равным ZR_LS_UBP_RCP, и имеющей ссылку на
          организацию - владельца счета, указанной
          в поле «Бюджетополучатель» РЧБ.
        Если условие НЕ выполняется, то выдавать ошибку следующего текста:
         «Счет < ZR_LS_UBP_RCP > не найден для организации <<Бюджетополучатель>
         документ № <номер> от <дата> обработан не будет».
         Сформированный документ оставлять на статусе «Отложен».
        ИНАЧЕ: продолжать обработку документа по существующему алгоритму. }

      xRECIPIENT_ID := GetNodeAttributeEx( aED11Line, 'RECIPIENT_ID');
      if (xRECIPIENT_ID <> '0')

          then
        if (xZR_LS_UBP_RCP <> '') then
          // проверяем роль ау/бу
          if (QueryField( ' select count( * ) X from orgroles r'
                         +' where r.org_id=? and r.orgrole_id in (18,19)',
                          [ xRECIPIENT_ID],
                          'X') <> '0') then
            // проверяем наличие счета у орг бюджетополучателя
            if (QueryField( ' select count( * ) X from orgaccount a'
                           +' where a.org_id=? and a.account_number=?',
                            [ xRECIPIENT_ID,
                              xZR_LS_UBP_RCP],
                            'X') = '0') then begin
              // сообщение и в эд дописываем спец.тег, по наличию которого
              // эд не будет менять статус
              WriteInfo(
                  FORMAT( 'Счет %s не найден для организации %s. '
                         +'Документ № %s от %s обработан не будет',
                          [ xZR_LS_UBP_RCP,
                            xRECIPIENT_ID,
                            TRIM( GetNodeAttributeEx( aED11, 'DOC_NUMBER')),
                            GetNodeAttributeEx( aED11, 'DOC_DATE')]));
              // любое непустое значение в атрибуте
              aED11.SetAttribute( '__ERROR_3063__', 'ERROR');
            end;
      except
        ExceptionProc( 'DoFillLineED11_3024');
    end;

end;


{~GetEstimateId_2957_Ex
  поиск БР по ид.орг и счету + КБК с кодом цели.
  используется при создании эд 215 по IK.ZR и загрузке IK.UF
  exchange #3062
  убран косгу для эд не ау/бу - убран косгу из поиска в рчб
  exchange #3099
  по требованию АО реализован единый механизм поиска БР - по доработке #3063.
  в результате, эта функция вызывает поиск БР - GetEstimateId_3024}
function GetEstimateId_2957_Ex( aBudgetId: string;
                                aOrgID: string;
                                aLS_Number: string;
                                aLine: Variant): string;
var
  xEstimateID: string;
(*
  xXml: Variant;
  s: string;
  i: integer;
  xEst_Query: string;
  xEst_Value: array of string;
  xPURPOSEFULGRANT_ID: string;
  xKFSR_CODE: string;
  xKVR_CODE: string;
  xKESR_CODE: string;
  xKCSR_CODE: string;
  xKADMR_CODE: string;
  xResultID: string;

  {~DoFound_ESTIMATE_ID_
    если в результате xXml найдена одна строка, то из этой записи
    берется поле ID и сохраняется как результат: ид.бланка расходов.
    результат:
      =true - запись найдена - результат сохранен как ид.бланк расходов;
              и так же, если не найдено ничего - бланк расходов не найден.
      =false - найдено несколько записей.}
  function DoFound_ESTIMATE_ID_: integer;
  begin

      try
        xXml := xXml.documentElement;
        Result := xXml.childNodes.Length;
        if (Result = 1)
          then xResultID := xXml.childNodes.item[0].getAttribute( 'ID');

        except
          ExceptionProc( 'DoFound_ESTIMATE_ID_');
      end;

  end;
  *)
begin
//  xResultID := '';
  try

    try
      if GetEstimateId_3024( aBudgetId,
                              '', '',
                              aLS_Number,
                              GetNodeAttributeEx( aLine, 'KADMR_CODE'),
                              GetNodeAttributeEx( aLine, 'KCSR_CODE'),
                              GetNodeAttributeEx( aLine, 'KFSR_CODE'),
                              GetNodeAttributeEx( aLine, 'KVR_CODE'),
                              GetNodeAttributeEx( aLine, 'KESR_CODE'),
                              GetNodeAttributeEx( aLine, 'PURPOSEFULGRANT_ID'),
                              TRUE,
                              xEstimateID,
                              aOrgID)
        then Result := xEstimateID
        else Result := '';
(*
      WriteLog( 'Поиск бланка расходов в справочнике...');
      xXml := QueryXml( ' Select distinct Id From Estimate'
                       +' Where EstKind_Id in (1, 7) and Actual_Flag = 1'
                       +' and Budget_Id = ? and Org_Id = ?',
                        [ aBudgetId,
                          aOrgID]);
      if (DoFound_ESTIMATE_ID_ <= 1)
        then EXIT;

      if (LENGTH( aLS_Number) > 0) then begin
        WriteLog(
            FORMAT(
                'Поиск бланка расходов в справочнике с учетом счета %s...',
                [ aLS_Number]));
        xXml := QueryXml( ' Select distinct e.Id From Estimate e'
                         +' join orgaccount o on o.id = e.Face_Acc'
                         +' Where e.EstKind_Id in (1, 7) and e.Actual_Flag = 1'
                         +' and e.Budget_Id = ? and e.Org_Id = ?'
                         +' and o.account_number = ?',
                          [ aBudgetId,
                            aOrgID,
                            aLS_Number]);
        if (DoFound_ESTIMATE_ID_ <= 1)
          then EXIT;
      end;

      // берем первую строку ZRST, если есть
//      xZRLine := aXmlZR.SelectSingleNode('ZRST');
//      if VarIsNULL( xZRLine) then EXIT;

      WriteLog( 'Поиск в бланка расходов РЧБ по КБК + коду цели...');

      // перечисляем найденные ид.бланков расходов из справочника через запятую
      s := '';
      for i := 0 to xXml.childNodes.Length - 1 do begin
        if (i > 0) then s := s + ', ';
        s := s + xXml.childNodes.Item[i].getAttribute('ID');
      end;//for//
      // получаем по списку id,id... строку подзапроса ?,? и значений vararray
      xEst_Query := QueryGetParamsFromValue( s, xEst_Value);

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

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

      // ищем в РЧБ с учетом кбк+код цели бланки расходов
      xXml := QueryXml( ' Select distinct E.Estimate_Id Id From Expbudget E'
                       +' Where E.Budget_Id = ? and E.Estimate_Id in ('
                       + xEst_Query
                       +') and E.Kfsr_Code = ?'
                       +'  and E.Kvr_Code = ?'
                       //exchange #3062
//                       +'  and E.Kesr_Code = ?'
                       +'  and E.Kcsr_Code = ?'
                       +'  and E.Kadmr_Code = ?'
                       +'  and E.PURPOSEFULGRANT_ID=?',
                        [ aBudgetId,
                          xEst_Value,
                          xKFSR_CODE,
                          xKVR_CODE,
  //                        xKESR_CODE,
                          xKCSR_CODE,
                          xKADMR_CODE,
                          xPURPOSEFULGRANT_ID]);
      // если в рчб нет строк с таким кбк+кц - БР не нашли
      // если найден один БР, то считаем что БР найден. но бюджетополучатель
      // здесь не заполняем. его заполним в каждой строке.
      // если нашлось несколько бланков расходов,
      DoFound_ESTIMATE_ID_;
      *)
      except
        ExceptionProc( 'GetEstimateId_2957_Ex');
    end;
    finally
//      Result := xResultID;

  end;
end;





begin
end.
