// QueryWork.pfs - Общие запросы к АЦК, используемые во многих форматах
// Все предварительные проверки на непустоту параметров делать до вызова функций
const
  sqlOrgId = 'Select * From Org Where Id = ?';
  sqlOrgName = 'Select * From Org Where Name = ?';
  sqlFoNameByBudg = ' Select O.* From Org O' +
    ' Left Join Budget B on B.Org_Id = O.Id' +
    ' Where B.Id = ?';
  sqlBudgId = 'Select * From Budget Where Id = ?';
  sqlTerritoryOKATO = 'Select COALESCE(okato, '+#39#39+') TEROKATO from Territory Where Id = ?';
  sqlOrgByBudget = ' Select O.* From Budget B' +
    ' Left Join Org O on (B.Org_Id = O.Id)' +
    ' Where B.Id = ?';


  sqlBudgOrgOtv = 'Select Bl.BudgType Budg_Type, Bl.Caption BudgLevel_Caption,' +
    ' B.Caption Budg_Caption, O.Description, O.OKPO' +
    ' From Budget B' +
    ' Left Join Org O on O.Id = B.Org_id' +
    ' Left Join BudgLevel Bl on B.BudgLevel_Id = Bl.Id' +
    ' Where B.Id = ?';

  sqlOrgRefActual = 'Select O.Id, O.Caption, O.Description, O.Kadm_Code, O.Version,' +
    ' O.Close_Date, O.Open_Date, ParentOrg.Name, ParentOrg.Caption Root_Caption,' +
    ' ParentOrg.Description Root_Description, O.Taxcode, O.Kpp, O.Name, O.Caption_Empty' +
    ' From Org O' +
    ' Left Join OrgRoles Ors on O.Id = Ors.Org_Id' +
    ' Left Join OrgRole Orl on Orl.id = Ors.orgrole_id' +
    ' Join Contractor C on C.Org_Id = O.Id' +
    ' Left Join Org ParentOrg on ParentOrg.Id = O.Manager_Id' +
    ' Where O.id <> 0';
  sqlOrgNotClose = 'Select * From Org Where Close_Date is null';
  sqlOrgNotCloseRecCount = 'Select count(*) N From Org Where Close_Date is null';
  sqlAccAllRek = 'Select A.Id Id, A.Account_Number Account_Number, Ofk.Description Ofk_Description,' +
    ' Ufk.Description Ufk_Description, UfkAcc.Account_Number Ufk_Account_Number,' +
    ' UfkAcc.Id Ufk_Acc_Id, Ufkb.Bic Bic, Ufkb.Description B_Name, Ufkb.CorAccount CorAccount,' +
    ' SpecAcc.Account_Number SpecUfk_Account_Number, SpecAcc.Id SpecUfk_Acc_Id, ' +
    ' Specb.Bic SpecBic, Specb.Description Specb_Name, Specb.CorAccount SpecCorAccount' +
    ' From OrgAccount A' +
    ' Left Join Org Ofk on Ofk.Id = A.Keeper_Id' +
    ' Left Join Org Ufk on Ufk.Id = A.Executer_Id' +
    ' Left Join OrgAccount UfkAcc on UfkAcc.Id = A.ExecuterAcc_Id' +
    ' Left Join Bank Ufkb on Ufkb.Id = UfkAcc.Bank_Id' +
    ' Left Join OrgAccount SpecAcc on SpecAcc.Id = A.SpecialFundsAcc_Id' +
    ' Left Join Bank Specb on Specb.Id = SpecAcc.Bank_Id' +
    ' Where A.Close_Date is null';
  sqlTofkAcc = 'Select O.Name, O.Description, O.Caption From Org O' +
      ' Left Join OrgAccount Oa on Oa.Keeper_Id = O.Id' +
      ' Where Oa.Id = ?';
  sqlUfkAcc = 'Select O.Name, O.Description, O.Caption From Org O' +
      ' Left Join OrgAccount Oa on Oa.Executer_Id = O.Id' +
      ' Where Oa.Id = ?';
  sqlOrgByOrgAccountId = 'Select O.* From Org O' +
    ' Join OrgAccount Oa on Oa.Org_Id = O.Id' +
    ' Where Oa.Id = ?';
  sqlAccById = ' Select * From OrgAccount Where Id = ?';
  sqlIso = ' Select Asset.Name, Asset.Description, Iso_Code' +
    ' From Budget, Accbook, Asset, Currency' +
    ' Where Accbook.Id = Coalesce(Budget.FinBook_Id, Budget.RepBook_Id)' +
    ' And Asset.Id = Accbook.Currency_Id' +
    ' And Currency.Asset_Id = Accbook.Currency_Id' +
    ' And Budget.Id = ?';
  sqlTerritory = ' Select * From Territory Where Id = ?';
  sqlOrgAllRek = 'Select A.Id Acc_Id, A.Account_Number, O.Id Org_Id, O.TaxCode,' +
    ' O.Kpp, O.Description Org_Description, O.Caption Org_Caption,' +
    ' O.Name Org_Code, O.Kadm_Code, Ofk.Description Ofk_Description, Ufk.Description Ufk_Description,' +
    ' UfkAcc.Account_Number Ufk_Account_Number, UfkAcc.Id Ufk_Acc_Id, Ufkb.Bic Bic,' +
    ' Ufkb.Description B_Name, Ufkb.CorAccount CorAccount, ufkf.Name Ufk_Filial_Name,' +
    ' SpecAcc.Account_Number SpecUfk_Account_Number, SpecAcc.Id SpecUfk_Acc_Id, Specb.Bic SpecBic,' +
    ' Specb.Description Specb_Name, Specb.CorAccount SpecCorAccount,' +
    ' SpecUfkf.Name SpecUfk_Filial_Name, Obd.Budget_id' +
    ' From OrgAccount A' +
    ' Left Join Org O on O.Id = A.Org_Id' +
    ' Left Join OrgBudgetDet Obd on Obd.Org_Id = O.Id' +
    ' Left Join Budget B on B.Id = Obd.Budget_id' +
    ' Left Join Org Ofk on Ofk.Id = A.Keeper_Id' +
    ' Left Join Org Ufk on Ufk.Id = A.Executer_Id' +
    ' Left Join OrgAccount UfkAcc on UfkAcc.Id = A.ExecuterAcc_Id' +
    ' Left Join Bank Ufkb on Ufkb.Id = UfkAcc.Bank_Id' +
    ' Left Join Filial Ufkf on Ufkf.Id = UfkAcc.Filial_Id' +
    ' Left Join OrgAccount SpecAcc on SpecAcc.Id = A.SpecialFundsAcc_Id' +
    ' Left Join Bank Specb on Specb.Id = SpecAcc.Bank_Id' +
    ' Left Join Filial SpecUfkf on SpecUfkf.Id = SpecAcc.Filial_Id' +
    ' Where A.Close_Date is null and O.Close_Date is null';
  sqlBudget = 'Select * From Budget';
  sqlParentClass148 = ' Select D.Instance_Link, D.Id, D.Doc_Number, D.Doc_Date,' +
    ' D.Amount, D.Description, D.DocumentClass_Id, D.DispStatus_Id, D.Parent_Id' +
    ' From Document D' +
    ' Join BudgOrder B on D.Id = B.Document_Id' +
    ' Where B.Register_Id = ?' +
    ' Union Select D.Instance_Link, D.Id, D.Doc_Number, D.Doc_Date, D.Amount,' +
    ' D.Description, D.DocumentClass_Id, D.DispStatus_Id, D.Parent_Id' +
    ' From Document D' +
    ' Join PayOrder P on D.Id = P.Document_Id' +
    ' Where P.Register_Id = ?';
  sqlAccByOrgId = 'Select * From OrgAccount where Org_Id = ? and Close_Date is null';
  sqlBudgetByFinYearFOKodFo = 'Select Obd.Budget_Id' +
    ' From OrgBudgetDet Obd' +
    ' Left Join Budget B on B.Id = Obd.Budget_Id' +
    ' Where Obd.Org_Id = ? and Obd.Code_Fk = ? and B.FinYear = ?';
  sqlBudgetByReceiver = ' Select distinct R.Budget_Id' +
    ' From Org O Join Receiver R on R.Org_Id = O.Id' +
    ' Left Join Budget B on R.Budget_Id = B.Id' +
    ' Where O.Name = ? and B.FinYear = ?';
  sqlAccTofkByBuh = 'Select O.Name, O.Description, O.Caption, O.Id, Oa.Account_Number' +
    ' From OrgAccount Oa' +
    ' Left Join Budget B on B.MainAcc_Id = Oa.Id' +
    ' Left Join Org O on O.Id = Oa.Keeper_Id' +
    ' Where B.Id = ? and Oa.OrgAcctype_Id = 9';
  sqlAccByBudg = 'Select O.*, Oa.Account_Number, Oa.Id Acc_Id, Oa.Orgacctype_Id,' +
    ' Oa.Description Account_Description, Bk.Description Bank_Name, Bk.Bic, Bk.CorAccount' +
    ' From Budget B' +
    ' Left Join OrgAccount Oa on B.Common_Acc_Id = Oa.Id' +
    ' Left Join Org O on Oa.Org_Id = O.Id' +
    ' Left Join Bank Bk on Bk.Id = Oa.Bank_Id' +
    ' Where B.Id = ?';
  sqlBank = ' Select * From Bank Where Bic = ?';
  sqlBankById = ' Select * From Bank Where Id = ?';

function GetBudgLevel(BudgetId: String; Node: Variant = Null): String;
var
  sql: String;
begin
  if (not VarIsNull(Node)) and (not VarIsNull(Node.getAttribute('PAY_ACC_ID')))
    and (Node.getAttribute('PAY_ACC_ID') <> '')
      and (GetAccType(Node.getAttribute('PAY_ACC_ID')) = '2') then
    Result := '6'
  else begin
    sql := ' Select Bl.* From Budget B' +
      ' Join BudgLevel Bl on (B.BudgLevel_Id = Bl.Id)' +
      ' Where B.Id = ?';
    Result := QueryField(sql, [BudgetId], 'BUDGTYPE');
  end;
end;

{~GetOrgByBudget
  Получает данные организации по бюджету, результат в Xml.
  exchange #2983
  доработан запрос чтобы возвращялся ид.орг. в поле ID}
function GetOrgByBudget( aBudget: String): Variant;
var
  sql: String;
begin

    try
      Result := QueryXml(  ' Select coalesce(Ob.Code_Fk, o.name) as Name, O.Description, '
                          + 'O.ID as ID'
                          +' From OrgBudgetDet Ob'
                          +' Left Join Budget B on (B.Org_Id = Ob.Org_Id'
                          +' and B.Id = Ob.Budget_Id)'
                          +' Left Join Org O on O.Id = B.Org_Id'
                          +' Where B.Id = ?',
                           [ aBudget]);
      except
        ExceptionProc( 'GetOrgByBudget');
    end;

end;

//Получает полно наименование организации владельца бланка расходов по Estimate_Id
function GetOrgByEstimate_Id(Estimate_Id: String): String;
var
  sql: String;
begin
  sql := 'Select O.*' +
    ' From Estimate E' +
    ' Join Org O on O.Id = E.Org_Id' +
    ' Where E.Id = ?';
  Result := QueryField(sql, [Estimate_Id], 'DESCRIPTION');
end;

//получает данные бюджета по Id организации через инспектора. Результат в xml.
function GetBudgetFromInspectorOrgId(Org_Id, FinYear: String): Variant;
var
  sql: String;
begin
  sql := 'Select B.Id' +
    ' From Budget B' +
    ' Join Org Fo on Fo.Id = B.Org_Id' +
    ' Join Contractor Inspector on Inspector.Inspector_Id = Fo.Id' +
    ' Join Org O on O.Id = Inspector.Org_Id' +
    ' Where O.Id = ? and B.Finyear = ?';
  Result := QueryXml(sql, [Org_Id, FinYear]);
end;

function GetTofkByBuh(BudgetId: String): Variant;
begin
  // Тофк из Бухгалтерия-Настройка счетов-Счета ФО-Основной бюджетный счет 02
  Result := QueryXml(sqlAccTofkByBuh, [BudgetId]);
  // Если счет не указан, либо не 02, то вытаскиваем из справочника бюджетов.
  if Result.documentElement.childNodes.Length = 0 then
    Result := QueryXml(sqlAccByBudg, [BudgetId]);
end;

//Функция возвращает Id бюджета в случае однозначного определения бюджета
//по коду организации,указанного на закладке Дополнительно организации.
//если  FinYear=пусто, поиск производится по справочнику получателей доходов и
//коду организации,указанного на закладке "Общая информация" организации
function GetBudgetByOrgCode(OrgCode: String; FinYear: String = ''): String;
var
  sql: String;
  Xml: Variant;
begin
  Result := '';
  if FinYear <> '' then
  begin
    sql := ' Select distinct Obd.Budget_Id' +
      ' From OrgBudgetDet Obd' +
      ' Left Join Budget B on Obd.Budget_Id = B.Id' +
      ' Where Obd.Code_Fk = ? and B.FinYear = ?';
    Xml := QueryXml(sql, [OrgCode, FinYear]);
    if Xml.documentElement.childNodes.Length = 1 then
      Result := Xml.documentElement.childNodes.Item[0].getAttribute('BUDGET_ID');
  end
  else begin
    sql := ' Select distinct R.Budget_Id' +
      ' From Org O Join Receiver R on R.Org_Id = O.Id' +
      ' Join OrgBudgetDet Obd on Obd.Org_Id = O.Id and Obd.Budget_Id = R.Budget_Id' +
      ' Where Obd.Code_Fk = ?';
    Xml := QueryXml(sql, [OrgCode]);
    if Xml.documentElement.childNodes.Length = 1 then
      Result := Xml.documentElement.childNodes.Item[0].getAttribute('BUDGET_ID')
    else begin
      sql := ' Select distinct R.Budget_Id' +
        ' From Org O Join Receiver R on R.Org_Id = O.Id' +
        ' Where O.Name = ?';
      Xml := QueryXml(sql, [OrgCode]);
      if Xml.documentElement.childNodes.Length = 1 then
        Result := Xml.documentElement.childNodes.Item[0].getAttribute('BUDGET_ID')
    end;
  end;
end;

//Возвращает данные бюджета с типом "исполнение" по фин.году
//и номеру единого счета бюджета. Результат в Xml.
function GetBudgetByFinYearAccNum(FinYear, AccNum: String): Variant;
var
  sql: String;
begin
  //ищем  бюджет по единому счету бюджета
  sql := 'Select B.Id, B.Caption, B.Org_Id, B.Common_Acc_Id, B.Sf_Account_Id' +
    ' From OrgAccount A' +
    ' Left Join Budget B on B.Common_Acc_Id = A.Id' +
    ' Where B.FinYear = ? and B.BudgKind = 2 and A.Account_Number = ?' +
    ' and A.Close_Date is null';
  Result := QueryXml(sql, [FinYear, AccNum]);
  if Result.documentElement.childNodes.Length = 0 then
  begin
    //ищем счет по счету для учета спец. средств.
    sql := 'Select B.Id, B.Caption, B.Org_Id, B.Common_Acc_Id, B.Sf_Account_Id' +
      ' From OrgAccount A' +
      ' Left Join Budget B on B.Sf_Account_Id = A.Id' +
      ' Where B.FinYear = ? and B.BudgKind = 2 and A.Account_Number = ?' +
      ' and A.Close_Date is null';
    Result := QueryXml(sql, [FinYear, AccNum]);
    if Result.documentElement.childNodes.Length > 0 then
      Result.documentElement.childNodes.Item[0].setAttribute('F_SS', 'True');
  end
  else
    //записываем признак спец средств в только в первый нод. Ошибок не будет,
    //т.к. при неоднозначном определении бюджета, загрузка файла прекратится.
    Result.documentElement.childNodes.Item[0].setAttribute('F_SS', 'False');
end;

//Возвращает данные бюджета с типом "исполнение" по фин.году
//и id единого счета бюджета. Результат в Xml.
function GetBudgetByFinYearAccId(FinYear, AccId: String): Variant;
var
  sql: String;
begin
  //ищем  бюджет по единому счету бюджета
  sql := 'Select B.Id, B.Caption, B.Org_Id, B.Common_Acc_Id, B.Sf_Account_Id' +
    ' From Budget B Where B.FinYear = ? and B.BudgKind = 2 and B.Common_Acc_Id = ?';
  Result := QueryXml(sql, [FinYear, AccId]);
end;

//Определяет загружался ли документ данного класса с указанным ключем
//True - загружался.
function IsLoaded(BudgetId, DocumentClass_Id, Fk: String;
  Doc: Variant = null; SF: Boolean = False): Boolean;
var
  Xml: Variant;
  sql: String;
begin

    try
      //нужно ли проверять на повторную загрузку. Здесь нет проверки на тип
      //загружаемого файла т.к. атрибут IGNORE_GUID будет только в нужных нам типах.
      if (not VarIsNull(Doc)) and (not VarIsNull(Doc.getAttribute('IGNORE_GUID'))) and
        (StrToBool(Doc.getAttribute('IGNORE_GUID'))) and
        (DocumentClass_Id in ['5', '24']) then
      begin
        //делаем вид, что проверили и документ в базе не нашли.
        Result := False;
        Exit;
      end;

      // exchange #2641
      // при загрузке файлов VB,VT для 24го класса проверка осуществляется по
      // GUID+л/с_получателя=VB.LS (DOC.REC_ACCOUNT)
      if (DocumentClass_Id = '24') then
        if ( NOT VarIsNull( Doc)) then
          if (VarToStr( Doc.getAttribute( 'F_ORIGINAL_TYPE')) in ['VB','VT'])
            then begin

              Xml := QueryXml( ' Select * From Payorder'
                              +' Where Budget_Id = ? and DocumentClass_Id = ?'
                              +' and Foreign_Key = ? and REC_ACCOUNT=?'
                              +' and DispStatus_Id > -1',
                               [ BudgetId,
                                 DocumentClass_Id,
                                 Fk,
                                 Doc.getAttribute( 'REC_ACCOUNT')],
                               False);
              Result := Xml.documentElement.childNodes.Length > 0;
              EXIT;
            end;

      case DocumentClass_Id of
        '178', '214':
          sql := 'Select * From Explainreq' +
            ' Where Budget_Id = ? and DocumentClass_Id = ? and Ufk_GUID = ?' +
            ' and DispStatus_Id > -1';
        '5', '24':
          sql := 'Select * From Payorder' +
            ' Where Budget_Id = ? and DocumentClass_Id = ? and Foreign_Key = ?' +
            ' and DispStatus_Id > -1';
        '39', '80':
          begin
            sql := 'Select * From SrcOrder' +
              ' Where Budget_Id = ? and DocumentClass_Id = ? and Foreign_Key = ?' +
              ' and DispStatus_Id > -1';
            if SF then
              sql := StringReplace(sql, 'and Foreign_Key =', 'and Guid_Fk =');
          end;
        '35', '43':
          begin
            sql := 'Select * From IncOrder' +
              ' Where Budget_Id = ? and DocumentClass_Id = ? and Foreign_Key = ?' +
              ' and DispStatus_Id > -1';
            if SF then
              sql := StringReplace(sql, 'and Foreign_Key =', 'and Guid_Fk =');
          end;
        '11':
          sql := 'Select * From BudgOrder' +
            ' Where Budget_Id = ? and DocumentClass_Id = ? and Guid_Fk = ?' +
            ' and DispStatus_Id > -1';
        '75':
          sql := 'Select * From PayReQuest' +
            ' Where Budget_Id = ? and DocumentClass_Id = ? and Guid_Fk = ?' +
            ' and DispStatus_Id > -1';
        '118':
          sql := 'Select * From SrcReQuest' +
            ' Where Budget_Id = ? and DocumentClass_Id = ? and Guid_Fk = ?' +
            ' and DispStatus_Id > -1';
        '195':
          sql := 'Select * From AuBuCashRequest' +
            ' Where Budget_Id = ? and DocumentClass_Id = ? and Foreign_Key = ?' +
            ' and DispStatus_Id > -1';
        else
          Raise('IsLoaded: Класс ' + DocumentClass_Id + ' не поддерживается.');
      end;
      //здесь кэш не юзаем - бесполезно
      Xml := QueryXml(sql, [BudgetId, DocumentClass_Id, Fk], False);
      Result := Xml.documentElement.childNodes.Length > 0;
      except
        ExceptionLog( 'Сбой QueryWork.IsLoaded');
    end;

end;


{~GetOrgByTaxKppEx
  Получает данные незакрытой организации из справочника по ИНН и КПП.
  Результат в виде Xml или NULL.
  exchange #2391 - вместо доменов используется ППО бюджета.

  2013/02/28 Выдыш С.М.
  доработка оптимизации скорости. поэтому эту функцию нельзя применять,
  если не ожидается однозначный результат.
  при неоднозначном результате функция может вернуть NULL. }
function GetOrgByTaxKppEx( Taxcode, Kpp: String;
                            DocClass: String = '';
                            RecPay: String = '';
                            UseOrgRef: Boolean = False;
                            Doc: Variant = null): Variant;
var
  sql, sqlusedomen: String;
  TmpRes: Variant;
  NoKpp: Boolean;
  n: integer;
begin

    try
      // 2013/02/28 Выдыш С.М.
      // с целью оптимизации скорости, первоначально выполняется запрос количества
      // записей, и в случае однозначного результата - выполняем полноценный запрос.
      // это связано с тем, что в пользовательских БД слишком много организаций
      // может вернуться только по условию ИНН или КПП
      sql := sqlOrgNotCloseRecCount + ' and Taxcode = ?';
      NoKpp := Trim(StringReplace(Kpp, '0', '')) = '';
      if NoKpp
        then n := STRTOINT( QueryField( sql, [Taxcode], 'N'))
        else n := STRTOINT( QueryField( sql + ' and Kpp = ?', [Taxcode, Kpp], 'N'));
      if (n = 1)
        then begin
          sql := sqlOrgNotClose + ' and Taxcode = ?';
//          NoKpp := Trim(StringReplace(Kpp, '0', '')) = '';
          if NoKpp
            then Result := QueryXml(sql, [Taxcode])
            else Result := QueryXml(sql + ' and Kpp = ?', [Taxcode, Kpp]);
        end else begin
          // при неожнозначном результате формируем XML с пустым результатом
          Result := CreateOleObject('Microsoft.XmlDom');
          Result.LoadXml( '<EXCHQUERY completed="true"/>');
        end;
      //нашли более одной организации, присоединяем роли
      //Exchange #1916 (распространяется только на 5 и 24 классы)
      if Result.documentElement.childNodes.Length > 1 then
      begin
        if (DocClass = '24') and (RecPay = 'REC') then
        begin
          sql := 'Select distinct O.* From Org O' +
            ' Join OrgRoles Ors on O.Id = Ors.Org_Id' +
            ' Where O.Taxcode = ? and Ors.OrgRole_Id not in (3,6,7,8,17)';
          if NoKpp then
            Result := QueryXml(sql, [Taxcode])
          else begin
            sql := sql + ' and O.Kpp = ?';
            Result := QueryXml(sql, [Taxcode, Kpp]);
          end;
        end;
        if ((DocClass = '5') and (RecPay = 'REC')) or ((DocClass = '24') and (RecPay = 'PAY')) then
        begin
          sql := 'Select distinct O.* From Org O' +
            ' Join OrgRoles Ors on O.Id = Ors.Org_Id' +
            ' Where Taxcode = ? and Ors.OrgRole_Id in (3,6,7,8,17)';
          if NoKpp then
            Result := QueryXml(sql, [Taxcode])
          else begin
            sql := sql + ' and O.Kpp = ?';
            Result := QueryXml(sql, [Taxcode, Kpp]);
          end;
        end;
      end;
      //Exchange#2059
      //не нашли однозначно организацию по основному КПП, продолжаем поиск по дополнительному КПП
      if (AzkCompareVersion('2.25.0.14') > 0) and (not NoKpp)
        and (Result.documentElement.childNodes.Length <> 1) then
      begin
        sql := ' Select distinct O.* From Org O' +
          ' Join OrgKpp Ok on O.Id = Ok.Org_Id' +
          ' Where O.Close_Date is null and O.Taxcode = ? and Ok.Kpp = ?';
        Result := QueryXml(sql, [Taxcode, Kpp]);
        //нашли более одной организации, присоединяем роли
        //Exchange #1916 (распространяется только на 5 и 24 классы)
        if Result.documentElement.childNodes.Length > 1 then
        begin
          if (DocClass = '24') and (RecPay = 'REC') then
          begin
            sql := 'Select distinct O.* From Org O' +
              ' Join OrgKpp Ok on O.Id = Ok.Org_Id' +
              ' Join OrgRoles Ors on O.Id = Ors.Org_Id' +
              ' Where O.Taxcode = ? and Ors.OrgRole_Id not in (3,6,7,8,17) and Ok.Kpp = ?';
              Result := QueryXml(sql, [Taxcode, Kpp]);
          end;
          if ((DocClass = '5') and (RecPay = 'REC')) or ((DocClass = '24') and (RecPay = 'PAY')) then
          begin
            sql := 'Select distinct O.* From Org O' +
              ' Join OrgKpp Ok on O.Id = Ok.Org_Id' +
              ' Join OrgRoles Ors on O.Id = Ors.Org_Id' +
              ' Where Taxcode = ? and Ors.OrgRole_Id in (3,6,7,8,17) and Ok.Kpp = ?';
            Result := QueryXml(sql, [Taxcode, Kpp]);
          end;
        end;
      end;
      //Exchange #2252 - добавляем в поиск домены
      // правило заменено на exchange #2391.
      if (AzkCompareVersion('2.26.43.16') >= 0)
        and (Result.documentElement.childNodes.Length <> 1)
        and (not VarIsNull(Doc)) and ((not VarIsNull(Doc.getAttribute('BUDGET_ID')))
          or (not VarIsNull(Doc.getAttribute('F_BUDGET_ID')))) then
      begin
        if VarIsNull(Doc.getAttribute('BUDGET_ID')) then
          Doc.setAttribute('BUDGET_ID', Doc.getAttribute('F_BUDGET_ID'));
        sqlusedomen := 'Select O.*' +
          ' From Org O'
          { exchange #2391
           изменение в алгоритме поиска организации при загрузке файлов
           VB, VP, IV, IP, IK, VT, SB, SР, осуществлять поиск не по домену
           организации, а по значению поля Публично правовое образование.
           При неоднозначном определении организации по ИНН + КПП + дата
           закрытия пусто, осуществлять поиск по ИНН + КПП + дата закрытия=пусто
           с учетом значения поля «Публично правовое образование» в карточке
           Организации (Справочники – Организации-Организации) которое должно
           совпадать со значением поля «Публично правовое образование» в карточке
           «Бюджета» (Справочники- Бюджеты-Бюджеты).}
          +' left join budget b on b.ppo_id=o.ppo_id'
        //+' Join Budget B on B.Domen_Id = O.Domen_Id' { оставлено на память }

          +' Where O.Taxcode = ? and O.Close_Date is null and B.Id = ?';
        if NoKpp then
          TmpRes := QueryXml(sqlusedomen, [Taxcode, Doc.getAttribute('BUDGET_ID')])
        else
          TmpRes := QueryXml(sqlusedomen + ' and O.Kpp = ?',
            [Taxcode, Doc.getAttribute('BUDGET_ID'), Kpp]);
        if TmpRes.documentElement.childNodes.Length = 1 then
          Result := TmpRes;
      end;
      if (UseOrgRef) and (Result.documentElement.childNodes.Length > 1) then
      begin
        TmpRes := GetOrgFromRef(sql, Taxcode, Kpp, NoKpp, Doc);
        if not VarIsNull(TmpRes) then
          Result := TmpRes;
      end;
      except
        ExceptionLog( 'Сбой QueryWork.GetOrgByTaxKppEx');
    end;

end;


{~GetOrgByTaxKpp
//Получает данные незакрытой организации из справочника по ИНН и КПП.
//Результат в Xml.
  exchange #2391 - вместо доменов используется ППО бюджета.}
function GetOrgByTaxKpp(Taxcode, Kpp: String; DocClass: String = '';
  RecPay: String = ''; UseOrgRef: Boolean = False; Doc: Variant = null): Variant;
var
  sql, sqlusedomen: String;
  TmpRes: Variant;
  NoKpp: Boolean;
begin

    try
      sql := sqlOrgNotClose + ' and Taxcode = ?';
      NoKpp := Trim(StringReplace(Kpp, '0', '')) = '';
      if NoKpp then
        Result := QueryXml(sql, [Taxcode])
      else
      begin
        sql := sql + ' and Kpp = ?';
        Result := QueryXml(sql, [Taxcode, Kpp]);
      end;
      //нашли более одной организации, присоединяем роли
      //Exchange #1916 (распространяется только на 5 и 24 классы)
      if Result.documentElement.childNodes.Length > 1 then
      begin
        if (DocClass = '24') and (RecPay = 'REC') then
        begin
          sql := 'Select distinct O.* From Org O' +
            ' Join OrgRoles Ors on O.Id = Ors.Org_Id' +
            ' Where O.Taxcode = ? and Ors.OrgRole_Id not in (3,6,7,8,17)';
          if NoKpp then
            Result := QueryXml(sql, [Taxcode])
          else begin
            sql := sql + ' and O.Kpp = ?';
            Result := QueryXml(sql, [Taxcode, Kpp]);
          end;
        end;
        if ((DocClass = '5') and (RecPay = 'REC')) or ((DocClass = '24') and (RecPay = 'PAY')) then
        begin
          sql := 'Select distinct O.* From Org O' +
            ' Join OrgRoles Ors on O.Id = Ors.Org_Id' +
            ' Where Taxcode = ? and Ors.OrgRole_Id in (3,6,7,8,17)';
          if NoKpp then
            Result := QueryXml(sql, [Taxcode])
          else begin
            sql := sql + ' and O.Kpp = ?';
            Result := QueryXml(sql, [Taxcode, Kpp]);
          end;
        end;
      end;
      //Exchange#2059
      //не нашли однозначно организацию по основному КПП, продолжаем поиск по дополнительному КПП
      if (AzkCompareVersion('2.25.0.14') > 0) and (not NoKpp)
        and (Result.documentElement.childNodes.Length <> 1) then
      begin
        sql := ' Select distinct O.* From Org O' +
          ' Join OrgKpp Ok on O.Id = Ok.Org_Id' +
          ' Where O.Close_Date is null and O.Taxcode = ? and Ok.Kpp = ?';
        Result := QueryXml(sql, [Taxcode, Kpp]);
        //нашли более одной организации, присоединяем роли
        //Exchange #1916 (распространяется только на 5 и 24 классы)
        if Result.documentElement.childNodes.Length > 1 then
        begin
          if (DocClass = '24') and (RecPay = 'REC') then
          begin
            sql := 'Select distinct O.* From Org O' +
              ' Join OrgKpp Ok on O.Id = Ok.Org_Id' +
              ' Join OrgRoles Ors on O.Id = Ors.Org_Id' +
              ' Where O.Taxcode = ? and Ors.OrgRole_Id not in (3,6,7,8,17) and Ok.Kpp = ?';
              Result := QueryXml(sql, [Taxcode, Kpp]);
          end;
          if ((DocClass = '5') and (RecPay = 'REC')) or ((DocClass = '24') and (RecPay = 'PAY')) then
          begin
            sql := 'Select distinct O.* From Org O' +
              ' Join OrgKpp Ok on O.Id = Ok.Org_Id' +
              ' Join OrgRoles Ors on O.Id = Ors.Org_Id' +
              ' Where Taxcode = ? and Ors.OrgRole_Id in (3,6,7,8,17) and Ok.Kpp = ?';
            Result := QueryXml(sql, [Taxcode, Kpp]);
          end;
        end;
      end;
      //Exchange #2252 - добавляем в поиск домены
      // правило заменено на exchange #2391.
      if (AzkCompareVersion('2.26.43.16') >= 0)
        and (Result.documentElement.childNodes.Length <> 1)
        and (not VarIsNull(Doc)) and ((not VarIsNull(Doc.getAttribute('BUDGET_ID')))
          or (not VarIsNull(Doc.getAttribute('F_BUDGET_ID')))) then
      begin
        if VarIsNull(Doc.getAttribute('BUDGET_ID')) then
          Doc.setAttribute('BUDGET_ID', Doc.getAttribute('F_BUDGET_ID'));
        sqlusedomen := 'Select O.*' +
          ' From Org O'
          { exchange #2391
           изменение в алгоритме поиска организации при загрузке файлов
           VB, VP, IV, IP, IK, VT, SB, SР, осуществлять поиск не по домену
           организации, а по значению поля Публично правовое образование.
           При неоднозначном определении организации по ИНН + КПП + дата
           закрытия пусто, осуществлять поиск по ИНН + КПП + дата закрытия=пусто
           с учетом значения поля «Публично правовое образование» в карточке
           Организации (Справочники – Организации-Организации) которое должно
           совпадать со значением поля «Публично правовое образование» в карточке
           «Бюджета» (Справочники- Бюджеты-Бюджеты).}
          +' left join budget b on b.ppo_id=o.ppo_id'
        //+' Join Budget B on B.Domen_Id = O.Domen_Id' { оставлено на память }

          +' Where O.Taxcode = ? and O.Close_Date is null and B.Id = ?';
        if NoKpp then
          TmpRes := QueryXml(sqlusedomen, [Taxcode, Doc.getAttribute('BUDGET_ID')])
        else
          TmpRes := QueryXml(sqlusedomen + ' and O.Kpp = ?',
            [Taxcode, Doc.getAttribute('BUDGET_ID'), Kpp]);
        if TmpRes.documentElement.childNodes.Length = 1 then
          Result := TmpRes;
      end;
      if (UseOrgRef) and (Result.documentElement.childNodes.Length > 1) then
      begin
        TmpRes := GetOrgFromRef(sql, Taxcode, Kpp, NoKpp, Doc);
        if not VarIsNull(TmpRes) then
          Result := TmpRes;
      end;

      except
        ExceptionProc( 'GetOrgByTaxKpp');
    end;

end;

// получает данные организации с выбором из справочника
function GetOrgFromRef(sql, Taxcode, Kpp: String; NoKpp: Boolean;
  Doc: Variant = null): Variant;
var
  FmOrg: TFormCustomList;
  DBGrid: TDBGridEh;
  EdtOrgId: TEdit;
  actSelect, actClose, actRefresh: TAction;
  procedure OnBeforRefresh;
  begin
    Query.AddStr(Taxcode);
    if not NoKpp then
      Query.AddStr(KPP);
    FmOrg.SQLText := sql;
  end;
  procedure OnMessage;
  begin
    actSelect.Enabled := DBGrid.Bookmark.Count = 1;
  end;
begin
  Result := null;
  if not FileExists(DirIni + 'Forms\FmOrg.dfm') then
    Exit;
  FmOrg := TFormCustomList.Create(Application);
  try
    FmOrg.LoadDfm(DirIni + 'Forms\FmOrg.dfm');
    DBGrid := TDBGridEh(FmOrg.FindComponent('DBGrid'));
    actSelect := TAction(FmOrg.FindComponent('actSelect'));
    actClose := TAction(FmOrg.FindComponent('actClose'));
    actRefresh := TAction(FmOrg.FindComponent('actRefresh'));
    TApplicationEvents(FmOrg.FindComponent('appEvents')).OnMessage := @OnMessage;
    EdtOrgId := TEdit.Create(nil);
    FmOrg.Edit := EdtOrgId;
    actClose.Enabled := True;
    actRefresh.Enabled := True;
    FmOrg.OnBeforRefresh := @OnBeforRefresh;
    FmOrg.SQLText := sql;
    if (not VarIsNull(Doc)) and (not VarIsNull(Doc.getAttribute('DOC_NUMBER')))
      and (not VarIsNull(Doc.getAttribute('DOC_DATE')))
      and (not VarIsNull(Doc.getAttribute('DESCRIPTION'))) then
      FmOrg.Caption := 'Документ № ' + Doc.getAttribute('DOC_NUMBER') +
        ', дата: ' + Doc.getAttribute('DOC_DATE') + ', основание: ' +
        Doc.getAttribute('DESCRIPTION');
    FmOrg.ShowModal;
    if EdtOrgId.Text <> '' then
      Result := QueryXml(sqlOrgId, [EdtOrgId.Text]);
  finally
    FmOrg.Free;
    EdtOrgId.Free;
  end;
end;

//Возвращает реквизиты незакрытого счета, вместе с ТОФК, УФК и прочее по ID счета.
function GetOrgAccount( aAccID: String): Variant;
begin
  Result := QueryXml( sqlAccAllRek + ' and A.Id = ?', [aAccID]);
end;

//Возвращает реквизиты незакрытого счета, вместе с ТОФК, УФК и прочее по ID счета.
function GetOrgAccountByTypes( aAccID, aAccType: String;
                              aBudgetFlag: String = ''): Variant;
begin
  Result := QueryXml(
    'Select A.Id Id, Ofk.Description Ofk_Description,' +
    ' Ufk.Description Ufk_Description, UfkAcc.Account_Number Ufk_Account_Number,' +
    ' UfkAcc.Id Ufk_Acc_Id, Ufkb.Bic Bic, Ufkb.Description B_Name, Ufkb.CorAccount CorAccount,' +
    ' SpecAcc.Account_Number SpecUfk_Account_Number, SpecAcc.Id SpecUfk_Acc_Id,' +
    ' Specb.Bic SpecBic, Specb.Description Specb_Name, Specb.CorAccount SpecCorAccount,' +
    ' IncAcc.Account_Number IncUfk_Account_Number, IncAcc.Id IncUfk_Acc_Id, Incb.Bic IncBic,' +
    ' Incb.Description Incb_Name, Incb.CorAccount IncCorAccount, IncUfkf.Name IncUfk_Filial_Name' +
    ' From OrgAccount A' +
    ' Left Join Org Ofk on Ofk.Id = A.Keeper_Id' +
    ' Left Join Org Ufk on Ufk.Id = A.Executer_Id' +
    ' Left Join OrgAccount UfkAcc on UfkAcc.Id = A.ExecuterAcc_Id' +
    ' Left Join Bank Ufkb on Ufkb.Id = UfkAcc.Bank_Id' +
    ' Left Join OrgAccount SpecAcc on SpecAcc.Id = A.SpecialFundsAcc_Id' +
    ' Left Join Bank Specb on Specb.Id = SpecAcc.Bank_Id' +
    ' Left Join OrgAccount IncAcc on IncAcc.Id = A.IncomeAcc_Id' +
    ' Left Join Bank Incb on Incb.Id = IncAcc.Bank_Id' +
    ' Left Join Filial IncUfkf on IncUfkf.Id = IncAcc.Filial_Id' +
    ' Where A.Close_Date is null  and A.Id = ? and A.Distributive_Flag = 0'
   +IfThen( aBudgetFlag <> '', ' and A.Budget_Flag = ' + aBudgetFlag, '')
   +' and A.OrgAccType_Id in (' + aAccType + ')' ,
    [aAccID]);
end;

//Возвращает реквизиты незакрытого счета, вместе с ТОФК, УФК и прочее по ID счета.
function GetOrgAccountByOrgAndTypes( aOrgID, aAccType: String;
                              aBudgetFlag: String = ''): Variant;
begin
  Result := QueryXml(
    'Select A.Id Id, A.Account_number Account_Number, Ofk.Description Ofk_Description,' +
    ' Ufk.Description Ufk_Description, UfkAcc.Account_Number Ufk_Account_Number,' +
    ' UfkAcc.Id Ufk_Acc_Id, Ufkb.Bic Bic, Ufkb.Description B_Name, Ufkb.CorAccount CorAccount,' +
    ' SpecAcc.Account_Number SpecUfk_Account_Number, SpecAcc.Id SpecUfk_Acc_Id,' +
    ' Specb.Bic SpecBic, Specb.Description Specb_Name, Specb.CorAccount SpecCorAccount,' +
    ' IncAcc.Account_Number IncUfk_Account_Number, IncAcc.Id IncUfk_Acc_Id, Incb.Bic IncBic,' +
    ' Incb.Description Incb_Name, Incb.CorAccount IncCorAccount, IncUfkf.Name IncUfk_Filial_Name' +
    ' From OrgAccount A' +
    ' Left Join Org Ofk on Ofk.Id = A.Keeper_Id' +
    ' Left Join Org Ufk on Ufk.Id = A.Executer_Id' +
    ' Left Join OrgAccount UfkAcc on UfkAcc.Id = A.ExecuterAcc_Id' +
    ' Left Join Bank Ufkb on Ufkb.Id = UfkAcc.Bank_Id' +
    ' Left Join OrgAccount SpecAcc on SpecAcc.Id = A.SpecialFundsAcc_Id' +
    ' Left Join Bank Specb on Specb.Id = SpecAcc.Bank_Id' +
    ' Left Join OrgAccount IncAcc on IncAcc.Id = A.IncomeAcc_Id' +
    ' Left Join Bank Incb on Incb.Id = IncAcc.Bank_Id' +
    ' Left Join Filial IncUfkf on IncUfkf.Id = IncAcc.Filial_Id' +
    ' Where A.Close_Date is null  and A.Org_Id = ? and A.Distributive_Flag = 0'
   +IfThen( aBudgetFlag <> '', ' and A.Budget_Flag = ' + aBudgetFlag, '')
   +' and A.OrgAccType_Id in (' + aAccType + ')' ,
    [aOrgID]);
end;

//Возвращает реквизиты незакрытого счета, вместе с ТОФК, УФК и прочее
//по Id организации и номеру счета. Результат в Xml
function GetAccAllRekByOrgIdAccNum(Org_Id, AccNum: String; AccType: String = '';
  BudgetFlag: String = ''; IncomeAcc: Boolean = False): Variant;
var
  sql: String;
begin

    try
      if AccType = '' then
        Result := QueryXml( sqlAccAllRek + ' and A.Org_Id = ? and A.Account_Number = ?',
                           [Org_Id, AccNum])
      else
        if IncomeAcc then
        begin
          sql := 'Select A.Id Id, Ofk.Description Ofk_Description,' +
            ' Ufk.Description Ufk_Description, UfkAcc.Account_Number Ufk_Account_Number,' +
            ' UfkAcc.Id Ufk_Acc_Id, Ufkb.Bic Bic, Ufkb.Description B_Name, Ufkb.CorAccount CorAccount,' +
            ' SpecAcc.Account_Number SpecUfk_Account_Number, SpecAcc.Id SpecUfk_Acc_Id,' +
            ' Specb.Bic SpecBic, Specb.Description Specb_Name, Specb.CorAccount SpecCorAccount,' +
            ' IncAcc.Account_Number IncUfk_Account_Number, IncAcc.Id IncUfk_Acc_Id, Incb.Bic IncBic,' +
            ' Incb.Description Incb_Name, Incb.CorAccount IncCorAccount, IncUfkf.Name IncUfk_Filial_Name' +
            ' From OrgAccount A' +
            ' Left Join Org Ofk on Ofk.Id = A.Keeper_Id' +
            ' Left Join Org Ufk on Ufk.Id = A.Executer_Id' +
            ' Left Join OrgAccount UfkAcc on UfkAcc.Id = A.ExecuterAcc_Id' +
            ' Left Join Bank Ufkb on Ufkb.Id = UfkAcc.Bank_Id' +
            ' Left Join OrgAccount SpecAcc on SpecAcc.Id = A.SpecialFundsAcc_Id' +
            ' Left Join Bank Specb on Specb.Id = SpecAcc.Bank_Id' +
            ' Left Join OrgAccount IncAcc on IncAcc.Id = A.IncomeAcc_Id' +
            ' Left Join Bank Incb on Incb.Id = IncAcc.Bank_Id' +
            ' Left Join Filial IncUfkf on IncUfkf.Id = IncAcc.Filial_Id' +
            ' Where A.Close_Date is null and A.Org_Id = ? and A.Account_Number = ?' +
            ' and A.Distributive_Flag = 0';
          Result := QueryXml(sql + IfThen(BudgetFlag <> '', ' and A.Budget_Flag = ' + BudgetFlag, '') +
            ' and A.OrgAccType_Id in (' + AccType + ')' , [Org_Id, AccNum]);
        end
        else
          Result := QueryXml(sqlAccAllRek + ' and A.Org_Id = ? and A.Account_Number = ?' +
            ' and A.Distributive_Flag = 0' + IfThen(BudgetFlag <> '', ' and A.Budget_Flag = ' + BudgetFlag, '') +
            ' and A.OrgAccType_Id in (' + AccType + ')' , [Org_Id, AccNum]);
      except
        ExceptionProc( 'GetAccAllRekByOrgIdAccNum');
    end;

end;

//Возвращает номер счета с типом 9 или пусто на котором открыт счет с типом 1
function GetAccountKeeperByIdAccLs(Acc_Id: String): String;
var
  sql: String;
begin
  sql := 'Select LsKeeperAcc.Account_Number' +
    ' From OrgAccount Ls' +
    ' Left Join OrgAccount LsKeeperAcc on LsKeeperAcc.Id = Ls.KeeperAcc_Id' +
    ' Where Ls.Id = ? and LsKeeperAcc.OrgAccType_Id = 9 and Ls.OrgAccType_Id = 1';
  Result := QueryField(sql, [Acc_Id], 'ACCOUNT_NUMBER');
end;

//Возвращает Id территории по окато
function GetTerritory_IdByOkato(Okato: String): String;
begin
  Result := QueryField('Select Id From Territory Where Okato = ?', [Okato], 'ID');
end;

//Возвращает значение Id вида операции, или пусто, когда его нет
function GetBankoper_Id(Bankoper_Id: String): String;
var
  Value: Integer;
begin
  try
    Value := StrToInt(Bankoper_Id);
    Result := QueryField('Select Id From BankOper Where Id = ?', [Value], 'ID');
  except
    Result := '';
  end;
end;

//Возвращает True - если найден статус лица в базе. Поиск по Id(для загрузки)
function Author_IdExists(Id: String): Boolean;
begin
  Result := QueryField('Select ID From Paydocauthor Where Id = ?', [Id], 'ID') <> '';
end;

//Возвращает Id показателя основания налогового платежа, если есть в справочнике
//иначе пустую строку (поле "106")
function GetGrnd_Ground_Id(Name: String): String;
begin
  Result := QueryField('Select Id From PayGround Where Name = ?',
    [Trim(UpperCase(Name))], 'ID');
end;

//Возвращает тип налогового платежа, если есть в справочнике
//иначe пустую строку (поле "110")
function GetGrnd_PayType_Id(Name: String): String;
begin
  Result := QueryField('Select Id From PayType Where Name = ?',
    [Trim(UpperCase(Name))], 'ID');
end;

//Возвращает True, если установлена галка у сметы. На входе Id сметы.
//параметр CheckBox должен совпадать с полями галок в базе.
function GetEstimateCheckBox(Id, CheckBox: String): Boolean;
var
  sql: String;
begin
  if Trim(CheckBox) = '' then
    Raise('Функция: GetEstimateCheckBox. Значение параметра CheckBox - пусто.');
  sql := 'Select * From Estimate Where Id = ?';
  Result := QueryField(sql, [Id], UpperCase(CheckBox)) = '1';
end;

//функция проверяет тип счета
function GetAccType(Account_Id: String): String;
var
  sql: String;
begin
  sql := ' Select * From OrgAccount Where Id = ?';
  Result := QueryField(sql, [Account_Id], 'ORGACCTYPE_ID');
end;

//Возвращает True, если у организации есть указанная роль
function HasOrgRole(OrgId, RoleId: String): Boolean;
var
  sql: String;
begin
  sql := 'Select R.*' +
    ' From OrgRoles Rs' +
    ' Left Join OrgRole R on R.Id = Rs.OrgRole_Id' +
    ' Where Rs.Org_Id = ? and R.Id = ?';
  Result := QueryField(sql, [OrgId, RoleId], 'ID') = RoleId;
end;

//Возвращает True, если счет является бюджетным и нераспорядительным(распорядительным)
function HasAccRole(OrgId, RFlag: String): Boolean;
var
  sql: String;
begin
  sql := 'Select * From OrgAccount' +
    ' Where Id = ? and Budget_Flag = 1 and Distributive_Flag = ?';
  Result := QueryField(sql, [OrgId, RFlag], 'ID') <> '';
end;

//функция проверяет тип Банка
function GetBankType(Bic: String): String;
var
  sql: String;
begin
  sql := ' Select * From Bank Where Bic = ?';
  Result := QueryField(sql, [Bic], 'BANK_TYPE');
end;

{~GetOrgByAccNumOrgCode
//Получает данные организации по номеру счета и коду организации. Используется
//для получения данных ФО. Результат в Xml.
//NBR = счет без галок бюджетный и распорядительный
//IncomeAcc = счет для учета поступлений - только для 8 типа счета
  exchagne #3044
  доработка запроса:
    добавлен код филиала (UFK_FILIAL_CODE)
    добавлен код ТОФК (Ofk_CODE)}
function GetOrgByAccNumOrgCode(AccNum, OrgCode: String; OrgAccType: String = '';
  NBR: Boolean = False; IncomeAcc: Boolean = False; FinYear: String = ''): Variant;
var
  sql: String;
begin

    try
      // to do при переходе всех клиентов на 2.23.60.69 и выше версию добавить поля
      // в сам запрос sqlOrgAllRek
      if IncomeAcc then
        sql := 'Select A.Id Acc_Id, A.Account_Number, O.Id Org_Id, O.TaxCode,' +
        ' O.Kpp, O.Description Org_Description, O.Caption Org_Caption,' +
        ' O.Name Org_Code, O.Kadm_Code,'
       +' Ofk.Description Ofk_Description,'
       +' Ofk.Name Ofk_CODE,'
       +' Ufk.Description Ufk_Description,'
       +' UfkAcc.Account_Number Ufk_Account_Number, UfkAcc.Id Ufk_Acc_Id,'
       +' Ufkb.Bic Bic,'
       +' Ufkb.Description B_Name, Ufkb.CorAccount CorAccount,'
       +' UFKF.name UFK_FILIAL_NAME,'
       +' UFKF.code UFK_FILIAL_CODE,'
       +' SpecAcc.Account_Number SpecUfk_Account_Number,'
       +' SpecAcc.Id SpecUfk_Acc_Id, Specb.Bic SpecBic,'
       +' Specb.Description Specb_Name, Specb.CorAccount SpecCorAccount,'
       +' SpecUfkf.Name SpecUfk_Filial_Name,'
       +' IncAcc.Account_Number IncUfk_Account_Number,' +
        ' IncAcc.Id IncUfk_Acc_Id, Incb.Bic IncBic, Incb.Description Incb_Name,' +
        ' Incb.CorAccount IncCorAccount, IncUfkf.Name IncUfk_Filial_Name,'
       +' Obd.Budget_id'
       +' From OrgAccount A' +
        ' Left Join Org O on O.Id = A.Org_Id' +
        ' Left Join OrgBudgetDet Obd on Obd.Org_Id = O.Id' +
        ' Left Join Budget B on B.Id = Obd.Budget_id' +
        ' Left Join Org Ofk on Ofk.Id = A.Keeper_Id' +
        ' Left Join Org Ufk on Ufk.Id = A.Executer_Id' +
        ' Left Join OrgAccount UfkAcc on UfkAcc.Id = A.ExecuterAcc_Id' +
        ' Left Join Bank Ufkb on Ufkb.Id = UfkAcc.Bank_Id' +
        ' Left Join Filial Ufkf on Ufkf.Id = UfkAcc.Filial_Id' +
        ' Left Join OrgAccount SpecAcc on SpecAcc.Id = A.SpecialFundsAcc_Id' +
        ' Left Join Bank Specb on Specb.Id = SpecAcc.Bank_Id' +
        ' Left Join Filial SpecUfkf on SpecUfkf.Id = SpecAcc.Filial_Id' +
        ' Left Join OrgAccount IncAcc on IncAcc.Id = A.IncomeAcc_Id' +
        ' Left Join Bank Incb on Incb.Id = IncAcc.Bank_Id' +
        ' Left Join Filial IncUfkf on IncUfkf.Id = IncAcc.Filial_Id' +
        ' Where A.Close_Date is null and O.Close_Date is null' +
        ' and A.Account_Number = ? and Obd.Code_Fk = ?'
      else
        sql := sqlOrgAllRek + ' and A.Account_Number = ? and Obd.Code_Fk = ?';
      if NBR then
        sql := sql + ' and A.Budget_Flag = 0 and A.Distributive_Flag = 0';
      if FinYear <> '' then
      begin
        sql := sql + ' and B.FinYear = ?';
        if OrgAccType = '' then
          Result := QueryXml(sql + ' and A.OrgAccType_Id = 9', [AccNum, OrgCode, FinYear])
        else
          Result := QueryXml(sql + ' and A.OrgAccType_Id in (' + OrgAccType + ')',
            [AccNum, OrgCode, FinYear]);
      end
      else begin
        if OrgAccType = '' then
          Result := QueryXml(sql + ' and A.OrgAccType_Id = 9', [AccNum, OrgCode])
        else
          Result := QueryXml(sql + ' and A.OrgAccType_Id in (' + OrgAccType + ')',
            [AccNum, OrgCode]);
      end;
      if Result.documentElement.childNodes.length = 0 then
      begin
        if IncomeAcc then
          sql := StringReplace(sql, 'Obd.Code_Fk = ?', 'O.Name = ?')
        else
          sql := sqlOrgAllRek + ' and A.Account_Number = ? and O.Name = ?';
        if NBR then
          sql := sql + ' and A.Budget_Flag = 0 and A.Distributive_Flag = 0';
        if OrgAccType = '' then
          Result := QueryXml(StringReplace(sql, ' and B.FinYear = ?', ' ') + ' and A.OrgAccType_Id = 9', [AccNum, OrgCode])
        else
          Result := QueryXml(StringReplace(sql, ' and B.FinYear = ?', ' ') + ' and A.OrgAccType_Id in (' + OrgAccType + ')',
            [AccNum, OrgCode]);
      end;

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

end;

//Возвращает ID бюджета по фин.году и орг. исп. бюджет. Не нашли - вернули пусто
function GetBudgetByFinYearExecutor(FinYear, Executor_Id: String): String;
begin
  Result := QueryXml(sqlBudget + ' Where BudgKind = 2 and FinYear = ?' +
    ' and Executor_Id = ?', [FinYear, Executor_Id]);
end;

//Возвращает ID бюджета по фин.году, орг ФО и коду УБП. Не нашли - вернули пусто
function GetBudgetByFinYearFoCodeUbp(Fo_Id, Code_Ubp, FinYear: String): Variant;
begin
  Result := QueryXml(sqlBudgetByFinYearFOKodFo, [Fo_Id, Code_Ubp, FinYear]);
end;

//Возвращает получателей доходов с флагом по умолчанию по Id организации.
function GetIncReceiverByBudgetOrgId(BudgetId, OrgId: String): Variant;
begin

    try
      Result := QueryXml('Select * From Receiver Where IsDefault = 1' +
        ' and Budget_Id = ? and Org_Id = ?', [BudgetId, OrgId]);

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

end;

{~GetIncReceiverByBudget
  Возвращает Id всех получателей доходов с флагом по умолчанию привязанных к
  органиции ФО справочника бюджетов. Результат в Xml.}
function GetIncReceiverByBudget(BudgetId: String): Variant;
begin

    try
      Result := QueryXml( 'Select R.Id Rec_Id'
                         +' From Budget B'
                          // exchange #2456 - поправлен запрос
                         +' Left Join Receiver R on R.Budget_Id=B.ID and R.Org_Id = B.Org_Id'
                         +' Where R.IsDefault = 1 and B.Id = ?',
                          [BudgetId]);

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

end;

//Возвращает данные бюджета с типом "исполнение" по ID организации и фин.году.
//Результат в Xml.
function GetBudgetByFinYearOrgId(FinYear, OrgId: String): Variant;
begin
  Result := QueryXml(sqlBudget + ' Where BudgKind = 2 and FinYear = ?' +
    ' and Org_Id = ?', [FinYear, OrgId]);
end;

//Возвращает данные по получателю доходов с галкой по умолчнию, в привязке к
//организации
function GetReceiverAttrByOrg(OrgId: String; Budget: String = ''): Variant;
begin
  if Budget <> '' then
    Result := QueryXml('Select * From Receiver Where IsDefault = 1 and Org_Id = ?' +
     ' and Budget_Id = ?', [OrgId, Budget])
  else
    Result := QueryXml('Select * From Receiver Where IsDefault = 1 and Org_Id = ?',
      [OrgId]);
end;

{~GetAnswerDocId
//получает Id документа для которого искать пару
// пока поиск только 114 и 182 классов}
function GetAnswerDocId(Doc: Variant): String;
var
  Xml: Variant;
  sql: String;
  QueryLink: TRunQuery;
begin
  Result := '';
  QueryLink := TRunQuery.Create;
  try
    sql := ' Select A.Id From Document D';
    if Doc.getAttribute('class') = 114 then
      sql := sql + ' Left Join PayDetail A on A.Document_Id = D.Id';
    if Doc.getAttribute('class') = 182 then
      sql := sql + ' Left Join CancelReqorder A on A.Document_Id = D.Id';
    sql := sql + ' Where D.Budget_Id = ? and D.DispStatus_Id = 16' +
      ' and D.DocumentClass_Id = ? and LTrim(D.Doc_Number) = ?' +
      ' and D.Doc_Date = ? and A.Extstatus_Id = 1';
    QueryLink.AddStr(Doc.getAttribute('F_BUDGET_ID'));
    QueryLink.AddStr(Doc.getAttribute('class'));
    QueryLink.AddStr(Doc.getAttribute('DOC_NUMBER'));
    QueryLink.AddDate(StrToDate(Doc.getAttribute('DOC_DATE')));
    if not (Doc.getAttribute('F_ORIGINAL_TYPE') in ['CE', 'IK']) and
      (Doc.getAttribute('class') = 114) then
    begin
      sql := sql + ' and D.Amount = ?';
      QueryLink.AddCurr(StrToCurr(Doc.getAttribute('AMOUNT')));
    end;
    if Doc.getAttribute('F_ORIGINAL_TYPE') = 'IK' then
    begin
      sql := sql + ' and A.Org_Account = ?';
      QueryLink.AddStr(Doc.getAttribute('LS'));
    end;
    Xml := CreateOleObject('Microsoft.XmlDom');
    Xml.LoadXml(QueryLink.Run(sql));
    if Xml.documentElement.childNodes.Length = 1 then
      Result := Xml.documentElement.childNodes.Item[0].getAttribute('ID');
  finally
    QueryLink.Free;
  end;
end;

{~GetAnswerDocId_2638_114
  exchange #2638
  поиск ЭД 114го класса для файлов: VB,VA

  здесь сумма проверяется как для шапки ЭД, так и как сумма в целевых строках
  на закладке "расшифровка"}
function GetAnswerDocId_2638_114(Doc: Variant): String;
var
  xXml: Variant;
  xAmount: Currency;//string;
  xAmountStr: string;
  xQueryLink: TRunQuery;
  i,j: integer;
  xXmlLines: Variant;
  xXmlNode: Variant;
  xID: string;
  xAmountLines: Currency;
  xSQL: string;
  {---------------------------------------------------------------------------}
  {~IsFieldValFill_
    проверка заполнения поля aAttrName.
    результат:
      =true - поле содержит не пустое и не нулевое значение
      =false - поле содержит пустое или нулевое значение.
    если aNullIsEmpty все символы '0' заменяются на пусто.
    это актуально для КБК, где указывается код.}
  function IsFieldValFill_( aAttrName: string;
                            aNullIsEmpty: boolean = FALSE): boolean;
  var
    s: string;
  begin
  
      try
        s := TRIM( GetNodeAttributeEx( xXmlNode,  aAttrName));

        if ( LENGTH( s) <= 0)
          then Result := TRUE
          else
            if NOT aNullIsEmpty
              then Result := FALSE
              else
                if ( LENGTH( StringReplace( s, '0', '')) <= 0)
                  then Result := TRUE
                  else Result := FALSE;
        except
          ExceptionLog( 'Сбой IsFieldValFill_');
      end;
  
  end;
  {---------------------------------------------------------------------------}
  function IsFieldPurposefulFill_( aAttrName: string): boolean;
  var
    s: string;
  begin
  
      try
        s := TRIM( GetNodeAttributeEx( xXmlNode,  aAttrName));

        if ( LENGTH( s) <= 0)
          then Result := TRUE
          else
            if ( QueryField( ' select CODE C from PURPOSEFULGRANT'
                            +' where ID = ?',
                             [ s],
                             'C') = '0')
              then Result := TRUE
              else Result := FALSE;
        except
          ExceptionLog( 'Сбой IsFieldPurposefulFill_');
      end;
  
  end;
  {---------------------------------------------------------------------------}
begin

    try
      Result := '';

      xXml := CreateOleObject('Microsoft.XmlDom');
      try
        // exchange #2798
        // доработана обработка запроса (через TRunQuery).
        // это более надежно в плане передачи параметров даты и чисел.
        // запрос должен быть без кеша.
        // exchange #2638
        // поправлена реализация: нужно было искать по сумме всех строк,
        // а не по сумме в каждой строке. это придется делать отдельным запросом.
        xQueryLink := TRunQuery.Create;
        try
          // сумма понадобится в виде числовой переменной
          xAmountStr := Doc.getAttribute('AMOUNT');
          xAmount := StrToCurr( xAmountStr);

          // в начале ищем по сумме в шапке
          xQueryLink.AddStr( Doc.getAttribute('F_BUDGET_ID'));
          xQueryLink.AddStr( Doc.getAttribute('class'));
          xQueryLink.AddStr( Doc.getAttribute('DOC_NUMBER'));
          xQueryLink.AddDate( StrToDate( Doc.getAttribute('DOC_DATE')));
          xQueryLink.AddCurr( xAmount);

          xSQL :=  ' Select A.Id From Document D'
                  +' Left Join PayDetail A on A.Document_Id = D.Id'
                  +' Where D.Budget_Id = ? and D.DispStatus_Id = 16'
                  +' and D.DocumentClass_Id = ? and LTrim(D.Doc_Number) = ?'
                  +' and D.Doc_Date = ? and A.Extstatus_Id = 1'
                  +' and D.Amount = ?';      // с искомой суммой

          xXml.LoadXml( xQueryLink.Run( xSQL));
          if (xXml.documentElement.childNodes.Length = 1) then begin
            Result := xXml.documentElement.childNodes.Item[0].getAttribute('ID');
            EXIT;
          end;

          // если поиск по сумме в шапке не нашел однозначно ЭД,
          // то перебираем все ЭД в которых есть целевые строки.
          // в результате получаем список ID таких ЭД
          xQueryLink.AddStr( Doc.getAttribute('F_BUDGET_ID'));
          xQueryLink.AddStr( Doc.getAttribute('class'));
          xQueryLink.AddStr( Doc.getAttribute('DOC_NUMBER'));
          xQueryLink.AddDate( StrToDate( Doc.getAttribute('DOC_DATE')));

          xSQL :=  ' Select A.Id From Document D'
                  +' Left Join PayDetail A on A.Document_Id = D.Id'
                  +' Where D.Budget_Id = ? and D.DispStatus_Id = 16'
                  +' and D.DocumentClass_Id = ? and LTrim(D.Doc_Number) = ?'
                  +' and D.Doc_Date = ? and A.Extstatus_Id = 1'
                  +' and exists (select * from paydetailline AL'
                  +' where AL.paydetail_id = A.ID'
                  +' and AL.IS_SOURCE_LINE=0)';   // нужны только dslline

          xXml.LoadXml( xQueryLink.Run( xSQL));

          // для ускорения операции создаем xml, в который будем
          // загружать ЭД по ID, а в конце его очистим. это быстрее чем
          // на каждый ID создавать свой XML, хотя менее наглядно.
          xXmlLines := CreateOleObject('Microsoft.XmlDom');
          try
            for i := 0 to xXml.documentElement.childNodes.Length - 1 do begin
              xXmlNode  := xXml.documentElement.childNodes.Item[ i];
              xID       := xXmlNode.GetAttribute('ID');


              // в начале сравниваем итоговую сумму по всем строкам.
              // если сумма строк совпадает с искомой суммой - считаем ЭД
              // найденным. однако, если будет найдено несколько ЭД
              // с подходящей суммой, поиск считаем неудачным.
              xAmountLines := StrToCurr(
                                  QueryField( 'select SUM(al.amount) N'
                                             +' from paydetailline AL'
                                             +' where AL.paydetail_id = ?'
                                             +' and AL.IS_SOURCE_LINE=0',
                                              [ xID],
                                              'N'));

              // exchange #2838
              // проблема сравнения значений currency - ошибка плавающей
              // арифметики из-за дробных значений.
              // нужно сравнивать строковые значения!
              if (xAmountStr = FORMAT( '%0.2f', [ xAmountLines])) then begin

                if (LENGTH( Result) > 0) then begin

                  Result := '';
                  BREAK;        // прерываем поиск
                end;
                Result := xID;
              end;

              // если по сумме строк не совпадает - получаем все строки,
              // для этого ЭД, которые будем анализировать по отдельности.
              xQueryLink.AddStr( xID);
              xXmlLines.LoadXml(
                  xQueryLink.Run( 'select * from paydetailline AL'
                                 +' where AL.paydetail_id = ?'
                                 +' and AL.IS_SOURCE_LINE=0'));


              for j := 0 to xXmlLines.documentElement.childNodes.Length - 1 do begin
                // берем строку
                xXmlNode  := xXmlLines.documentElement.childNodes.Item[ j];

                // если значение в строке пустое, кроме суммы (вид классификации
                // и номер строки не проверяется).
                // в получателе проверяется: или ID или любое из полей
                // считается заполненной орг.
                if NOT IsFieldValFill_( 'REC_ID') then CONTINUE;
                if NOT IsFieldValFill_( 'REC_NAME') then CONTINUE;
                if NOT IsFieldValFill_( 'REC_ACCOUNT') then CONTINUE;
                if NOT IsFieldValFill_( 'REC_ACC_ID') then CONTINUE;
                if NOT IsFieldValFill_( 'REC_KPP') then CONTINUE;
                if NOT IsFieldValFill_( 'REC_TAXCODE') then CONTINUE;
                if NOT IsFieldValFill_( 'REC_OKATO') then CONTINUE;
                if NOT IsFieldValFill_( 'KADMD_CODE', TRUE) then CONTINUE;
                if NOT IsFieldValFill_( 'KADMI_CODE', TRUE) then CONTINUE;
                if NOT IsFieldValFill_( 'KADMR_CODE', TRUE) then CONTINUE;
                if NOT IsFieldValFill_( 'KCSR_CODE', TRUE) then CONTINUE;
                if NOT IsFieldValFill_( 'KDD_CODE', TRUE) then CONTINUE;
                if NOT IsFieldValFill_( 'KDE_CODE', TRUE) then CONTINUE;
                if NOT IsFieldValFill_( 'KDF_CODE', TRUE) then CONTINUE;
                if NOT IsFieldValFill_( 'KDI_CODE', TRUE) then CONTINUE;
                if NOT IsFieldValFill_( 'KESD_CODE', TRUE) then CONTINUE;
                if NOT IsFieldValFill_( 'KESI_CODE', TRUE) then CONTINUE;
                if NOT IsFieldValFill_( 'KESR_CODE', TRUE) then CONTINUE;
                if NOT IsFieldValFill_( 'KVR_CODE', TRUE) then CONTINUE;
                // exchange #3085
                // убраны поля квфо из проверки на пустую строку
//                if NOT IsFieldValFill_( 'FSD_ID', TRUE) then CONTINUE;
//                if NOT IsFieldValFill_( 'FSI_ID', TRUE) then CONTINUE;
//                if NOT IsFieldValFill_( 'FSR_ID', TRUE) then CONTINUE;
                if NOT IsFieldValFill_( 'KD_CODE', TRUE) then CONTINUE;
                if NOT IsFieldValFill_( 'KFSR_CODE', TRUE) then CONTINUE;
                if NOT IsFieldValFill_( 'KI_CODE', TRUE) then CONTINUE;
                if NOT IsFieldPurposefulFill_( 'PURPOSEFULGRANTD_ID') then CONTINUE;
                if NOT IsFieldPurposefulFill_( 'PURPOSEFULGRANTI_ID') then CONTINUE;
                if NOT IsFieldPurposefulFill_( 'PURPOSEFULGRANT_ID') then CONTINUE;
                // найдена пустая строка - вычитаем сумму из общей суммы строк
                xAmountLines := xAmountLines
                                - StrToCurr( xXmlNode.GetAttribute( 'AMOUNT'));

              end;//for//
              // если в итоге, сумма всех строк кроме пустых совпадет с искомой
              // суммой - считаем такой ЭД найденным

              // exchange #2838
              // проблема сравнения значений currency - ошибка плавающей
              // арифметики из-за дробных значений.
              // нужно сравнивать строковые значения!
              if (xAmountStr = FORMAT( '%0.2f', [ xAmountLines])) then begin
                // здесь проверяем, если уже был найден ЭД с подходящей суммой,
                // и это не тот же ЭД, в котором и итоговая сумма совпала,
                // то считаем что ничего не найдено и дальнейший перебор
                // списка ид.найденных ЭД прерываем.
                // exchange #2838
                // ошибка была в том, что есть вариант эд в котором совпадает
                // и итоговая сумма и в одной из пустых строк сумма =0.
                // т.е. срабатывают две независимые проверки.
                // и вот тут нужно проверить - это один и тот же ЭД или это
                // разные ЭД.
                if (( LENGTH( Result) > 0) AND (Result <> xID)) then begin

                  Result := '';
                  BREAK;    // прерываем перебор строк в ЭД
                end;

                Result := xID;
              end;
            end;//for//
            finally
              xXmlLines.LoadXml( '');   // чистим память
          end;
          finally
            xQueryLink.Free;
        end;
        finally
          xXml.LoadXml( '');   // чистим память
      end;
{
  //        xAmount := FORMAT( '%0.2f', [ StrToCurr(Doc.getAttribute('AMOUNT'))]);
      xXml := QueryXml(  ' Select A.Id From Document D'
                        +' Left Join PayDetail A on A.Document_Id = D.Id'
                        +' Where D.Budget_Id = ? and D.DispStatus_Id = 16'
                        +' and D.DocumentClass_Id = ? and LTrim(D.Doc_Number) = ?'
                        +' and D.Doc_Date = ? and A.Extstatus_Id = 1'
                        +' and ( D.Amount = ? or'
                        +' exists (select * from paydetailline AL'
                        +' where AL.paydetail_id = A.ID'
                        +' and AL.IS_SOURCE_LINE=0'   // нужны только dslline
                        +' and AL.amount=?))',        // с искомой суммой
                         [ Doc.getAttribute('F_BUDGET_ID'),
                           Doc.getAttribute('class'),
                           Doc.getAttribute('DOC_NUMBER'),

                           // работает, если делать так.
                           // если заполнять переменную типа TDateTime и передавать
                           // ее как параметр, тогда она преобразуется не как
                           // Date, а как число и в выполнении запроса будет сбой.
                           // это место одно из самых проблемных.
                           StrToDate(Doc.getAttribute('DOC_DATE')),

                           xAmount,
                           xAmount],
                         FALSE);    // без кэша


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

      }
      except
        ExceptionLog( 'Сбой QueryWork.GetAnswerDocId_2638_114');
    end;

end;


function GetAnswerDocIdBu(Doc: Variant): String;
var
  Xml: Variant;
  sql: String;
  QueryLink: TRunQuery;
begin
  Result := '';
  QueryLink := TRunQuery.Create;
  try
    sql := 'Select P.Id' +
      ' From Document D' +
      ' Join PayDetail P on P.Document_Id = D.Id' +
      ' Join OrgAccount Oa on Oa.Id = P.Org_Acc_Id' +
      ' Where D.Budget_Id = ? and D.DispStatus_Id = 86' +
      ' and D.DocumentClass_Id = ? and LTrim(D.Doc_Number) = ?' +
      ' and D.Doc_Date = ? and P.Extstatus_Id = 1 and Oa.OrgAccType_Id = 5';
    QueryLink.AddStr(Doc.getAttribute('F_BUDGET_ID'));
    QueryLink.AddStr(Doc.getAttribute('class'));
    QueryLink.AddStr(Doc.getAttribute('DOC_NUMBER'));
    QueryLink.AddDate(StrToDate(Doc.getAttribute('DOC_DATE')));
    Xml := CreateOleObject('Microsoft.XmlDom');
    Xml.LoadXml(QueryLink.Run(sql));
    if Xml.documentElement.childNodes.Length = 1 then
      Result := Xml.documentElement.childNodes.Item[0].getAttribute('ID');
  finally
    QueryLink.Free;
  end;
end;


{~GetAnswerDocIdRR_VR_By2490
  поиск РР (расходных расписаний) и РРР (реестра расходных расписаний)
  по #2492 при загрузке из VR для разделов VRRAS и VRPOL.
  здесь используется расширенный критерий поиска, отличный от старой
  реализации в подпрограмме GetAnswerDocIdRR.
  при создании ЭД 148 в XML (в функции Imp_FK_VR.LoadFile) для разделов
  VRRAS/VRPOL необходимы следующие дополнительные теги:
    _VR_LS_ - номер л/с из VR.LS
    _VR_TYPE_ - тип подразделов: VRRAS/VRPOL }
function GetAnswerDocIdRR_VR_By2490(  aDoc: Variant;
                                      aQueryLink: TRunQuery): String;
var
  xXml: Variant;
  xXmlDoc: Variant;
  xSql: String;
  xVR_LS: string;
  xF_BUDGET_ID: string;
  xDOC_NUMBER: string;
  xDOC_DATE: TDateTime;
begin

    try
      Result := '';

      // эти параметры используются в нескольких запросах, поэтому
      // буферизуем их в локальных переменных
      xVR_LS        := aDoc.GetAttribute( '_VR_LS_');
      xF_BUDGET_ID  := aDoc.getAttribute( 'F_BUDGET_ID');
      xDOC_NUMBER   := aDoc.getAttribute( 'DOC_NUMBER');
      xDOC_DATE     := StrToDate( aDoc.getAttribute( 'DOC_DATE'));

      // этот объект понадобится в любом случае, поэтому создаем его один раз
      xXml := CreateOleObject('Microsoft.XmlDom');

      case aDoc.GetAttribute('_VR_TYPE_') of
        'VRPOL': begin


              { ищем пару среди РР
                при загрузке VR при поиске РР по расходной кбк, а также номеру,
                дате из блока VRPOL добавляем одновременно условие поиска по
                VR.LS - значение поля должно совпадать с номером счета,
                указанного в поле "Счет" блока "Получатель" Расходного
                расписания.}
              xSql :=  ' Select A.Id From Document D'
                      +' Left Join Expschedule A on A.Document_Id = D.Id'
                      +' Where D.Budget_Id = ? and D.DispStatus_Id = 16'
                      +' and D.DocumentClass_Id = ? and LTrim(D.Doc_Number) = ?'
                      +' and D.Doc_Date = ? and A.Extstatus_Id = 1'
                      +' and A.REC_ACCOUNT = ?'
                      +' and A.Anal_Kind = 0'
                      // exchange #2881
                      // получаем только шапку эд для многострочных эд
                      +' and (a.title_id=a.id or a.title_id is null)';

              aQueryLink.AddStr ( xF_BUDGET_ID);
              aQueryLink.AddStr ( aDoc.getAttribute('class'));
              aQueryLink.AddStr ( xDOC_NUMBER);
              aQueryLink.AddDate( xDOC_DATE);
              aQueryLink.AddStr ( xVR_LS);

              xXml.LoadXml( aQueryLink.Run( xSql));
              xXmlDoc := xXml.documentElement;

              if (xXmlDoc.childNodes.Length = 1) then begin
                Result := xXmlDoc.childNodes.Item[0].getAttribute('ID');
                EXIT;
              end;

              // пару среди рр не нашли, ищем среди ррр,
              // среди ррр ищем пару только если номер <= 3 символов
              if ( LENGTH( xDOC_NUMBER) > 3) then begin

                EXIT;
              end;

              { при загрузке VR при поиске РРР по расходной кбк, а также номеру,
                дате из блока VRPOL добавляем одновременно условие поиска по
                VR.LS - значение поля должно совпадать с номером счета,
                указанного в поле "Счет" блока "Получатель" хотя бы одного
                Расходного расписания, входящего в РРР на закладке "Связанные
                документы".}
              aDoc.SetAttribute('class', '149');
              xSql :=  ' Select A.Id From Document D'
                      +' Left Join ExpscheduleRegistry A on A.Document_Id = D.Id'
                      // join - поскольку ищем обязательная связка РРР-РР
                      // где РР - связанные документы в РРР.
                      +' join registerdoc rd on rd.master_id = A.document_id'
                      +' join expschedule e on rd.slave_id = e.document_id'
                      +' Where D.Budget_Id = ? and D.DispStatus_Id = 16'
                      +' and D.DocumentClass_Id = ? and LTrim(D.Doc_Number) = ?'
                      +' and D.Doc_Date = ? and A.Extstatus_Id = 1'
                      +' and e.REC_ACCOUNT = ?'
                      +' and A.Bk_Type = 10';
              aQueryLink.AddStr ( xF_BUDGET_ID);
              aQueryLink.AddStr ( aDoc.getAttribute('class'));
              aQueryLink.AddStr ( xDOC_NUMBER);
              aQueryLink.AddDate( xDOC_DATE);
              aQueryLink.AddStr ( xVR_LS);

//              xXml := CreateOleObject('Microsoft.XmlDom');
              xXml.LoadXml( aQueryLink.Run( xSql));
              xXmlDoc := xXml.documentElement;

              if xXmlDoc.childNodes.Length = 1 then begin
                Result := xXmlDoc.childNodes.Item[0].getAttribute('ID');
                EXIT;
              end;
            end;

        'VRRAS': begin


              { ищем пару среди РР
                при загрузке VR при поиске РР по расходной кбк, а также номеру,
                дате из блока VRRAS добавляем одновременно условие поиска по
                VR.LS - значение поля должно совпадать с номером счета,
                указанного в поле "Счет" блока "От кого" Расходного расписания
                (либо для организации блока полей "ГРБС/ГАИФДБ", либо для
                организации блока полей "РБС/ПБС/АИФДБ").}
              xSql :=  ' Select A.Id From Document D'
                      +' Left Join Expschedule A on A.Document_Id = D.Id'
                      +' Where D.Budget_Id = ? and D.DispStatus_Id = 16'
                      +' and D.DocumentClass_Id = ? and LTrim(D.Doc_Number) = ?'
                      +' and D.Doc_Date = ? and A.Extstatus_Id = 1'
                      +' and (A.MAIN_ACCOUNT = ? OR A.ORG_ACCOUNT = ?)'
                      +' and A.Anal_Kind = 0'
                      // exchange #2881
                      // получаем только шапку эд для многострочных эд
                      +' and (a.title_id=a.id or a.title_id is null)';

              aQueryLink.AddStr ( xF_BUDGET_ID);
              aQueryLink.AddStr ( aDoc.getAttribute('class'));
              aQueryLink.AddStr ( xDOC_NUMBER);
              aQueryLink.AddDate( xDOC_DATE);
              aQueryLink.AddStr ( xVR_LS);
              aQueryLink.AddStr ( xVR_LS);

//              xXml := CreateOleObject('Microsoft.XmlDom');
              xXml.LoadXml( aQueryLink.Run( xSql));
              xXmlDoc := xXml.documentElement;

              if (xXmlDoc.childNodes.Length = 1) then begin
                Result := xXmlDoc.childNodes.Item[0].getAttribute('ID');
                EXIT;
              end;

              // пару среди рр не нашли, ищем среди ррр,
              // среди ррр ищем пару только если номер <= 3 символов
              if ( LENGTH( xDOC_NUMBER) > 3) then begin

                EXIT;
              end;

              { поиск в РРР
                при загрузке VR при поиске РРР по расходной кбк, а также номеру,
                дате из блока VRRAS добавляем одновременно условие поиска по
                VR.LS - значение поля должно совпадать с номером счета,
                указанного в поле "Счет" блока на закладке "Документ" Реестра
                расходных расписаний (либо для организации блока полей
                "ГРБС/ГАИФДБ", либо для организации блока полей "РБС/АИФДБ").}
              aDoc.setAttribute('class', '149');
              xSql :=  ' Select A.Id From Document D'
                      +' Left Join ExpscheduleRegistry A on A.Document_Id = D.Id'
                      +' Where D.Budget_Id = ? and D.DispStatus_Id = 16'
                      +' and D.DocumentClass_Id = ? and LTrim(D.Doc_Number) = ?'
                      +' and D.Doc_Date = ? and A.Extstatus_Id = 1'
                      +' and (A.MAINORG_ACCOUNT = ? OR A.ORG_ACCOUNT = ?)'
                      +' and A.Bk_Type = 10';
              aQueryLink.AddStr ( xF_BUDGET_ID);
              aQueryLink.AddStr ( aDoc.getAttribute('class'));
              aQueryLink.AddStr ( xDOC_NUMBER);
              aQueryLink.AddDate( xDOC_DATE);
              aQueryLink.AddStr ( xVR_LS);
              aQueryLink.AddStr ( xVR_LS);

//              xXml := CreateOleObject('Microsoft.XmlDom');
              xXml.LoadXml( aQueryLink.Run( xSql));
              xXmlDoc := xXml.documentElement;

              if (xXmlDoc.childNodes.Length = 1) then begin
                Result := xXmlDoc.childNodes.Item[0].getAttribute('ID');
                EXIT;
              end;
            end;

      end;//case//
      except
        ExceptionLog( 'Сбой QueryWork.GetAnswerDocIdRR_VR_By2490');
    end;

end;


//получает Id документа для которого искать пару
//поиск 148, 149 классов
function GetAnswerDocIdRR(Doc: Variant): String;
var
  Xml: Variant;
  sql: String;
  QueryLink: TRunQuery;
begin

    try
      Result := '';
      QueryLink := TRunQuery.Create;
      try
        // exchange #2492
        // для VR поиск РР и РРР выполняется по другому.
        if (Doc.getAttribute('F_ORIGINAL_TYPE') = 'VR') then begin
          Result := GetAnswerDocIdRR_VR_By2490( Doc, QueryLink);
          EXIT;
        end;

        // временно разбираем рр и ррр по особенному
        if Doc.getAttribute('class') = '148' then
        begin
          // ищем пару среди РР
          sql := ' Select A.Id From Document D' +
            ' Left Join Expschedule A on A.Document_Id = D.Id' +
            ' Where D.Budget_Id = ? and D.DispStatus_Id = 16' +
            ' and D.DocumentClass_Id = ? and LTrim(D.Doc_Number) = ?'
            // exchange #2882
            // получаем только шапку эд для многострочных эд
            +' and (a.title_id=a.id or a.title_id is null)'
            +' and D.Doc_Date = ? and A.Extstatus_Id = 1';
          QueryLink.AddStr(Doc.getAttribute('F_BUDGET_ID'));
          QueryLink.AddStr(Doc.getAttribute('class'));
          QueryLink.AddStr(Doc.getAttribute('DOC_NUMBER'));
          QueryLink.AddDate(StrToDate(Doc.getAttribute('DOC_DATE')));
          if not (Doc.getAttribute('F_ORIGINAL_TYPE') in ['VA', 'VR', 'VG']) then
          begin
            sql := sql + ' and D.Amount = ?';
            QueryLink.AddCurr(StrToCurr(Doc.getAttribute('AMOUNT')));
          end;
          if Doc.getAttribute('F_ORIGINAL_TYPE') = 'VR' then
            sql := sql + ' and A.Anal_Kind = 0';
          if Doc.getAttribute('F_ORIGINAL_TYPE') = 'VG' then
            sql := sql + ' and A.Anal_Kind = 2';

          Xml := CreateOleObject('Microsoft.XmlDom');
          Xml.LoadXml(QueryLink.Run(sql));

          if Xml.documentElement.childNodes.Length = 1 then
            Result := Xml.documentElement.childNodes.Item[0].getAttribute('ID');
          //пару среди рр не нашли, ищем среди ррр,
          //среди ррр ищем пару только если номер <= 3 символов
          if (Result = '') and (Length(Doc.getAttribute('DOC_NUMBER')) <= 3) then
          begin
            Doc.setAttribute('class', '149');
            sql := 'Select A.Id From Document D' +
              ' Left Join ExpscheduleRegistry A on A.Document_Id = D.Id' +
              ' Where D.Budget_Id = ? and D.DispStatus_Id = 16' +
              ' and D.DocumentClass_Id = ? and LTrim(D.Doc_Number) = ?' +
              ' and D.Doc_Date = ? and A.Extstatus_Id = 1';
            QueryLink.AddStr(Doc.getAttribute('F_BUDGET_ID'));
            QueryLink.AddStr(Doc.getAttribute('class'));
            QueryLink.AddStr(Doc.getAttribute('DOC_NUMBER'));
            QueryLink.AddDate(StrToDate(Doc.getAttribute('DOC_DATE')));
            if not (Doc.getAttribute('F_ORIGINAL_TYPE') in ['VA', 'VR', 'VG']) then
            begin
              sql := sql + ' and D.Amount = ?';
              QueryLink.AddCurr(StrToCurr(Doc.getAttribute('AMOUNT')));
            end;
            if Doc.getAttribute('F_ORIGINAL_TYPE') = 'VR' then
              sql := sql + ' and A.Bk_Type = 10';
            if Doc.getAttribute('F_ORIGINAL_TYPE') = 'VG' then
              sql := sql + ' and A.Bk_Type in (31, 32)';
            Xml := CreateOleObject('Microsoft.XmlDom');
            Xml.LoadXml(QueryLink.Run(sql));
            if Xml.documentElement.childNodes.Length = 1 then
              Result := Xml.documentElement.childNodes.Item[0].getAttribute('ID');
          end;
        end;
      finally
        QueryLink.Free;
      end;
      except
        ExceptionLog( 'Сбой QueryWork.GetAnswerDocIdRR');
    end;

end;

{~GetDeclineDocId
  получает Id документа для которого искать пару для отказа.

  exchange #2462 - доработка:
  aStatusDocEx - проверка нужного статуса ЭД.
    по умолчанию - как в запросах: проверка жесткого статуса, но если параметр
    <>'', то производится проверка состояния ЭД по этому статусу.
    пока не используется.

    exchange #2530 - доработка пп.2 и пп.3}
function GetDeclineDocId(Doc: Variant; aStatusDocEx: string = ''): String;
var
  i: Integer;
  Xml: Variant;
  sql: String;
  QueryLink: TRunQuery;
begin

    try
      Result := '';
      QueryLink := TRunQuery.Create;
      try
        case Doc.getAttribute('class') of
          '148': begin
              // ищем пару среди РР
              sql := ' Select A.Id From Document D' +
                ' Left Join Expschedule A on A.Document_Id = D.Id' +
                ' Where D.Budget_Id = ? and D.DocumentClass_Id = ?'
                // exchange #3074
                // добавлено условие искать шапку эд
               +' and (a.title_id=a.id or a.title_id is null)'
               +' and D.DispStatus_Id = 16 and A.Extstatus_Id = 1' +
                ' and LTrim(D.Doc_Number) = ? and D.Doc_Date = ?';
              QueryLink.AddStr(Doc.getAttribute('F_BUDGET_ID'));
              QueryLink.AddStr(Doc.getAttribute('class'));
              QueryLink.AddStr(Doc.getAttribute('DOC_NUMBER'));
              QueryLink.AddDate(StrToDate(Doc.getAttribute('DOC_DATE')));
              if Doc.getAttribute('LS') <> '' then
              begin
                sql := sql + ' and A.Main_Account = ?' +
                  ' Union Select A.Id From Document D' +
                  ' Left Join Expschedule A on A.Document_Id = D.Id' +
                  ' Where D.Budget_Id = ? and D.DocumentClass_Id = ?'
                  // exchange #3074
                  // добавлено условие искать шапку эд
                 +' and (a.title_id=a.id or a.title_id is null)'
                 +' and D.DispStatus_Id = 16 and A.Extstatus_Id = 1' +
                  ' and LTrim(D.Doc_Number) = ? and D.Doc_Date = ?' +
                  ' and A.Org_Account = ?';
                QueryLink.AddStr(Doc.getAttribute('LS'));
                QueryLink.AddStr(Doc.getAttribute('F_BUDGET_ID'));
                QueryLink.AddStr(Doc.getAttribute('class'));
                QueryLink.AddStr(Doc.getAttribute('DOC_NUMBER'));
                QueryLink.AddDate(StrToDate(Doc.getAttribute('DOC_DATE')));
                QueryLink.AddStr(Doc.getAttribute('LS'));
              end;
              Xml := CreateOleObject('Microsoft.XmlDom');
              Xml.LoadXml(QueryLink.Run(sql));
              if Xml.documentElement.childNodes.Length = 1 then
                Result := Xml.documentElement.childNodes.Item[0].getAttribute('ID');
              //пару среди рр не нашли, ищем среди ррр,
              //среди ррр ищем пару только если номер <= 3 символов
              if (Result = '') and (Length(Doc.getAttribute('DOC_NUMBER')) <= 3) then
              begin
                Doc.setAttribute('class', '149');
                sql := 'Select A.Id From Document D' +
                  ' Left Join ExpscheduleRegistry A on A.Document_Id = D.Id' +
                  ' Where D.Budget_Id = ? and D.DocumentClass_Id = ?'
                 +' and D.DispStatus_Id = 16 and A.Extstatus_Id = 1' +
                  ' and LTrim(D.Doc_Number) = ? and D.Doc_Date = ?';
                QueryLink.AddStr(Doc.getAttribute('F_BUDGET_ID'));
                QueryLink.AddStr(Doc.getAttribute('class'));
                QueryLink.AddStr(Doc.getAttribute('DOC_NUMBER'));
                QueryLink.AddDate(StrToDate(Doc.getAttribute('DOC_DATE')));
                if Doc.getAttribute('LS') <> '' then
                begin
                  sql := sql + ' and A.MainOrg_Account = ?' +
                    ' Union Select A.Id From Document D' +
                    ' Left Join ExpscheduleRegistry A on A.Document_Id = D.Id' +
                    ' Where D.Budget_Id = ? and D.DocumentClass_Id = ?'
                   +' and D.DispStatus_Id = 16 and A.Extstatus_Id = 1' +
                    ' and LTrim(D.Doc_Number) = ? and D.Doc_Date = ?' +
                    ' and A.Org_Account = ?';
                  QueryLink.AddStr(Doc.getAttribute('LS'));
                  QueryLink.AddStr(Doc.getAttribute('F_BUDGET_ID'));
                  QueryLink.AddStr(Doc.getAttribute('class'));
                  QueryLink.AddStr(Doc.getAttribute('DOC_NUMBER'));
                  QueryLink.AddDate(StrToDate(Doc.getAttribute('DOC_DATE')));
                  QueryLink.AddStr(Doc.getAttribute('LS'));
                end;
                Xml := CreateOleObject('Microsoft.XmlDom');
                Xml.LoadXml(QueryLink.Run(sql));
                if Xml.documentElement.childNodes.Length = 1 then
                  Result := Xml.documentElement.childNodes.Item[0].getAttribute('ID');
              end;
            end;

          '13': begin
                sql := 'Select A1.Id From Payorder A1' +
                  ' Left Join Document Pd on Pd.Parent_Id = +A1.Document_Id' +
                  ' Where A1.Budget_Id = ? and A1.DocumentClass_Id = ?' +
                  ' and A1.DispStatus_Id = 16  and A1.ExtStatus_Id = 1' +
                  ' and LTrim(A1.Doc_Number) = ? and A1.Doc_Date = ?' +
                  ' and Pd.Id is null';
                QueryLink.addStr(Doc.getAttribute('F_BUDGET_ID'));
                QueryLink.addStr(Doc.getAttribute('class'));
                QueryLink.addStr(Doc.getAttribute('DOC_NUMBER'));
                QueryLink.addDate(StrToDate(Doc.getAttribute('DOC_DATE')));
                if Doc.getAttribute('LS') <> '' then
                begin
                  sql := sql + ' and A1.Pay_Account = ?';
                  QueryLink.AddStr(Doc.getAttribute('LS'));
                end;
                Xml := CreateOleObject('Microsoft.XmlDom');
                Xml.LoadXml(QueryLink.Run(sql));
                if Xml.documentElement.childNodes.Length = 1 then
                  Result := Xml.documentElement.childNodes.Item[0].getAttribute('ID');
              end;

          '11': begin
                // exchange #2531
                // в связи с тем, что есть старый код и есть задача #2531
                // то для #2531 ищем только ЭД 11-го класса, а по старому
                // ищется ЭД 11го и 75го классов.
                // в результате неверно отображается информация в логе, поскольку
                // пишется что ищется ЭД 11го класса, а находится ЭД 75го
                // класса.
                // поэтому, если видим параметр FIMP_PT_ZN_MODE в Doc, то
                // считаем что выполняется доработка #2531 и ищем только
                // ЭД 11го класса с параметром "КАРТА".
                if (VarToStr( Doc.GetAttribute( 'FIMP_PT_ZN_MODE')) = '1')
                  then begin
                    sql := 'Select P.Id, P.DocumentClass_Id From Document D' +
                      ' Join BudgOrder P On P.Document_Id = D.Id' +
                      ' Join OrgAccount A on A.Id = P.OrgAccount_Id' +
                      ' Where D.Budget_Id = ?  And D.DocumentClass_Id=11' +
                      ' And P.DispStatus_Id In (6, 13) And P.Extstatus_Id = 1' +
                      ' And LTrim(P.Doc_Number) = ? And P.Doc_Date = ?' +
                      ' and P.WAYTOGETCASH=1';

                    QueryLink.addStr(Doc.getAttribute('F_BUDGET_ID'));
                    QueryLink.addStr(Doc.getAttribute('DOC_NUMBER'));
                    QueryLink.addDate(StrToDate(Doc.getAttribute('DOC_DATE')));

                    If (Doc.getAttribute('LS') <> '') then begin
                      sql := sql + ' And A.Account_Number = ?';
                      QueryLink.AddStr(Doc.getAttribute('LS'));
                    end;

                    Xml := CreateOleObject('Microsoft.XmlDom');
                    Xml.LoadXml(QueryLink.Run(sql));
                    if Xml.documentElement.childNodes.Length = 1
                      then Result := Xml.documentElement.childNodes.Item[0].getAttribute('ID');
                  end else begin
                    sql := 'Select P.Id, P.DocumentClass_Id From Document D' +
                      ' Join BudgOrder P On P.Document_Id = D.Id' +
                      ' Join OrgAccount A on A.Id = P.OrgAccount_Id' +
                      ' Where D.Budget_Id = ?  And D.DocumentClass_Id in (11, 75)' +
                      ' And P.DispStatus_Id In (6, 13) And P.Extstatus_Id = 1' +
                      ' And LTrim(P.Doc_Number) = ? And P.Doc_Date = ?' +
                      ' And P.Cash_Income = ?'
                      + IfThen(Doc.getAttribute('LS') <> '', ' And A.Account_Number = ?', '');

                    sql := sql + ' Union ' + StringReplace(StringReplace(StringReplace(
                      sql, 'BudgOrder', 'PayReQuest'), '6, ', ''), 'OrgAccount_Id', 'Pay_Acc_Id') + ' And P.TaxPayment = 1';
                    for i := 1 to 2 do
                    begin
                      QueryLink.addStr(Doc.getAttribute('F_BUDGET_ID'));
                      QueryLink.addStr(Doc.getAttribute('DOC_NUMBER'));
                      QueryLink.addDate(StrToDate(Doc.getAttribute('DOC_DATE')));
                      QueryLink.addStr(Doc.getAttribute('CASH'));
                      if Doc.getAttribute('LS') <> '' then
                        QueryLink.AddStr(Doc.getAttribute('LS'));
                    end;
                    Xml := CreateOleObject('Microsoft.XmlDom');
                    Xml.LoadXml(QueryLink.Run(sql));
                    if Xml.documentElement.childNodes.Length = 1 then
                    begin
                      Class_id := Xml.documentElement.childNodes.Item[0].getAttribute('DOCUMENTCLASS_ID');
                      Result := Xml.documentElement.childNodes.Item[0].getAttribute('ID');
                    end;
                  end;
              end;
{
          '11': begin
                sql := 'Select P.Id, P.DocumentClass_Id From Document D' +
                  ' Join BudgOrder P On P.Document_Id = D.Id' +
                  ' Join OrgAccount A on A.Id = P.OrgAccount_Id' +
                  ' Where D.Budget_Id = ?  And D.DocumentClass_Id in (11, 75)' +
                  ' And P.DispStatus_Id In (6, 13) And P.Extstatus_Id = 1' +
                  ' And LTrim(P.Doc_Number) = ? And P.Doc_Date = ?' +
                  ' And P.Cash_Income = ?'
                  + IfThen(Doc.getAttribute('LS') <> '', ' And A.Account_Number = ?', '');

                // exchange #2531
                // искать 11 класс с признаком "карта"
                if (VarToStr( Doc.GetAttribute( 'FIMP_PT_ZN_MODE')) = '1')
                  then sql := sql + ' and P.WAYTOGETCASH=1';

                sql := sql + ' Union ' + StringReplace(StringReplace(StringReplace(
                  sql, 'BudgOrder', 'PayReQuest'), '6, ', ''), 'OrgAccount_Id', 'Pay_Acc_Id') + ' And P.TaxPayment = 1';
                for i := 1 to 2 do
                begin
                  QueryLink.addStr(Doc.getAttribute('F_BUDGET_ID'));
                  QueryLink.addStr(Doc.getAttribute('DOC_NUMBER'));
                  QueryLink.addDate(StrToDate(Doc.getAttribute('DOC_DATE')));
                  QueryLink.addStr(Doc.getAttribute('CASH'));
                  if Doc.getAttribute('LS') <> '' then
                    QueryLink.AddStr(Doc.getAttribute('LS'));
                end;
                Xml := CreateOleObject('Microsoft.XmlDom');
                Xml.LoadXml(QueryLink.Run(sql));
                if Xml.documentElement.childNodes.Length = 1 then
                begin
                  Class_id := Xml.documentElement.childNodes.Item[0].getAttribute('DOCUMENTCLASS_ID');
                  Result := Xml.documentElement.childNodes.Item[0].getAttribute('ID');
                end;
              end;
}
          '118': begin
                sql := ' Select A.Id From Document D' +
                  ' Left Join SrcRequest A on A.Document_Id = D.Id' +
                  ' Left Join OrgAccount Oa on Oa.Id = A.Pay_Acc_Id' +
                  ' Where D.Budget_Id = ? and D.DocumentClass_Id = ?' +
                  ' and D.DispStatus_Id = 6 and A.Extstatus_Id = 1' +
                  ' and LTrim(D.Doc_Number) = ? and D.Doc_Date = ?' +
                  ' and A.Pay_Account = ? and Oa.OrgAcctype_Id = 7';
                QueryLink.AddStr(Doc.getAttribute('F_BUDGET_ID'));
                QueryLink.AddStr(Doc.getAttribute('class'));
                QueryLink.AddStr(Doc.getAttribute('DOC_NUMBER'));
                QueryLink.AddDate(StrToDate(Doc.getAttribute('DOC_DATE')));
                QueryLink.AddStr(Doc.getAttribute('LS'));
                Xml := CreateOleObject('Microsoft.XmlDom');
                Xml.LoadXml(QueryLink.Run(sql));
                if Xml.documentElement.childNodes.Length = 1 then
                  Result := Xml.documentElement.childNodes.Item[0].getAttribute('ID');
              end;

          '114': begin
                // exchange #2677 - поиск ЭД с учетом счета
                // он должен быть равень значению поля "Счет",
                // указанному в блоке "ФО" или "ПБС/АДБ/АИФДБ" основной закладки
                // ЭД "Уведомление об уточнении вида и принадлежности платежа"
                // внешний статус должен быть = выгружен.
                sql := ' Select A.Id From Document D'
                      +' Left Join PayDetail A on A.Document_Id = D.Id'
                      +' Where D.Budget_Id = ? and D.DocumentClass_Id = ?'
                      +' and D.DispStatus_Id = 16 and A.Extstatus_Id = 1'
                      +' and LTrim(D.Doc_Number) = ? and D.Doc_Date = ?'
                      +' and ( A.ADMIN_ACCOUNT=? or A.ORG_ACCOUNT=?)';
                QueryLink.AddStr(Doc.getAttribute('F_BUDGET_ID'));
                QueryLink.AddStr(Doc.getAttribute('class'));
                QueryLink.AddStr(Doc.getAttribute('DOC_NUMBER'));
                QueryLink.AddDate(StrToDate(Doc.getAttribute('DOC_DATE')));
                QueryLink.AddStr( Doc.getAttribute( 'LS'));
                QueryLink.AddStr( Doc.getAttribute( 'LS'));
                Xml := CreateOleObject('Microsoft.XmlDom');
                Xml.LoadXml(QueryLink.Run(sql));

                if Xml.documentElement.childNodes.Length = 1 then
                  Result := Xml.documentElement.childNodes.Item[0].getAttribute('ID');
              end;

          '80': begin
                sql := ' Select A.Id From Document D' +
                  ' Left Join SrcOrder A on A.Document_Id = D.Id' +
                  ' Where D.Budget_Id = ? and D.DocumentClass_Id = ?' +
                  ' and D.DispStatus_Id = 16 and A.ExtStatus_Id = 1' +
                  ' and LTrim(A.Doc_Number) = ? and A.Doc_Date = ?' +
                  ' and A.Admin_Account = ?';
                QueryLink.AddStr(Doc.getAttribute('F_BUDGET_ID'));
                QueryLink.AddStr(Doc.getAttribute('class'));
                QueryLink.AddStr(Doc.getAttribute('DOC_NUMBER'));
                QueryLink.AddDate(StrToDate(Doc.getAttribute('DOC_DATE')));
                QueryLink.AddStr(Doc.getAttribute('LS'));
                Xml := CreateOleObject('Microsoft.XmlDom');
                Xml.LoadXml(QueryLink.Run(sql));
                if Xml.documentElement.childNodes.Length = 1 then
                  Result := Xml.documentElement.childNodes.Item[0].getAttribute('ID');
              end;

          '43': begin
                sql := ' Select A.Id From Document D' +
                  ' Left Join IncOrder A on A.Document_Id = D.Id' +
                  ' Where D.Budget_Id = ? and D.DocumentClass_Id = ?' +
                  ' and D.DispStatus_Id = 16 and A.ExtStatus_Id = 1' +
                  ' and LTrim(A.Doc_Number) = ? and A.Doc_Date = ?' +
                  ' and A.Pay_Account = ?';
                QueryLink.AddStr(Doc.getAttribute('F_BUDGET_ID'));
                QueryLink.AddStr(Doc.getAttribute('class'));
                QueryLink.AddStr(Doc.getAttribute('DOC_NUMBER'));
                QueryLink.AddDate(StrToDate(Doc.getAttribute('DOC_DATE')));
                QueryLink.AddStr(Doc.getAttribute('LS'));
                Xml := CreateOleObject('Microsoft.XmlDom');
                Xml.LoadXml(QueryLink.Run(sql));
                if Xml.documentElement.childNodes.Length = 1 then
                  Result := Xml.documentElement.childNodes.Item[0].getAttribute('ID');
              end;

          // exchange #2531
          // искать 75 класс с признаком "карта"
          // галочку признак получения наличных можно не проверять.
          // галочку "налоги, платежи в бюджет, не проверяем.
          // статус ЭД 6 или 13.
          // старый запрос (если нет FIMP_PT_ZN_MODE) - без изменений.
          '75': begin
                if (VarToStr( Doc.GetAttribute( 'FIMP_PT_ZN_MODE')) = '1')
                  then begin
                    sql := ' Select A.Id From Document D' +
                      ' Left Join PayRequest A on A.Document_Id = D.Id' +
                      ' Where D.Budget_Id = ? and D.DocumentClass_Id = 75' +
                      ' and D.DispStatus_Id in (6,13) and A.ExtStatus_Id = 1' +
                      ' and A.WAYTOGETCASH=1 '
                     +' and LTrim(A.Doc_Number) = ? and A.Doc_Date = ?';
                    QueryLink.AddStr(Doc.getAttribute('F_BUDGET_ID'));
                    QueryLink.AddStr(Doc.getAttribute('DOC_NUMBER'));
                    QueryLink.AddDate(StrToDate(Doc.getAttribute('DOC_DATE')));
                    if Doc.getAttribute('LS') <> '' then begin
                      sql := sql + ' and A.Pay_Account = ?';
                      QueryLink.AddStr(Doc.getAttribute('LS'));
                    end;
                    Xml := CreateOleObject('Microsoft.XmlDom');
                    Xml.LoadXml(QueryLink.Run(sql));
                    if Xml.documentElement.childNodes.Length = 1
                      then Result := Xml.documentElement.childNodes.Item[0].getAttribute('ID');
                  end else begin
                    sql := ' Select A.Id From Document D' +
                      ' Left Join PayRequest A on A.Document_Id = D.Id' +
                      ' Where D.Budget_Id = ? and D.DocumentClass_Id = ?' +
                      ' and D.DispStatus_Id = 13 and A.ExtStatus_Id = 1' +
                      ' and A.TaxPayment = 0 and LTrim(A.Doc_Number) = ? and A.Doc_Date = ?';
                    QueryLink.AddStr(Doc.getAttribute('F_BUDGET_ID'));
                    QueryLink.AddStr(Doc.getAttribute('class'));
                    QueryLink.AddStr(Doc.getAttribute('DOC_NUMBER'));
                    QueryLink.AddDate(StrToDate(Doc.getAttribute('DOC_DATE')));
                    if Doc.getAttribute('LS') <> '' then
                    begin
                      sql := sql + ' and A.Pay_Account = ?';
                      QueryLink.AddStr(Doc.getAttribute('LS'));
                    end;
                    Xml := CreateOleObject('Microsoft.XmlDom');
                    Xml.LoadXml(QueryLink.Run(sql));
                    if Xml.documentElement.childNodes.Length = 1 then
                      Result := Xml.documentElement.childNodes.Item[0].getAttribute('ID');
                  end;
              end;

          // exchange #2462
          // Заявка БУ/АУ на выплату средств на статусе "Готов к исполнению"
          // поле Счет блока Плательщик закладки Документ
          '195': begin
                sql := ' Select A.Id From Document D' +
                  ' Left Join aubucashrequest A on A.Document_Id = D.Id' +
                  ' Where D.Budget_Id = ? and D.DocumentClass_Id = ?' +
                  ' and D.DispStatus_Id = 86 and A.ExtStatus_Id = 1' +
                  ' and LTrim(A.Doc_Number) = ? and A.Doc_Date = ?';

                QueryLink.AddStr(Doc.getAttribute('F_BUDGET_ID'));
                QueryLink.AddStr(Doc.getAttribute('class'));
                QueryLink.AddStr(Doc.getAttribute('DOC_NUMBER'));
                QueryLink.AddDate(StrToDate(Doc.getAttribute('DOC_DATE')));
                if Doc.getAttribute('LS') <> '' then
                begin
                  sql := sql + ' and A.Pay_Account = ?';
                  QueryLink.AddStr(Doc.getAttribute('LS'));

                end;
                // exchange #2928
                // дополнительная проверка в ЭД 195-го класса:
                // "Тип документа в ФК"= "Платежное поручение"

                if ( VarToStr( Doc.GetAttribute('F195_PAYDOC_CODE')) = 'PP')
                  then sql := sql + ' and A.PAYDOC_CODE = '#39'PP'#39;

                Xml := CreateOleObject('Microsoft.XmlDom');

                Xml.LoadXml(QueryLink.Run(sql));
                if Xml.documentElement.childNodes.Length = 1 then
                  Result := Xml.documentElement.childNodes.Item[0].getAttribute('ID');
              end;

          // exchange #2462
          // "Расшифровка сумм неиспользованных средств БУ/АУ" на статусе "отправлен"
          // поле Лицевой счет блока Учреждение закладки Документ
          // необходимо учесть внешний статус =выгружен
          // нужно учесть что для многострочных ЭД поле title_id=id ЭД (шапка)
          // а для однострочных title_id=null.
          '222': begin
                sql := ' Select A.Id From Document D'
                      +' Left Join UNSPENTFUNDSDECODE A on A.Document_Id = D.Id'
                      +' Where D.Budget_Id = ? and D.DocumentClass_Id = ?'
                      +' and (A.title_id is null or A.title_id = A.id)'
                      +' and D.DispStatus_Id = 16 and A.ExtStatus_Id = 1 '
                      +' and LTrim(A.Doc_Number) = ? and A.Doc_Date = ?';
                QueryLink.AddStr(Doc.getAttribute('F_BUDGET_ID'));
                QueryLink.AddStr(Doc.getAttribute('class'));
                QueryLink.AddStr(Doc.getAttribute('DOC_NUMBER'));
                QueryLink.AddDate(StrToDate(Doc.getAttribute('DOC_DATE')));

                if Doc.getAttribute('LS') <> '' then
                begin
                  sql := sql + ' and A.ORG_ACCOUNT = ?';
                  QueryLink.AddStr(Doc.getAttribute('LS'));

                end;
                Xml := CreateOleObject('Microsoft.XmlDom');
                Xml.LoadXml(QueryLink.Run(sql));

                if Xml.documentElement.childNodes.Length = 1 then
                  Result := Xml.documentElement.childNodes.Item[0].getAttribute('ID');
              end;

          // exchange #2531
          // "Расшифровка сумм неиспользованных средств" на статусе "отправлен"
          // поле Лицевой счет блока Учреждение закладки Документ
          // Искать по DATE_OSN = "Дата документа", NOM_OSN = "Номер документа",
          // "Лицевому счету" блока "Учреждение" 5 типа, равного LS_UBP
          // на статусе "Отправлен"
          // необходимо учесть внешний статус =выгружен
          // нужно учесть что для многострочных ЭД поле title_id=id ЭД (шапка)
          // а для однострочных title_id=null.
          '221': begin
                sql :=   ' Select A.Id From Document D'
                        +' Left Join UNSPENTFUNDSDECODE A on A.Document_Id = D.Id'
                        +' join orgaccount oa on oa.id=A.org_acc_id'
                        +' Where D.Budget_Id = ? and D.DocumentClass_Id = ?'
                        +' and (A.title_id is null or A.title_id = A.id)'
                        +' and D.DispStatus_Id = 16 and A.ExtStatus_Id = 1 '
                        +' and LTrim(A.Doc_Number) = ? and A.Doc_Date = ?';
                QueryLink.AddStr(Doc.getAttribute('F_BUDGET_ID'));
                QueryLink.AddStr(Doc.getAttribute('class'));
                QueryLink.AddStr(Doc.getAttribute('DOC_NUMBER'));
                QueryLink.AddDate(StrToDate(Doc.getAttribute('DOC_DATE')));

                if Doc.getAttribute('LS') <> '' then begin
                  sql := sql + ' and A.ORG_ACCOUNT = ? and oa.orgacctype_id=5 ';
                  QueryLink.AddStr(Doc.getAttribute('LS'));

                end;
                Xml := CreateOleObject('Microsoft.XmlDom');
                Xml.LoadXml(QueryLink.Run(sql));

                if Xml.documentElement.childNodes.Length = 1
                  then Result := Xml.documentElement.childNodes.Item[0].getAttribute('ID');
              end;

          // exchange #2462
          // "Заявка БУ/АУ на получение наличных денег" на статусе "Готов к исполнению"
          // поле Счет блока Плательщик закладки Документ
          '194': begin
                sql := ' Select A.Id From Document D' +
                  ' Left Join AUBUCASHREQUEST A on A.Document_Id = D.Id' +
                  ' Where D.Budget_Id = ? and D.DocumentClass_Id = ?' +
                  ' and D.DispStatus_Id = 86 and A.ExtStatus_Id = 1' +
                  ' and LTrim(A.Doc_Number) = ? and A.Doc_Date = ?';
                QueryLink.AddStr( Doc.getAttribute('F_BUDGET_ID'));
                QueryLink.AddStr( Doc.getAttribute('class'));
                QueryLink.AddStr( Doc.getAttribute('DOC_NUMBER'));
                QueryLink.AddDate(StrToDate(Doc.getAttribute('DOC_DATE')));
                if Doc.getAttribute('LS') <> '' then
                begin
                  sql := sql + ' and A.PAY_ACCOUNT = ?';
                  QueryLink.AddStr(Doc.getAttribute('LS'));
                end;
                Xml := CreateOleObject('Microsoft.XmlDom');
                Xml.LoadXml(QueryLink.Run(sql));
                if Xml.documentElement.childNodes.Length = 1 then
                  Result := Xml.documentElement.childNodes.Item[0].getAttribute('ID');
              end;

          // exchange #2462
          // "Справка - уведомление об уточнении операций клиента"
          // на статусе "Готов к исполнению"
          // поле Лицевой счет закладки Документ
          '198': begin
                sql := ' Select A.Id From Document D' +
                  ' Left Join paydetail A on A.Document_Id = D.Id' +
                  ' Where D.Budget_Id = ? and D.DocumentClass_Id = ?' +
                  ' and D.DispStatus_Id = 86 and A.ExtStatus_Id = 1' +
                  ' and LTrim(A.Doc_Number) = ? and A.Doc_Date = ?';
                QueryLink.AddStr(Doc.getAttribute('F_BUDGET_ID'));
                QueryLink.AddStr(Doc.getAttribute('class'));
                QueryLink.AddStr(Doc.getAttribute('DOC_NUMBER'));
                QueryLink.AddDate(StrToDate(Doc.getAttribute('DOC_DATE')));

                if Doc.getAttribute('LS') <> '' then
                begin
                  sql := sql + ' and A.ORG_ACCOUNT = ?';

                  QueryLink.AddStr(Doc.getAttribute('LS'));
                end;

                Xml := CreateOleObject('Microsoft.XmlDom');
                Xml.LoadXml(QueryLink.Run(sql));
                if Xml.documentElement.childNodes.Length = 1 then
                  Result := Xml.documentElement.childNodes.Item[0].getAttribute('ID');
              end;

          { exchange #2530 пп.2 и пп.3
            "Сведения об операциях с целевыми субсидиями"
            искать ЭД на статусе "Утвержден" с внешним статусом "Выгружен",
            Номер равен "PT.NOM_OSN", дата документа равна "PT.DATE_OSN",
            Код УФК, указанный на закладке "Дополнительно" карточки оганизации
            "Учреждения" Сведений для бюджета, в который грузится Протокол,
            равен "TO.KOD_UBP" (а если на закладке "Дополнительно" код не найден,
            сравнивать со значением на закладке "Общая информация"
            в поле "Код организации").
            параметр TO.KOD_UBP передается в атрибуте F12002_TO_KOD_UBP.}
          '12002': begin
                sql := ' Select A.Id From Document D'
                      +' Left Join TARGETGRANTOPER A on A.Document_Id = D.Id'
                      +' join org O on O.id = A.org_id'
                      +' Where a.Budget_Id = ? and D.DocumentClass_Id = 12002'
                      +' and D.DispStatus_Id = 58 and A.ExtStatus_Id = 1'
                      +' and LTrim(A.Doc_Number)=? and A.Doc_Date=?'
                      +' and (exists (select obd.id from orgbudgetdet obd '
                      +'  where obd.org_id=a.org_id and obd.code_fk=?)'
                      +'  or O.name=?)';
                QueryLink.AddStr(Doc.getAttribute('F_BUDGET_ID'));
                QueryLink.AddStr(Doc.getAttribute('DOC_NUMBER'));
                QueryLink.AddDate(StrToDate(Doc.getAttribute('DOC_DATE')));
                QueryLink.AddStr(Doc.getAttribute('F12002_TO_KOD_UBP'));
                QueryLink.AddStr(Doc.getAttribute('F12002_TO_KOD_UBP'));

                Xml := CreateOleObject('Microsoft.XmlDom');
                Xml.LoadXml(QueryLink.Run(sql));

                if Xml.documentElement.childNodes.Length = 1
                  then Result := Xml.documentElement.childNodes.Item[0].getAttribute('ID');
              end;

        end;//case//
        finally
          QueryLink.Free;
      end;

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

end;


//Возвращает пусто, если пара не найдена
function GetLinkId(Doc_Date: TDate; Amount: Double; Doc_Number,
  DocumentClass_Id, BudgetId: String; Ls: String = ''): String;
var
  sql: String;
  Xml: Variant;
  QueryLink: TRunQuery;
begin

    try
      Result := '';
      if Trim(DocumentClass_Id) = '' then Exit;
      QueryLink := TRunQuery.Create;
      try
        case DocumentClass_Id of
          '13': sql := 'Select A1.Id From Payorder A1';
          '43': sql := 'Select A1.Id From Incorder A1';
          '80': sql := 'Select A1.Id From SrcOrder A1';
          '195', '194': sql := 'Select A1.Id From AubucashRequest A1';
        else
          Raise('Функция GetLinkId: не обрабатывается класс документа ' + DocumentClass_Id);
        end;
        sql := sql + ' Left Join Document Pd on Pd.Parent_Id = +A1.Document_Id' +
            ' Where A1.Budget_Id = ? and A1.DocumentClass_Id = ?' +
            ' and A1.DispStatus_Id = 16 and A1.ExtStatus_Id = 1' +
            ' and LTrim(A1.Doc_Number) = ? and A1.Amount = ? and A1.Doc_Date = ?' +
            ' and Pd.Id is null ';
        if DocumentClass_Id in ['194', '195'] then
          sql := StringReplace(StringReplace(sql, 'A1.DispStatus_Id = 16',
            'A1.DispStatus_Id = 86'), ' and Pd.Id is null', ' and A1.Pay_Account = ? and Pd.Id is null');
        QueryLink.addStr(BudgetId);
        QueryLink.addStr(DocumentClass_Id);
        QueryLink.addStr(Doc_Number);
        QueryLink.addCurr(Amount);
        QueryLink.addDate(Doc_Date);
        if DocumentClass_Id in ['194', '195'] then
          QueryLink.addStr(Ls);
        Xml := CreateOleObject('Microsoft.XmlDom');
        Xml.LoadXml(QueryLink.Run(sql));

        if Xml.documentElement.childNodes.Length = 1 then
          Result := Xml.documentElement.childNodes.Item[0].getAttribute('ID');
      finally
        QueryLink.Free;
      end;
      except
        ExceptionLog( 'Сбой QueryWork.GetLinkId');
    end;

end;

//Получает данные организации по ID организации, ID единого счета бюджета и AccStart.
//у организации должен быть открыт л/с УФК, который начинается с AccStart
//Используется для получения данных ФО. Результат в Xml.
//Для 3-ей схемы подменяем AccId на сам счет
function GetOrgByOrgIdAccIdAccStart(OrgId, AccId, AccStart: String; Budget: String = '';
  SpecFund: Boolean = False): Variant;
var
  sql: String;
  Xml: Variant;
begin
  sql := StringReplace(sqlOrgAllRek,
    'From OrgAccount A Left Join Org O on O.Id = A.Org_Id',
    'From Org O Left Join OrgAccount A on A.Org_Id = O.Id');
  Xml := QueryXml('Select * From OrgBudgetDet Where Budget_id =?', [Budget]);
  if Xml.documentElement.childNodes.Length = 1 then
  begin
    if AccStart = '' then
      Result := QueryXml(sql + ' and O.Id = ? and A.Account_Number = ? and obd.Budget_Id = ?',
        [OrgId, AccId, Budget])
    else if SpecFund then
    begin
    if AccStart = '01' then
      Result := QueryXml(sql + ' and A.OrgAccType_Id = 5 and O.Id = ?' +
        ' and A.SpecialFundsAcc_Id = ? and obd.Budget_Id = ? and A.Account_Number Like ?',
        [OrgId, AccId, Budget, AccStart + '%'])
    else
      Result := QueryXml(sql + ' and A.OrgAccType_Id = 9 and O.Id = ?' +
        ' and A.SpecialFundsAcc_Id = ? and obd.Budget_Id = ? and A.Account_Number Like ?',
        [OrgId, AccId, Budget, AccStart + '%']);
    end
    else begin
      if AccStart = '01' then
      Result := QueryXml(sql + ' and A.OrgAccType_Id = 5 and O.Id = ?' +
        ' and A.ExecuterAcc_Id = ? and obd.Budget_Id = ? and A.Account_Number Like ?',
        [OrgId, AccId, Budget, AccStart + '%'])
      else
        Result := QueryXml(sql + ' and A.OrgAccType_Id = 9 and O.Id = ?' +
          ' and A.ExecuterAcc_Id = ? and obd.Budget_Id = ? and A.Account_Number Like ?',
          [OrgId, AccId, Budget, AccStart + '%']);
    end;
  end
  else begin
    sql := StringReplace(StringReplace(sql, ', Obd.Budget_id', ' '),
      ' Left Join OrgBudgetDet Obd on Obd.Org_Id = O.Id' +
      ' Left Join Budget B on B.Id = Obd.Budget_id', ' ');
    if AccStart = '' then
      Result := QueryXml(sql + ' and O.Id = ? and A.Account_Number = ?',
        [OrgId, AccId])
    else
      if SpecFund then
      begin
        if AccStart = '01' then
          Result := QueryXml(sql + ' and A.OrgAccType_Id = 5 and O.Id = ?' +
            ' and A.SpecialFundsAcc_Id = ? and A.Account_Number Like ?',
            [OrgId, AccId, AccStart + '%'])
        else
          Result := QueryXml(sql + ' and A.OrgAccType_Id = 9 and O.Id = ?' +
            ' and A.SpecialFundsAcc_Id = ? and A.Account_Number Like ?',
            [OrgId, AccId, AccStart + '%']);
      end
      else begin
        if AccStart = '01' then
          Result := QueryXml(sql + ' and A.OrgAccType_Id = 5 and O.Id = ?' +
            ' and A.ExecuterAcc_Id = ? and A.Account_Number Like ?',
            [OrgId, AccId, AccStart + '%'])
        else
          Result := QueryXml(sql + ' and A.OrgAccType_Id = 9 and O.Id = ?' +
            ' and A.ExecuterAcc_Id = ? and A.Account_Number Like ?',
            [OrgId, AccId , AccStart + '%']);
      end;
  end;
end;

{~GetLicAcc
//Возвращает ЛС ПБС по Id организации - владельцу.
// aOrgRoles - типы ролей организации Org_Id. если строка пустая,
//              роль организации не учитывается. номера ролей в этом параметре
//              нужно перечислять через апятую без кавычек.
//              например: aOrgRoles='' или aOrgRoles='4,14'.}
function GetLicAcc( Org_Id: String;
                    Acctype: String = '';
                    Account: String = '';
                    aOrgRoles: string = ''): String;
var
  sql: String;
  Xml: Variant;
begin

    try
      Result := '';
      sql := 'Select oa.* From OrgAccount oa'
              + IfThenElseStr(
                    (LENGTH( aOrgRoles) > 0),
                    FORMAT( ' join orgroles ors on ors.org_id=oa.org_id'
                           +' and (ors.orgrole_id in (%s))',
                            [ aOrgRoles]),
                    '')
              +' Where oa.Distributive_Flag = 0 and oa.Org_Id = ? and oa.Close_Date is null';
      if Account = '' then
      begin
        if Acctype <> '' then
          Xml := QueryXml(sql + ' and oa.OrgAccType_Id in ('+ Acctype + ')', [Org_Id])
        else
          Xml := QueryXml(sql + ' and oa.OrgAccType_Id = 1', [Org_Id]);
      end else
        Xml := QueryXml(sql + ' and oa.OrgAccType_Id in ('+ Acctype + ') and oa.Account_Number = ?', [Org_Id, Account]);
      if Xml.documentElement.childNodes.Length = 1 then
        Result := Xml.documentElement.childNodes.item[0].getAttribute('ID')
      else if Xml.selectNodes('.//ROW[@BUDGET_FLAG=1]').Length = 1 then
        Result := Xml.selectSingleNode('.//ROW[@BUDGET_FLAG=1]').getAttribute('ID');
      except
        ExceptionProc( 'GetLicAcc');
    end;

end;

//Возвращает ЛС ПБС без галки бюджетный по Id организации - владельцу
function GetLicAccSs(Org_Id: String; Acctype: String = '';Account: String = ''): String;
var
  sql: String;
  Xml: Variant;
begin
  Result := '';
  sql := 'Select Id' +
    ' From OrgAccount' +
    ' Where OrgAccType_Id = ? and Close_Date is null and Budget_Flag = 0' +
    ' and Distributive_Flag = 0 and Org_ID = ?';
  if Account = '' then
    Xml := QueryXml(sql, [IfThen(Acctype = '', '1', '5'), Org_Id])
  else
    Xml := QueryXml(sql + ' and Account_Number = ?', [IfThen(Acctype = '',
      '1', '5'), Org_Id, Account]);
  if Xml.documentElement.childNodes.Length = 1 then
    Result := Xml.documentElement.childNodes.item[0].getAttribute('ID');
end;

//Возвращает ЛС ПБС без галки бюджетный по Id организации - владельцу
//и Id счета организации ФО
function GetLicAccSs_VB(Org_Id, AccId: String): String;
var
  sql: String;
  Xml: Variant;
begin
  Result := '';
  sql := 'Select Id' +
    ' From OrgAccount' +
    ' Where OrgAccType_Id = 1 and Close_Date is null and Budget_Flag = 0' +
    ' and Distributive_Flag = 0 and Org_ID = ? and KeeperAcc_Id = ?';
    Xml := QueryXml(sql , [Org_Id, AccId]);
  if Xml.documentElement.childNodes.Length = 1 then
    Result := Xml.documentElement.childNodes.item[0].getAttribute('ID');
end;

{~GetEstimateId
//Возвращает ключ бланка расходов (Estimate_ID) по ключу организации (ORG_ID),
//по счету(если он заполнен),если бланк расходов у организации один
//если EstFlag =true, поиск производится только по бланку расходов
//                    с типом "Смета"(1).
//если EstFlag =false, поиск производится только по бланку расходов
//                    с типом "Смета"(1) и "ПНО"(7)}
function GetEstimateId(BudgetId, Org_Id: String; Account: String = '';
  Line: Variant = null; EstFlag: Boolean = False): String;
var
  Xml: Variant;
  sql: String;
  i: Integer;
  Est_Id: String;
  EstValue: array of string;
begin

    try
      Result := '';
      sql := 'Select Id From Estimate Where EstKind_Id in (1, 7) and Actual_Flag = 1' +
        ' and Budget_Id = ? and Org_Id = ?';
      if EstFlag then
        sql := StringReplace(sql, 'EstKind_Id in (1, 7)', 'EstKind_Id = 1');
      Xml := QueryXml(sql, [BudgetId, Org_Id]);

      if Xml.documentElement.childNodes.Length = 1 then
        Result := Xml.documentElement.childNodes.item[0].getAttribute('ID')
      //дополнительный поиск по счету
      else if Account <> '' then
      begin
        sql := sql + ' and Face_Acc = ?';
        Xml := QueryXml(sql, [BudgetId, Org_Id, Account]);
        if Xml.documentElement.childNodes.Length = 1 then
          Result := Xml.documentElement.childNodes.item[0].getAttribute('ID')
      end;
      //Exchange #2012
      if (Xml.documentElement.childNodes.Length > 1) and (not VarIsNull(Line)) then
      begin
        Est_Id := '';
        for i := 0 to Xml.documentElement.childNodes.Length - 1 do
          Est_Id := Est_Id +
            Xml.documentElement.childNodes.Item[i].getAttribute('ID') + ', ';
        Delete(Est_Id, Length(Est_Id) - 1, 2);
        sql := 'Select E.Estimate_Id Id' +
          ' From Expbudget E' +
          ' Where E.Budget_Id = ? and E.Estimate_Id in (' +
              QueryGetParamsFromValue(Est_Id, EstValue) + ') and E.Kfsr_Code = ?' +
          '   and E.Kvr_Code = ? '
          // exchange 3109 - удален косгу
         //+' and E.Kesr_Code = ?'
         +' and E.Kcsr_Code = ?'
         +'   and E.Kadmr_Code = ?' +
          ' Group by E.Estimate_Id';
        Xml := QueryXml(sql, [BudgetId, EstValue, Line.getAttribute('KFSR_CODE'),
          Line.getAttribute('KVR_CODE'),
          //Line.getAttribute('KESR_CODE'),
          Line.getAttribute('KCSR_CODE'), Line.getAttribute('KADMR_CODE')]);
        if Xml.documentElement.childNodes.Length = 1 then
          Result := Xml.documentElement.childNodes.item[0].getAttribute('ID');
      end;
      except
        ExceptionLog( 'Сбой QueryWork.GetEstimateId');
    end;

end;

{~GetEstimateId_3062
//Возвращает ключ бланка расходов (Estimate_ID) по ключу организации (ORG_ID),
//по счету(если он заполнен),если бланк расходов у организации один
//если EstFlag =true, поиск производится только по бланку расходов
//                    с типом "Смета"(1).
//если EstFlag =false, поиск производится только по бланку расходов
//                    с типом "Смета"(1) и "ПНО"(7)
  exchange #3062
  отмена косгу для эд не ау/бу.}
function GetEstimateId_3062( BudgetId, Org_Id: String;
                             Account: String = '';
                             Line: Variant = null;
                             EstFlag: Boolean = False): String;
var
  Xml: Variant;
  sql: String;
  i: Integer;
  Est_Id: String;
  EstValue: array of string;
begin

    try
      Result := '';

      if EstFlag
        then sql :=  ' Select Id From Estimate Where EstKind_Id = 1'
                    +' and Actual_Flag = 1 and Budget_Id = ? and Org_Id = ?'
        else sql :=  ' Select Id From Estimate Where EstKind_Id in (1, 7)'
                    +' and Actual_Flag = 1 and Budget_Id = ? and Org_Id = ?';
      Xml := QueryXml2(sql, [BudgetId, Org_Id]);

      if Xml.childNodes.Length = 1
        then Result := Xml.childNodes.item[0].getAttribute('ID')
        else
          if Account <> '' then begin
            //дополнительный поиск по счету
            Xml := QueryXml2( sql + ' and Face_Acc = ?',
                              [ BudgetId, Org_Id, Account]);
            // exchange #3062
            // поправлено: если со счетом ничего не нашлось, возвращаем
            // результат поиска БР без счета
            if Xml.childNodes.Length <= 0
              then Xml := QueryXml2(sql, [BudgetId, Org_Id]);
          end;

      //Exchange #2012
      if (Xml.childNodes.Length > 1) and (not VarIsNull(Line)) then begin
        Est_Id := '';
        for i := 0 to Xml.childNodes.Length - 1
          do Est_Id := Est_Id + Xml.childNodes.Item[i].getAttribute('ID') + ', ';
        Delete(Est_Id, Length(Est_Id) - 1, 2);

        Est_Id := QueryGetParamsFromValue(Est_Id, EstValue);
        Xml := QueryXml2( ' Select distinct E.Estimate_Id Id From Expbudget E'
                         +' Where E.Budget_Id = ?'
                         +' and E.Estimate_Id in (' + Est_Id + ')'
                         +' and E.Kfsr_Code = ?'
                         +' and E.Kvr_Code = ?'
                         +' and E.Kcsr_Code = ?'
                         +' and E.Kadmr_Code = ?',
                         [ BudgetId,
                           EstValue,
                           Line.getAttribute('KFSR_CODE'),
                           Line.getAttribute('KVR_CODE'),
                           Line.getAttribute('KCSR_CODE'),
                           Line.getAttribute('KADMR_CODE')]);
        if Xml.childNodes.Length = 1
          then Result := Xml.childNodes.item[0].getAttribute('ID');
      end;
      except
        ExceptionLog( 'Сбой GetEstimateId_3062');
    end;

end;

function GetEstimateId_PG(BudgetId, Org_Id: String; Account: String = '';
  Line: Variant = null; EstFlag: Boolean = False): String;
var
  Xml: Variant;
  sql: String;
  i: Integer;
  Est_Id: String;
  EstValue: array of string;
  xPURPOSEFULGRANT_ID: string;
begin

    try
      Result := '';
      sql := 'Select Id From Estimate Where EstKind_Id in (1, 7) and Actual_Flag = 1' +
        ' and Budget_Id = ? and Org_Id = ?';
      if EstFlag then
        sql := StringReplace(sql, 'EstKind_Id in (1, 7)', 'EstKind_Id = 1');
      Xml := QueryXml(sql, [BudgetId, Org_Id]);

      if Xml.documentElement.childNodes.Length = 1 then
        Result := Xml.documentElement.childNodes.item[0].getAttribute('ID')
      //дополнительный поиск по счету
      else if Account <> '' then
      begin
        sql := sql + ' and Face_Acc = ?';
        Xml := QueryXml(sql, [BudgetId, Org_Id, Account]);
        if Xml.documentElement.childNodes.Length = 1 then
          Result := Xml.documentElement.childNodes.item[0].getAttribute('ID')
      end;
      //Exchange #2012
      if (Xml.documentElement.childNodes.Length > 1) and (not VarIsNull(Line)) then
      begin
        Est_Id := '';
        for i := 0 to Xml.documentElement.childNodes.Length - 1 do
          Est_Id := Est_Id +
            Xml.documentElement.childNodes.Item[i].getAttribute('ID') + ', ';
        Delete(Est_Id, Length(Est_Id) - 1, 2);

        // код цели для расходов берем из PURPOSEFULGRANT_ID
        xPURPOSEFULGRANT_ID := GetNodeAttributeEx( Line, 'PURPOSEFULGRANT_ID');
        if (xPURPOSEFULGRANT_ID = '') then begin

          sql := 'Select E.Estimate_Id Id' +
            ' From Expbudget E' +
            ' Where E.Budget_Id = ? and E.Estimate_Id in (' +
                QueryGetParamsFromValue(Est_Id, EstValue) + ') and E.Kfsr_Code = ?' +
            '   and E.Kvr_Code = ? and E.Kesr_Code = ?'
            // exchange #3109 - удален косгу
//            +' and E.Kcsr_Code = ?'
            +'   and E.Kadmr_Code = ?' +
            ' Group by E.Estimate_Id';
          Xml := QueryXml(sql, [BudgetId, EstValue, Line.getAttribute('KFSR_CODE'),
            Line.getAttribute('KVR_CODE'),
            //Line.getAttribute('KESR_CODE'),
            Line.getAttribute('KCSR_CODE'), Line.getAttribute('KADMR_CODE')]);
          if Xml.documentElement.childNodes.Length = 1 then
            Result := Xml.documentElement.childNodes.item[0].getAttribute('ID');
        end else begin

          sql := 'Select E.Estimate_Id Id' +
            ' From Expbudget E' +
            ' Where E.Budget_Id = ? and E.Estimate_Id in (' +
                QueryGetParamsFromValue(Est_Id, EstValue) + ') and E.Kfsr_Code = ?' +
            '   and E.Kvr_Code = ?'
            // exchange #3109 - удален косгу
//            +' and E.Kesr_Code = ?'
            +' and E.Kcsr_Code = ?' +
            '   and E.Kadmr_Code = ?'
           +' and e.PURPOSEFULGRANT_ID=?'
           +' Group by E.Estimate_Id';
          Xml := QueryXml(sql, [BudgetId, EstValue, Line.getAttribute('KFSR_CODE'),
            Line.getAttribute('KVR_CODE'),
            //Line.getAttribute('KESR_CODE'),
            Line.getAttribute('KCSR_CODE'), Line.getAttribute('KADMR_CODE'),
            xPURPOSEFULGRANT_ID]);
          if Xml.documentElement.childNodes.Length = 1 then
            Result := Xml.documentElement.childNodes.item[0].getAttribute('ID');
        end;
      end;
      except
        ExceptionLog( 'Сбой QueryWork.GetEstimateId_PG');
    end;

end;

//Возвращает ключ бланка расходов (Estimate_ID) по ключу организации (ORG_ID),
//по счету(если он заполнен),если бланк расходов у организации один для сс
function GetEstimateIdSs(BudgetId, Org_Id: String; Account: String = ''): String;
var
  Xml: Variant;
  sql: String;
begin
  Result := '';
  sql := 'Select Id From Estimate Where EstKind_Id = 5 and Actual_Flag = 1' +
    ' and Budget_Id = ? and Org_Id = ?';
  Xml := QueryXml(sql, [BudgetId, Org_Id]);
  if Xml.documentElement.childNodes.Length = 1 then
    Result := Xml.documentElement.childNodes.item[0].getAttribute('ID')
  else
    if Account <> '' then
    begin
      sql := sql + ' and Face_Acc = ?';
      Xml := QueryXml(sql, [BudgetId, Org_Id, Account]);
      if Xml.documentElement.childNodes.Length = 1 then
        Result := Xml.documentElement.childNodes.item[0].getAttribute('ID')
      else
        //не смогли найти по 5 типу бланка расходов, далее поиск производится по 1 типу
        Result := GetEstimateId(BudgetId, Org_Id, Account, null, True);
    end
    else
    //не смогли найти по 5 типу бланка расходов, далее поиск производится по 1 типу
     Result := GetEstimateId(BudgetId, Org_Id, Account, null, True);
end;

//Возвращает ID организации распорядителя
procedure getMasterId(BudgetId, EstimateId: String; var MasterEstimateId,
  MasterOrgId: String);
var
  Xml: Variant;
  sql: String;
begin
  MasterOrgId := '';
  MasterEstimateId := '';
  sql := 'Select oMaster.Id Org_Id, eMaster.Id Estimate_Id' +
    ' From estimate E' +
    ' Left Join Estimate eMaster on eMaster.Id = e.Parent_Id' +
    ' Left Join Org oMaster on oMaster.Id = eMaster.Org_Id' +
    ' Where E.Budget_Id = ? and E.Id = ?';
  Xml := QueryXml(sql, [BudgetId, EstimateId]);
  if Xml.documentElement.childNodes.Length = 1 then
  begin
    Xml := Xml.documentElement.childNodes.Item[0];
    MasterOrgId := Xml.getAttribute('ORG_ID');
    MasterEstimateId := Xml.getAttribute('ESTIMATE_ID');
  end;
end;

//Получает Id организации ФО бюджета.
function GetOrgIdByBudgetId(BudgetId: String): String;
begin
  Result := QueryField(sqlBudgId, [BudgetId], 'ORG_ID');
end;

//Возвращает ID счета (лицевой, бюджетный, распорядительный)
function GetMasterAccID(OrgId: String): String;
var
  sql: String;
begin
  sql := sqlAccByOrgId + ' and OrgAcctype_ID = 1 and Budget_Flag = 1' +
    ' and Distributive_Flag = 1';
  Result := QueryField(sql, [OrgId], 'ID');
end;

function GetOrgRef(OpenOrg, NotCloseOrg, OrgWithAcc, paramOrg: Boolean; OrgRoles,
  BudgetId: String = ''; sqlText: Boolean = False): Variant;
var
  sql, sql1: String;
begin
  sql1 := ' Select O.Id, O.Caption, O.Description, O.Kadm_Code, O.Version,' +
        ' O.Close_Date, O.Open_Date, ParentOrg.Name, ParentOrg.Caption Root_Caption,' +
        ' ParentOrg.Description Root_Description, O.Taxcode, O.Kpp, O.Name, O.Caption_Empty' +
        ' From ExpBudget E' +
        ' Left Join Org O on O.Id = E.Recipient_Id' +
        ' Left Join Org ParentOrg on ParentOrg.Id = O.Manager_Id' +
        ' Join Contractor C on C.Org_Id = O.Id';
  if paramOrg then
  begin
    if OrgWithAcc then
    begin
      sql := sql1 + ' Left Join OrgAccount Oa on Oa.Org_Id = O.Id' +
        ' Where O.Id <> 0 and E.Budget_Id = ? and Oa.OrgAcctype_Id in (5, 7, 8, 9)';
      Query.AddStr(BudgetId);
    end
    else begin
      sql := sql1 + ' Where O.Id <> 0 and E.Budget_Id = ?';
      Query.AddStr(BudgetId);
    end;
  end
  // выгрузка из справочника организаций
  else begin
    sql := '';
    if OrgWithAcc then begin
      sql := StringReplace(sqlOrgRefActual, ' Where O.id <> 0',
        ' Left Join OrgAccount Oa on Oa.Org_Id = O.Id' +
        ' Left Join Budget B on B.Org_Id = C.Inspector_Id' +
        ' Where O.Id <> 0 and B.Id = ? and Oa.OrgAcctype_Id in (5, 7, 8, 9)');
      Query.AddStr(BudgetId);
    end;
    if sql = '' then begin
      sql := StringReplace(sqlOrgRefActual, ' Where O.id <> 0',
      ' Left Join Budget B on B.Org_Id = C.Inspector_Id Where O.Id <> 0 and B.Id = ?');
      Query.AddStr(BudgetId);
    end;
    if Trim(OrgRoles) = '' then
      sql := sql + ' and Orl.Id in (0,1,9,10)'
    else
      sql := sql + ' and Orl.Id in (' + OrgRoles + ')';
  end;
  if OpenOrg then
  begin
    sql := sql + ' and ((O.Open_Date is null) or (O.Open_Date <= ?))';
    Query.AddDate(Work_Date);
  end;
  if NotCloseOrg then
  begin
    sql := sql + ' and ((O.Close_Date is null) or (O.Close_Date >= ?))';
    Query.AddDate(Work_Date);
  end;
  sql := sql + ' Group by O.Id, O.Caption, O.Description, O.Kadm_Code, O.Version, ' +
    'O.Close_Date, O.Open_Date, ParentOrg.Name, ParentOrg.Caption, ' +
    'ParentOrg.Description, O.Taxcode, O.Kpp, O.Name, O.Caption_Empty';
  //нужен только текст запроса. используется для выгрузки выбранных организаций
  //из списка.
  if sqlText then
    Result := sql
  else begin
    Result := CreateOleObject('Microsoft.XmlDom');
    Result.LoadXml(Query.Run(sql));
  end;
end;

//Возвращает True, если уровень бюджета = заданному
//BudgetId - Id бюджета, BudgLevel - уровень бюджета на который надо проверить
function IsBudgetLevel(BudgetId, BudgLevel: String): Boolean;
begin
  Result := QueryField(sqlBudgId, [BudgetId], 'BUDGLEVEL_ID') = BudgLevel;
end;

{~GetPermissionRash
//Возвращает данные разрешения и строки разрешения. Либо null в случае если не
//найдено разрешение. В поиске строки участвует КБК расходов
  вызывается при создании эд 11го по ik.zr/zn/zs
  exchange #3062
  убрано косгу из запросов}
function GetPermissionRash(HeadChildDoc, Doc: Variant; Flag: Boolean = False): Variant;
var
  sql: String;
begin

    try
      //Запрос не кэшируется скриптами из-за того что в кэше криво определ. даты.
      //Кривь в ValidDate(parValue) функции QueryStr
      sql := 'Select P.Id, PL.Fundsource_Id, PL.Kdr_Code, PL.Kde_Code, PL.Kdf_Code,' +
        // exchange #3062 - косгу теперь возвращается как результат
        ' PL.Fsr_Id, PL.Recipient_Id, PL.Id PermissionLine_Id, PL.Kesr_Code' +
        ' From Permission P' +
        ' Left Join PermissionLine PL on P.Id = PL.Permission_Id' +
        ' Where P.Budget_Id = ? and P.Org_Id = ? and P.OrgAccount_Id = ?' +
        '  and P.Dispstatus_Id = 1 and P.Start_Date <= ? and P.End_Date >= ?' +
        '  and PL.Estimate_Id = ? and PL.Kfsr_Code = ? and PL.Kcsr_Code = ?' +
        '  and PL.Kvr_Code = ?'
        // exchange #3062
//        +' and PL.Kesr_Code = ?'
        +' and PL.Kadmr_Code = ?';
      Query.AddStr(HeadChildDoc.getAttribute('BUDGET_ID'));
    //Flag используется для загрузки IK файлов
      if Flag then
        Query.AddStr(HeadChildDoc.getAttribute('ORG_ID'))
      else
        Query.AddStr(Doc.parentNode.parentNode.getAttribute('ORG_ID'));
      Query.AddStr(HeadChildDoc.getAttribute('ORGACCOUNT_ID'));
      Query.AddDate(XmlToDateTime(HeadChildDoc.getAttribute('DOC_DATE')));
      Query.AddDate(XmlToDateTime(HeadChildDoc.getAttribute('DOC_DATE')));
      Query.AddStr(HeadChildDoc.getAttribute('ESTIMATE_ID'));
      Query.AddStr(Doc.getAttribute('KFSR_CODE'));
      Query.AddStr(Doc.getAttribute('KCSR_CODE'));
      Query.AddStr(Doc.getAttribute('KVR_CODE'));
     // Query.AddStr(Doc.getAttribute('KESR_CODE'));
      Query.AddStr(Doc.getAttribute('KADMR_CODE'));
      Result := CreateOleObject('Microsoft.XmlDom');
      Result.LoadXml(Query.Run(sql));
      if Result.documentElement.childNodes.Length = 1 then
        Result := Result.documentElement.childNodes.Item[0]
      else
        Result := null;
      except
        ExceptionLog( 'Сбой QueryWork.GetPermissionRash');
    end;

end;

{~GetPermissionDoh
//Возвращает данные разрешения и строки разрешения. Либо null в случае если не
//найдено разрешение. В поиске строки участвует КБК доходов
//если KifFlag = true, в поиске также участвует КИФ строки
  вызывается при создании:
    эд 75го из ik.zr/zv/zs
    доп эд 74го.
  exchange #3062
    удаление косгу для эд не ау/бу}
function GetPermissionDoh(ChildDoc, Doc: Variant; KifFlag: Boolean = False): Variant;
var
  sql: String;
begin

    try
      //Запрос не кэшируется скриптами из-за того что в кэше криво определ. даты.
      //Кривь в ValidDate(parValue) функции QueryStr
      sql := 'Select PL.Id PermissionLine_Id, PL.Fundsource_Id, PL.Estimate_Id,' +
        ' PL.Recipient_Id, PL.Kfsr_Code, PL.Kcsr_Code, PL.Kvr_Code, PL.Kesr_Code,' +
        ' PL.Kadmr_Code, PL.Kdr_Code, PL.Kde_Code, PL.Kdf_Code, PL.Fsr_Id,' +
        ' PL.Receiver_Id, PL.Payer_Id, PL.Territory_Id, PL.Kdd_Code, PL.Fsd_Id,' +
        ' PL.Kdt_Code' +
        ' From Permission P' +
        ' Left Join PermissionLine PL on P.Id = PL.Permission_Id' +
        ' Where P.Budget_Id = ? and P.Org_Id = ? and P.OrgAccount_Id = ?' +
        '  and P.Dispstatus_Id = 1 and P.Start_Date <= ? and P.End_Date >= ?' +
        ' and PL.Kadmd_Code = ? and PL.Kd_Code = ?';
        // exchange #3062
//       +' and PL.Kesd_Code = ? and PL.Kesr_Code <> 999';
      Query.AddStr( GetNodeAttributeEx( ChildDoc, 'BUDGET_ID'));
      Query.AddStr( GetNodeAttributeEx( ChildDoc, 'ORG_ID'));
      Query.AddStr( GetNodeAttributeEx( ChildDoc, 'ORGACCOUNT_ID'));
      Query.AddDate(XmlToDateTime( GetNodeAttributeEx( ChildDoc, 'DOC_DATE')));
      Query.AddDate(XmlToDateTime( GetNodeAttributeEx( ChildDoc, 'DOC_DATE')));
      Query.AddStr( GetNodeAttributeEx( Doc, 'KADMD_CODE'));
      Query.AddStr( GetNodeAttributeEx( Doc, 'KD_CODE'));
      // exchange #3062
//      Query.AddStr( GetNodeAttributeEx( Doc, 'KESD_CODE'));
      if KifFlag then begin
        sql := sql + ' and PL.Fsd_Id =?';
        Query.AddStr( GetNodeAttributeEx( Doc, 'KOD_IST_KBK'));
      end;
      Result := CreateOleObject('Microsoft.XmlDom');
      Result.LoadXml(Query.Run(sql));
      if Result.documentElement.childNodes.Length = 1 then
        Result := Result.documentElement.childNodes.Item[0]
      else
        Result := null;
      except
        ExceptionLog( 'Сбой QueryWork.GetPermissionDoh');
    end;

end;

{~GetPermissionIrk
//Возвращает данные разрешения и строки разрешения. Либо null в случае если не
//найдено разрешение. В поиске строки участвует КБК доходов, организацию и счет
//не учитваем
  вызывается при создании:
    доп эд 74го.
  exchange #3062
    удаление косгу для эд не ау/бу}
function GetPermissionIrk(DocLine: Variant): Variant;
var
  sql: String;
begin

    try
      sql := 'Select P.Id, P.Org_Id, P.OrgAccount_Id, PL.Id PermissionLine_Id,'
            +' PL.Recipient_Id, PL.Kfsr_Code, PL.Kcsr_Code, PL.Kvr_Code, PL.Kesr_Code,'
            +' PL.Kadmr_Code, PL.Kdr_Code, PL.Kde_Code, PL.Kdf_Code, PL.Fsr_Id,'
            +' PL.Receiver_Id, PL.Payer_Id, PL.Territory_Id, PL.Kdd_Code, PL.Fsd_Id,'
            +' PL.Kdt_Code, PL.Fundsource_Id, PL.Estimate_Id'
            +' From Permission P'
            +' Left Join PermissionLine PL on P.Id = PL.Permission_Id'
            +' Where P.Budget_Id = ? and P.Dispstatus_Id = 1 and P.Start_Date <= ?'
            +' and P.End_Date >= ? and PL.Kadmd_Code = ? and PL.Kd_Code = ? ';
      //   +' and PL.Kesd_Code = ?';
      Query.AddStr(DocLine.parentNode.parentNode.getAttribute('F_BUDGET_ID'));
      Query.AddDate(XmlToDateTime(DocLine.parentNode.parentNode.getAttribute('CARRY_DATE')));
      Query.AddDate(XmlToDateTime(DocLine.parentNode.parentNode.getAttribute('CARRY_DATE')));
      Query.AddStr(DocLine.getAttribute('KADMD_CODE'));
      Query.AddStr(DocLine.getAttribute('KD_CODE'));
    //  Query.AddStr(DocLine.getAttribute('KESD_CODE'));
      Result := CreateOleObject('Microsoft.XmlDom');
      Result.LoadXml(Query.Run(sql));
      if Result.documentElement.childNodes.Length = 1
        then Result := Result.documentElement.childNodes.Item[0]
        else Result := null;
      except
        ExceptionProc( 'GetPermissionIrk');
    end;

end;

//Возвращает данные разрешения и строки разрешения. Либо null в случае если не
//найдено разрешение или найдено несколько.
//В поиске строки участвует КБК доходов и Id организации.
function GetPermissionKBR(Line: Variant): Variant;
var
  sql: String;
begin
  sql := 'Select PL.Id PermissionLine_Id, PL.Fundsource_Id, PL.Estimate_Id,' +
    ' PL.Recipient_Id, PL.Kfsr_Code, PL.Kcsr_Code, PL.Kvr_Code, PL.Kesr_Code,' +
    ' PL.Kadmr_Code, PL.Kdr_Code, PL.Kde_Code, PL.Kdf_Code, PL.Fsr_Id,' +
    ' PL.Receiver_Id, PL.Payer_Id, PL.Territory_Id, PL.Kdd_Code, PL.Fsd_Id,' +
    ' PL.Kdt_Code, P.Org_Id, P.OrgAccount_Id' +
    ' From Permission P' +
    ' Left Join PermissionLine PL on P.Id = PL.Permission_Id' +
    ' Where P.Budget_Id = ? and P.Org_Id = ?' +
    '  and P.Dispstatus_Id = 1 and P.Start_Date <= ? and P.End_Date >= ?' +
    ' and PL.Kadmd_Code = ? and PL.Kd_Code = ? and PL.Kesd_Code = ?';
  Query.AddStr(Line.getAttribute('F_BUDGET_ID'));
  Query.AddStr(Line.getAttribute('ORG_ID'));
  Query.AddDate(XmlToDateTime(Line.getAttribute('CARRY_DATE')));
  Query.AddDate(XmlToDateTime(Line.getAttribute('CARRY_DATE')));
  Query.AddStr(Line.getAttribute('KADMD_CODE'));
  Query.AddStr(Line.getAttribute('KD_CODE'));
  Query.AddStr(Line.getAttribute('KESD_CODE'));
  Result := CreateOleObject('Microsoft.XmlDom');
  Result.LoadXml(Query.Run(sql));
  if Result.documentElement.childNodes.Length = 1 then
    Result := Result.documentElement.childNodes.Item[0]
  else
    Result := null;
end;

function Rule1621_getIdPp(Doc: Variant): String;
var
  sql: String;
  Xml: Variant;
begin
  Result := '';
  sql := 'Select P.Id' +
    ' From Document D' +
    ' Left Join Payorder P on P.Document_Id = D.Id' +
    ' Where D.DocumentClass_Id = 13 and D.DispStatus_Id in (10, 16)' +
    ' and D.Budget_Id = ? and D.Doc_Number LIKE ? and D.Doc_Date = ?' +
    ' and D.Amount = ? and P.Pay_Account = ? and P.Anal_Kind = 0';
  Query.AddStr(Doc.getAttribute('F_BUDGET_ID'));
  Query.AddStr('%' + Doc.getAttribute('DOC_NUMBER'));
  Query.AddDate(XmlToDateTime(Doc.getAttribute('DOC_DATE')));
  Query.AddCurr(StrToCurr(Doc.getAttribute('AMOUNT')));
  Query.AddStr(Doc.getAttribute('PAY_ACCOUNT'));
  Xml := CreateOleObject('Microsoft.XmlDom');
  Xml.LoadXml(Query.Run(sql));
  if Xml.documentElement.childNodes.Length = 1 then
    Result := Xml.documentElement.childNodes.Item[0].getAttribute('ID');
end;

//Возвращает True, если счет УФК совпал со счетом УФК для учета спецсредств
//На входе id л/с, для которого делается проверка, и счет УФК из документа
function GetUfkSpec(Id, Account: String): Boolean;
var
  sql: String;
begin
  sql := ' Select O.Account_Number From OrgAccount Oa' +
    ' Left Join OrgAccount O on O.Id = Oa.Specialfundsacc_Id' +
    ' Where Oa.Id = ?';
  Result := QueryField(sql, [Id], 'ACCOUNT_NUMBER') = Account;
end;

//функция проверяет есть ли данный тип операции у данного класса
function OperTypeExists(DocumentClass_Id, OperType_Id: String): Boolean;
var
  Xml: Variant;
  sql: String;
begin
  sql := ' Select O.* From OperType O' +
    ' Left Join ClassOper C on C.OperType_Id = O.Id' +
    ' Where (C.Documentclass_id = ? Or O.Id = 0) And O.Id = ?';
  Xml := QueryXml(sql, [DocumentClass_Id, OperType_Id]);
  Result := Xml.documentElement.childNodes.Length > 0;
end;

// Если стоит значение 8 или 59 в системных параметрах в objectID,
// то функция возвращает true.
// Если true, в Распоряжение на зачисление в доходы подставляется код субсидии в
// зависимости от справочника соответствия КЦ и КВД.
function GetPurposeFulgrantFromSysParam: Boolean;
var
  Xml: Variant;
  sql: String;
begin
  Result := False;
  sql := 'Select S.Param_Value PV From Sysparam S' +
    ' Where Name=''objectID''';
  Xml := CreateOleObject('Microsoft.XmlDom');
  Xml.LoadXml(Query.Run(sql));
  if Xml.documentElement.childNodes.Length = 1 then
  begin
    Xml.loadXml(Xml.documentElement.childNodes.item[0].getAttribute('PV'));
    Result := Xml.documentElement.text in ['8', '59'];
  end;
end;

//Функция возвращает код субсидии по кбк (Exchange #1815)
//Line - строка вставляемого документа
function PurposeFulgrantAutoFill(Line: Variant; BudgetId: String): String;
var
  sql: String;
  Xml: Variant;
begin
  Result := '';
  //расходы
  if Line.getAttribute('ANAL_KIND') = 0 then
  begin
    sql := 'Select P.Id From PurposeFulgrant P' +
      ' Join PurposeFulgrant_ExpKbk PKbk on P.Id = PKbk.Purposefulgrant_Id' +
      ' Where P.ControlFk_Flag = 0 and P.Block_Flag = 0' +
      ' and PKbk.Kcsr_Code = ? and PKbk.Kvr_Code = ? and P.Budget_Id = ?';
    Xml := QueryXml(sql, [Line.getAttribute('KCSR_CODE'),
      Line.getAttribute('KVR_CODE'), BudgetId]);
    if Xml.documentElement.childNodes.Length = 1 then
      Result := Xml.documentElement.childNodes.Item[0].getAttribute('ID');
  end
  //доходы
  else if Line.getAttribute('ANAL_KIND') = 1 then
  begin
    sql := 'Select P.Id From PurposeFulgrant P' +
      ' Where P.Kd_Code = ? and P.Budget_Id = ?';
    Xml := QueryXml(sql, [Line.getAttribute('KD_CODE'), BudgetId]);
    if Xml.documentElement.childNodes.Length = 1 then
      Result := Xml.documentElement.childNodes.Item[0].getAttribute('ID');
  end
  else Result := '';
end;

{~isPurposeFulgrantAutoFill
//Получает данные из сис. параметров, о включении атоподстановки кода субсидии
//Documentclass_Id - класс документа;
//AttrName - наименование атрибута, который надо проверить.
  в АЦК-Ф:
  // DELETED
  // purposefullgrant.controldocs - таблица Контроль заполнения кода цели в документах
  // purposefulgrant.regroll.control - Разрешать создавать "Распоряжение на перечисление средств по заявкам" с разными кодами субсидий
  // purposefulgrant.ignore.unique.code - Проверять уникальность по паре Код и Наименование
  // budgreq.fillpurposefulgrant - Автоматически заполнять код субсидии для импортированных ЗОР
  // purposefulgrant.autofill.classes - таблица Автоподстановка кода в документах }
function isPurposeFulgrantAutoFill(Documentclass_Id, AttrName: String): Boolean;
var
  ParamValues, Node: Variant;
begin
  Result := False;
  ParamValues := GetValueFromSysparam('purposefulgrant.autofill.classes');
  if not VarIsNull(ParamValues) then
  begin
    ParamValues := ParamValues.documentElement;
    Node := ParamValues.selectNodes('//purposefulgrant.autofill.classes[@ID=' +
      Documentclass_Id + ']');
    //Параметр = Да
    if Node.Length <> 0 then // Найдено значение параметра
      Result := Node.Item[0].getAttribute(AttrName) = 1;
  end;
end;

{~GetEstimateType
  Определяем тип бланка расходов из справочника: бюджет/типы бланков расходов}
function GetEstimateType( aEstimateID: string): string;
begin

    try
      Result := QueryField( 'Select EstKind_Id From Estimate Where Id = ?',
                            [ aEstimateID],
                            'ESTKIND_ID');
      except
        ExceptionLog( 'Сбой QueryWork.GetEstimateType');
    end;

end;


{~GetEstimateTypeByPayRequest
  Определяем тип бланка расходов из справочника: бюджет/типы бланков расходов
  для ЭД «Заявка на списание специальных средств с лицевого счета» (75 класс)
  из таблицы PAYREQUEST.}
function GetEstimateTypeByPayRequest( aPayRequestID: string): string;
begin

    try
      Result := QueryField( ' Select e.EstKind_Id From Estimate e'
                           +' join PAYREQUEST P on p.estimate_id = e.id'
                           +' where P.id=?',
                            [ aPayRequestID],
                            'ESTKIND_ID');
      except
        ExceptionLog( 'Сбой QueryWork.GetEstimateTypeByPayRequest');
    end;

end;



{~GetOrgAccountType
  получить тип счета по идентификатору счета aOrgAccountID из справочника
  "счета организаций".}
function GetOrgAccountType( aOrgAccountID: string): string;
begin

    try
      Result := QueryField( 'Select orgacctype_id from orgaccount Where Id = ?',
                            [ aOrgAccountID],
                            'ORGACCTYPE_ID');
      except
        ExceptionLog( 'Сбой QueryWork.GetOrgAccountType');
    end;

end;


//Определяем тип бланка расходов
// справочник/бюджет/типы бланков расходов
function GetEstimateKind( aEstimateID: string): string;
begin
  Result := 'EST_KIND' + GetEstimateType( aEstimateID);
end;


{~DirectionAutoFillEx
  Функция выполняет поиск расходное обязательство по кбк.
  как результат возвращается DIRECTION_ID или пустая строка.
  exchange 3116
  доработка сводилась к поиску РО без косгу - на стороне АЦК-Ф.
  так же проверяется результат:
    если в результате РО не нашлось, результат будет =пустая строка.}
function DirectionAutoFillEx(BudgetId: String; aLine: Variant): String;
var
  Xml: Variant;
begin

    try
      Xml := CreateOleObject('Microsoft.XmlDom');
      Xml := Xml.appendChild(Xml.createElement('PL_DIRECTION'));
      Xml.setAttribute('action', 'fill_direction_editing');
      // оставляем замену в шапке на случай, если опять изменят алгоритм
      Xml.setAttribute('ANAL_KIND', 2); //2-расходы
      Xml.setAttribute('IS_REPLACE', 1); //всегда 1-замена(вставка)
      Xml := Xml.appendChild(aLine.cloneNode(True));
      Xml.setAttribute('BUDGET_ID', BudgetId);
      Xml.setAttribute('ANAL_KIND', 2); //2-расходы

      // exchange #3116
      // если косгу в строке пустое или отсутствует, заполняем его нулями
      if StrIsEmpty( GetNodeAttributeEx( Xml, 'KESR_CODE'))
        then Xml.setAttribute( 'KESR_CODE', KesCodeFormat( '0', BudgetId));

      Xml := Xml.ownerDocument;

      Xml.loadXml(ExecXml(Xml.xml));

      // exchange #3116 - проверка результата
      if (Xml.documentElement.childNodes.Length <= 0)
        then Result := ''
        else Result := Xml.documentElement.childNodes.Item[0].getAttribute('DIRECTION_ID');
      except
        ExceptionProc( 'DirectionAutoFillEx');
    end;

end;

{~DirectionAutoFill
  Функция возвращает расходное обязательство по кбк (Exchange #1917)
  Line - строка вставляемого документа (расходы)}
function DirectionAutoFill(Line: Variant; BudgetId: String): String;
begin

    try
      if Line.getAttribute('ANAL_KIND') = 0
        then Result := DirectionAutoFillEx( BudgetId, Line)
        else Result := '';
      except
        ExceptionProc( 'DirectionAutoFill');
    end;

end;
{var
  sql: String;
  Xml: Variant;
begin
  Result := '';
  //расходы
  if Line.getAttribute('ANAL_KIND') = 0 then
  begin
    Xml := CreateOleObject('Microsoft.XmlDom');
    Xml := Xml.appendChild(Xml.createElement('PL_DIRECTION'));
    Xml.setAttribute('action', 'fill_direction_editing');
    // оставляем замену в шапке на случай, если опять изменят алгоритм
    Xml.setAttribute('ANAL_KIND', 2); //2-расходы
    Xml.setAttribute('IS_REPLACE', 1); //всегда 1-замена(вставка)
    Xml := Xml.appendChild(Line.cloneNode(True));
    Xml.setAttribute('BUDGET_ID', BudgetId);
    Xml.setAttribute('ANAL_KIND', 2); //2-расходы
    Xml := Xml.ownerDocument;
    Xml.loadXml(ExecXml(Xml.xml));
    Result := Xml.documentElement.childNodes.Item[0].getAttribute('DIRECTION_ID');
  end
  else Result := '';
end;}

function isDirectionAutoFill(budgetId: String): Boolean;
begin
  Result := (SysParamBudgetValue(budgetId, 'direction.common', 'direction.autofill.in.imported.docs') = '1');
end;

{~GetValueFromSysparam
  Функция чтения значений из системных параметров
    XmlFlag - флаг получения данных в xml
              =True - данные в блобе в виде xml;
              =false - получение результата в виде строки.}
function GetValueFromSysparam(param_name: String; XmlFlag: Boolean = True): Variant;
var
  Xml: Variant;
begin

    try
      Result := null;
      Xml := CreateOleObject('Microsoft.XmlDom');
      Xml := Xml.appendChild(Xml.createElement('EXCH_UTILS_PROCESSOR'));
      Xml.setAttribute('action', 'get_sys_param_value');
      Xml := Xml.appendChild(Xml.ownerDocument.createElement('SYSPARAM'));
      Xml.setAttribute('NAME', param_name);
      Xml := Xml.ownerDocument;
      
      Xml.loadXml(ExecXml(Xml.xml));
      
      Xml := Xml.getElementsBytagName('PARAM_VALUE');
      if Xml.length = 1 then
      begin
        if XmlFlag
          then
            begin
              Result := CreateOleObject('Microsoft.XmlDom');
              Result.loadXml(Xml.items[0].firstChild.data);

            end
          else
            begin
              Result := Xml.items[0].firstChild.data;

            end;
      end;

      except
        ExceptionProc( 'QueryWork.GetValueFromSysparam');
    end;

end;

//Функция проверяет установлено ли значение в системном параметре. Используется
//только для бинарных параметров, т.е. значения которых не хранятся в xml,
//а хранятся как 0 - выключен, 1-включен
function IsSysparamOn(param_name: String): Boolean;
begin
  try
    
    Result := GetValueFromSysparam(param_name, False) = 1;
    
    except
      ExceptionLog( 'Сбой скрипта: "QueryWork.IsSysparamOn".');
  end;
end;

function GetQueueKind: String;
var
  sql, Tmp: String;
  Xml: Variant;
begin

    try
      Result := '';
      sql := ' Select Param_Value PV From Sysparam Where Name = ''queuerule.48_0''';
      Xml := QueryXml(sql);
      Tmp := Xml.documentElement.childNodes.Item[0].getAttribute('PV');
      if Copy(Tmp, Length(Tmp), 1) <> '' then
        Result := Copy(Tmp, Length(Tmp), 1)
      else
        Result := '';
      except
        ExceptionLog( 'Сбой QueryWork.GetQueueKind');
    end;

end;

//получаем данные первичной организации
function GetPrimaryOrg(Id: String; var Org: Variant): Boolean;
var
  sql: String;
begin
  Result := False;
  if Trim(Id) = '' then Exit;
  sql := ' Select PO.Id Recipient_id' +
    ' From Org O' +
    ' Left Join Org PO on O.Primary_Id = PO.Id' +
    ' Where O.Id = ? and PO.Close_Date is null';
  Org := QueryXml(sql, [Id]);
  if (Org.documentElement.childNodes.Length = 1)
    and (Org.documentElement.childNodes.Item[0].getAttribute('RECIPIENT_ID') <> '') then
  begin
    Org := Org.documentElement.childNodes.Item[0];
    Result := True;
  end;
end;

//Возвращает должность и фамилию ответственных лиц организации
procedure GetResperson(OrgId, Appointment: String; var Fio, Dolzhnost: String);
var
  sql: String;
  Xml: Variant;
begin
  Fio := '';
  Dolzhnost := '';
  sql := 'Select Rp.Fio, A.Caption from RespPerson Rp' +
    ' Left Join Appointment A on Rp.Appointment_Id = A.Id' +
    ' Where Rp.Org_Id = ? and A.id = ?';
  Xml := QueryXml(sql, [OrgId, Appointment]);
  if Xml.documentElement.childNodes.Length = 1 then
  begin
    Xml := Xml.documentElement.childNodes.Item[0];
    Fio := Xml.getAttribute('FIO');
    Dolzhnost := Xml.getAttribute('CAPTION');
  end;
end;

{~GetRespersonEx
  Возвращает должность и фамилию ответственных лиц организации.
  изменение по #2549 для #2492 (ZN из IK)
  особенность в том, что если найдено несколько записей, то выполняется
  повторно запрос, но с флагом актуальности.
  это связано с тем, что Эксч не может выбрать ответственное лицо, когда
  у организации  две должности с типом "Руководитель", актуальность не
  проверяется.}
procedure GetRespersonEx(OrgId, Appointment: String; var Fio, Dolzhnost: String);
var
  Xml: Variant;
  n: integer;
begin
  Fio := '';
  Dolzhnost := '';
  Xml := QueryXml(  'Select Rp.Fio, A.Caption from RespPerson Rp'
                   +' Left Join Appointment A on Rp.Appointment_Id = A.Id'
                   +' Where Rp.Org_Id = ? and A.id = ?',
                    [OrgId, Appointment]);
  n := Xml.documentElement.childNodes.Length;
  if (n = 1) then begin
    Xml := Xml.documentElement.childNodes.Item[0];
    Fio := Xml.getAttribute('FIO');
    Dolzhnost := Xml.getAttribute('CAPTION');
  end else
    if (n > 1) then begin
      Xml := QueryXml(  'Select Rp.Fio, A.Caption from RespPerson Rp'
                       +' Left Join Appointment A on Rp.Appointment_Id = A.Id'
                       +' Where Rp.Org_Id = ? and A.id = ? and Rp.ACTUAL_FLAG=1',
                        [OrgId, Appointment]);
      if (Xml.documentElement.childNodes.Length = 1) then begin
        Xml := Xml.documentElement.childNodes.Item[0];
        Fio := Xml.getAttribute('FIO');
        Dolzhnost := Xml.getAttribute('CAPTION');
      end;
    end;
end;

function RespersonFromSys(vid_id, Budget: String): Variant;
var
  Xml: Variant;
begin
  Result := CreateOleObject('Microsoft.XmlDom');
  with Result.appendChild(Result.createElement('RESPONSIBLEPERSONS')) do
  begin
    setattribute('action', 'read');
    setattribute('vid', vid_id);
    setattribute('budget', Budget);
  end;
  Result.loadXml(ExecXml(Result.xml));
end;

//Получает данные организации по бюджету и коду организации
//по умолчанию поиск производится по полю Код ФО вкладки "Дополнительно",
//если CodeFKFlag - True, то поиск производится по полю Код ФК
// Результат в Xml.
function GetOrgByCode(Budget, Code: String; CodeFKFlag: Boolean = False): Variant;
var
  sql: String;
  Xml: Variant;
begin
  sql := ' Select Org_Id Id From OrgBudgetDet Where Budget_id = ? and Code_Fo like ?';
  if CodeFKFlag then
    sql := StringReplace(sql, 'and Code_Fo', 'and Code_Fk');
  Xml := QueryXml(sql, [Budget, '%' + Code]);
  if Xml.documentElement.childNodes.Length = 1 then
    Result := Xml
  else begin
    sql := sqlOrgNotClose + ' and Name like ?';
    Result := QueryXml(sql, ['%' + Code]);
  end;
end;

//Получает данные организации по коду организации и полному наменованию
// Результат в Xml.
function GetOrgByCodeAndDescription(Code, Description: String): Variant;
var
  sql: String;
  Xml: Variant;
begin
  sql := ' Select Id Id From Org Where Name = ? and Description = ?';
  Xml := QueryXml(sql, [Code, Description]);
  Result := Xml;
end;


//Получает данные организации по бюджету и коду организации в ФК
//с учетом ролей. Результат в Xml.
function GetOrgByCodeAndBudget(Budget, Code: String; OrgRole: String = ''): Variant;
var
  sql: String;
  Xml: Variant;
begin
  sql := ' Select distinct O.* From Org O' +
    ' Left Join OrgBudgetDet Obd on Obd.Org_Id = O.Id' +
    ' Left Join OrgRoles Ors on O.Id = Ors.Org_Id' +
    ' Where O.Close_Date is null And Obd.Code_Fk = ? and Obd.Budget_Id = ?' +
    IfThen(OrgRole <> '', ' and Ors.OrgRole_Id not in (' + OrgRole + ')', '');
  Xml := QueryXml(sql, [Code, Budget]);
  if Xml.documentElement.childNodes.Length = 1 then
    Result := Xml
  else begin
    sql := ' Select distinct O.* From Org O' +
      ' Join OrgRoles Ors on O.Id = Ors.Org_Id' +
      ' Where O.Close_Date is null And O.Name = ?' +
      IfThen(OrgRole <> '', ' and Ors.OrgRole_Id not in (' + OrgRole + ')', '');
    Result := QueryXml(sql, [Code]);
  end;
end;


//получает код организации по Id, сначало смотрим закладку "дополнительно"
//в справочнике организаций, если заполнено возвращаем поле "Код ФК",
//иначе значение поля "Код организации".
function GetOrgCodeByOrgIdBugetId(Id, BudgetId: String): String;
var
  sql: String;
  Xml: Variant;
begin
  Result := '';
  if Id = '' then
    Exit;
  if BudgetId <> '' then
  begin
    sql := 'Select Code_Fk From OrgBudgetDet Where Org_Id = ? and Budget_Id = ?';
    Xml := QueryXml(sql, [Id, BudgetId]);
    if Xml.documentElement.childNodes.Length <> 1 then
      Result := QueryField(sqlOrgId, [Id], 'NAME')
    else
      Result := Xml.documentElement.childNodes.Item[0].getAttribute('CODE_FK');
  end else
    Result := QueryField(sqlOrgId, [Id], 'NAME');
end;

//получает код организации по Id счета
function GetOrgCodeByAccIdBugetId(Acc_Id, BudgetId: String): String;
var
  sql: String;
  Xml: Variant;
begin
  Result := '';
  if Acc_Id = '' then Exit;
  Xml := QueryXml(sqlOrgByOrgAccountId, [Acc_Id]);
  if Xml.documentElement.childNodes.Length = 1 then
  begin
    Xml := Xml.documentElement.childNodes.Item[0];
    Result := GetOrgCodeByOrgIdBugetId(Xml.getAttribute('ID'), BudgetId);
  end;
end;

//получаем Id бюджета по коду организации и году, сначала ищем по ФО в карточке
//бюджета. Если не нашли, смотрим по "Организации, осуществляющей исполнение"
//(код организации смотрим на закладке "дополнительно" в справочнике организаций,
//если заполнено берем поле "Код ФК",иначе значение поля "Код организации").
function GetBudgetByCodeOrg(OrgCode, FinYear: String): String;
var
  sql: String;
  Xml: Variant;
begin

    try
      Result := '';
      sql := ' Select distinct Obd.Budget_Id' +
        ' From OrgBudgetDet Obd' +
        ' Join Budget B on Obd.Budget_Id = B.Id and Obd.Org_Id = B.Org_Id' +
        ' Where Obd.Code_Fk = ? and B.FinYear = ?';
      Xml := QueryXml(sql, [OrgCode, FinYear]);
      if Xml.documentElement.childNodes.Length <> 1 then
      begin
        sql := ' Select B.Id Budget_Id From Budget B' +
          ' Left Join Org O on O.Id = B.Org_Id' +
          ' Where O.Name = ? and B.FinYear = ?';
        Xml := QueryXml(sql, [OrgCode, FinYear]);
        if Xml.documentElement.childNodes.Length = 1 then
          Result := Xml.documentElement.childNodes.Item[0].getAttribute('BUDGET_ID')
        else begin
          sql := ' Select distinct Obd.Budget_Id' +
            ' From OrgBudgetDet Obd' +
            ' Join Budget B on Obd.Budget_Id = B.Id and Obd.Org_Id = B.Executor_Id' +
            ' Where Obd.Code_Fk = ? and B.FinYear = ?';
          Xml := QueryXml(sql, [OrgCode, FinYear]);
          if Xml.documentElement.childNodes.Length = 1 then
            Result := Xml.documentElement.childNodes.Item[0].getAttribute('BUDGET_ID')
          else begin
            sql := ' Select B.Id Budget_Id From Budget B' +
              ' Left Join Org O on O.Id = B.Executor_Id' +
              ' Where O.Name = ? and B.FinYear = ?';
            Xml := QueryXml(sql, [OrgCode, FinYear]);
            if Xml.documentElement.childNodes.Length = 1 then
              Result := Xml.documentElement.childNodes.Item[0].getAttribute('BUDGET_ID');
          end;
        end;
      end
      else
        Result := Xml.documentElement.childNodes.Item[0].getAttribute('BUDGET_ID');
      except
        ExceptionProc( 'GetBudgetByCodeOrg');
    end;

end;


{~GetDocIdforIK
   поиск документа для которого искать пару для загрузки IK-файла

   возвращает
     Xml: получает Id, версии и бюджет

   exchange #2914
    убрана проверка внешнего статуса при поиске эд.

   exchange #2961
    неправильно возвращались результаты поиска многострочных эд.
    необходимо добавить проверку: (id=title_id or title_id is null).
    реально добавлено только в запрос поиска эд 11го, хотя в других запросах
    проблема аналогичная.
    в запросы поиска остальных эд строки добавлены но закомичены.
    так сделано поскольку пока проблем с другими эд не возникало.

    distinct можно было оставить - это не дает результата для конструкции
    такого запроса. проверено было на таком запросе:
        select distinct d.id
        From Document D
        Join BudgOrder B On B.Document_Id = D.Id ...
    вернется один id, поскольку и шапка и строки ссылаются на одну и ту же
    запись в document. }
function GetDocIdforIK(Doc: Variant): Variant;
var
  sql: String;
  QueryLink: TRunQuery;
  xCash: string;
begin

    try
      Result := CreateOleObject('Microsoft.XmlDom');
      QueryLink := TRunQuery.Create;
      try

        case Doc.getAttribute('class') of
          '11': begin
              { exchange #2492
                если поле CASH = 2, это доработка по #2492, означает поиск ЭД 11го
                класса по пп.4.1:
                  Если «Тип КБК плательщика» (TYPE_KBK) первой строки = 10,
                  производим поиск ЭД в списке ЭД системы (по Номеру заявки,
                  Дате заявки, Итоговая сумма (общая сумма всех строк ЭД «Заявка
                  на оплату расходов»), Номеру лицевого счета (IK.LS_UBP – Счет
                  финансирования), с признаком «Карта» на статусе Исполнение.
                в данном случае все совпадает со старым запросом, кроме поля CASH.
                его всегда подставляем =1}
              if (Doc.getAttribute('CASH') = '2')
                then xCash := '1'
                else xCash := Doc.getAttribute('CASH');

              sql := 'Select B.Id, B.Version, B.Guid_Fk' +
                ' From Document D' +
                ' Join BudgOrder B On B.Document_Id = D.Id' +
                ' Join OrgAccount A on A.Id = B.OrgAccount_Id' +
                ' Where D.Budget_Id = ?  And D.DocumentClass_Id = 11'
                // exchange #2961 - возаращает только шапку эд
               +' and (B.id=B.title_id or B.title_id is null)'
                // exchange #2914 - убрана проверка внешнего статуса
               +' And B.DispStatus_Id = 13 '+//And B.Extstatus_Id = 1' +
                ' And LTrim(B.Doc_Number) = ? And B.Doc_Date = ?' +
                ' And D.Amount = ? And B.Cash_Income = ?' +
                ' And A.Account_Number = ? And A.OrgAccType_Id = 5';
              QueryLink.addStr(Doc.getAttribute('F_BUDGET_ID'));
              QueryLink.addStr(Doc.getAttribute('DOC_NUMBER'));
              QueryLink.addDate(StrToDate(Doc.getAttribute('DOC_DATE')));
              QueryLink.addCurr(StrToCurr(Doc.getAttribute('AMOUNT')));
              QueryLink.addStr( xCash);
              QueryLink.addStr(Doc.getAttribute('LS'));
              Result.LoadXml(QueryLink.Run(sql));
    
            end;

          '75': begin
              sql := 'Select P.Id, P.Version, P.Guid_Fk' +
                ' From Document D' +
                ' Join PayReQuest P On P.Document_Id = D.Id' +
                ' Join OrgAccount A on A.Id = P.Pay_Acc_Id' +
                ' Where D.Budget_Id = ?  And D.DocumentClass_Id = 75' +
                // exchange #2961 - возаращает только шапку эд
//               +' and (P.id=P.title_id or P.title_id is null)'
                // exchange #2914 - убрана проверка внешнего статуса
                ' And P.DispStatus_Id = 13 '+//And P.Extstatus_Id = 1' +
                ' And LTrim(P.Doc_Number) = ? And P.Doc_Date = ?' +
                ' And D.Amount = ? And P.Cash_Income = ? And A.Account_Number = ?' +
                ' And A.OrgAccType_Id = 5 And P.TaxPayment = ?';
              QueryLink.addStr(Doc.getAttribute('F_BUDGET_ID'));
              QueryLink.addStr(Doc.getAttribute('DOC_NUMBER'));
              QueryLink.addDate(StrToDate(Doc.getAttribute('DOC_DATE')));
              QueryLink.addCurr(StrToCurr(Doc.getAttribute('AMOUNT')));
              QueryLink.addStr(Doc.getAttribute('CASH'));
              QueryLink.addStr(Doc.getAttribute('LS'));
              QueryLink.addStr(Doc.getAttribute('TAXPAYMENT'));
              Result.LoadXml(QueryLink.Run(sql));
            end;

          '118': begin
              sql := ' Select S.Id, S.Version, S.Guid_Fk' +
                ' From Document D' +
                ' Left Join SrcRequest S on S.Document_Id = D.Id' +
                ' Left Join OrgAccount A on A.Id = S.Pay_Acc_Id' +
                ' Where D.Budget_Id = ? And D.DocumentClass_Id = 118' +
                // exchange #2961 - возаращает только шапку эд
               //+' and (S.id=S.title_id or S.title_id is null)'
                // exchange #2914 - убрана проверка внешнего статуса
                ' And D.DispStatus_Id = 6 '+//And S.Extstatus_Id = 1' +
                ' And LTrim(D.Doc_Number) = ? And D.Doc_Date = ?' +
                ' And D.Amount = ? And S.Pay_Account = ? And A.OrgAcctype_Id = 7';
              QueryLink.AddStr(Doc.getAttribute('F_BUDGET_ID'));
              QueryLink.AddStr(Doc.getAttribute('DOC_NUMBER'));
              QueryLink.AddDate(StrToDate(Doc.getAttribute('DOC_DATE')));
              QueryLink.addCurr(StrToCurr(Doc.getAttribute('AMOUNT')));
              QueryLink.AddStr(Doc.getAttribute('LS'));
              Result.LoadXml(QueryLink.Run(sql));
            end;

          '114': begin
              sql := ' Select P.Id, P.Version, P.Guid_Fk' +
                ' From Document D' +
                ' Left Join PayDetail P on P.Document_Id = D.Id' +
                ' Where D.Budget_Id = ? And D.DocumentClass_Id = ?' +
                // exchange #2914 - убрана проверка внешнего статуса
                ' And D.DispStatus_Id = 16 '+//And P.Extstatus_Id = 1' +
                ' And LTrim(D.Doc_Number) = ? And D.Doc_Date = ? And P.Org_Account = ?';
              QueryLink.AddStr(Doc.getAttribute('F_BUDGET_ID'));
              QueryLink.AddStr(Doc.getAttribute('class'));
              QueryLink.AddStr(Doc.getAttribute('DOC_NUMBER'));
              QueryLink.AddDate(StrToDate(Doc.getAttribute('DOC_DATE')));
              QueryLink.AddStr(Doc.getAttribute('LS'));
              Result.LoadXml(QueryLink.Run(sql));
            end;

          '80': begin
              sql := ' Select S.Id, S.Version, S.Guid_Fk' +
                ' From Document D' +
                ' Left Join SrcOrder S on S.Document_Id = D.Id' +
                ' Left Join OrgAccount A on A.Id = S.Admin_Account_Id' +
                ' Where D.Budget_Id = ? And D.DocumentClass_Id = 80' +
                // exchange #2961 - возаращает только шапку эд
//               +' and (S.id=S.title_id or S.title_id is null)'
                // exchange #2914 - убрана проверка внешнего статуса
                ' And D.DispStatus_Id = 16 '+//And S.ExtStatus_Id = 1' +
                ' And LTrim(D.Doc_Number) = ? And D.Doc_Date = ?' +
                ' And D.Amount = ? And S.Admin_Account = ? And A.OrgAcctype_Id = 7';
              QueryLink.AddStr(Doc.getAttribute('F_BUDGET_ID'));
              QueryLink.AddStr(Doc.getAttribute('DOC_NUMBER'));
              QueryLink.AddDate(StrToDate(Doc.getAttribute('DOC_DATE')));
              QueryLink.addCurr(StrToCurr(Doc.getAttribute('AMOUNT')));
              QueryLink.AddStr(Doc.getAttribute('LS'));
              Result.LoadXml(QueryLink.Run(sql));
            end;

          '43': begin
              sql := ' Select I.Id, I.Version, I.Guid_Fk' +
                ' From Document D' +
                ' Left Join IncOrder I on I.Document_Id = D.Id' +
                ' Left Join OrgAccount A on A.Id = I.Pay_Acc_Id' +
                ' Where D.Budget_Id = ? And D.DocumentClass_Id = 43' +
                // exchange #2961 - возаращает только шапку эд
//               +' and (I.id=I.title_id or I.title_id is null)'
                // exchange #2914 - убрана проверка внешнего статуса
                ' And D.DispStatus_Id = 16 '+//And I.ExtStatus_Id = 1' +
                ' And LTrim(D.Doc_Number) = ? And D.Doc_Date = ?' +
                ' And D.Amount = ? And I.Pay_Account = ? And A.OrgAcctype_Id = 5';
              QueryLink.AddStr(Doc.getAttribute('F_BUDGET_ID'));
              QueryLink.AddStr(Doc.getAttribute('DOC_NUMBER'));
              QueryLink.AddDate(StrToDate(Doc.getAttribute('DOC_DATE')));
              QueryLink.AddCurr(StrToCurr(Doc.getAttribute('AMOUNT')));
              QueryLink.AddStr(Doc.getAttribute('LS'));
              Result.LoadXml(QueryLink.Run(sql));
            end;

(*
          // exchange #2600
          // добавлено для обработки раздела IK.UK п.2.7
          // 2.7.1.	В списке ЭД 198 класса по Номеру, Дате, Лицевому счету
          // (на основной закладке) ищем документ на статусе
          // «Готов к исполнению» внешний статус «Выгружен».
          '198': begin
              sql := ' Select I.Id, I.Version, I.Guid_Fk' +
                ' From Document D' +
                ' Left Join PayDetail I on I.Document_Id = D.Id' +
                ' Where D.Budget_Id = ? And D.DocumentClass_Id = 198' +
                ' And D.DispStatus_Id = 86 And I.ExtStatus_Id = 1' +
                ' And LTrim(D.Doc_Number) = ? And D.Doc_Date = ?' +
                ' And I.ORG_ACCOUNT = ?';
              QueryLink.AddStr(Doc.getAttribute('F_BUDGET_ID'));
              QueryLink.AddStr(Doc.getAttribute('DOC_NUMBER'));
              QueryLink.AddDate(StrToDate(Doc.getAttribute('DOC_DATE')));
              QueryLink.AddStr(Doc.getAttribute('LS'));
              Result.LoadXml(QueryLink.Run(sql));
            end;
*)

        end;//case//
        finally
          QueryLink.Free;
      end;
      except
        ExceptionLog( 'Сбой QueryWork.GetDocIdforIK');
    end;

end;

//Получает данные незакрытой организации из справочника по КАДМ. Результат в Xml.
function GetOrgByKadm(Code, Role: String): Variant;
var
  sql: String;
begin
  sql := ' Select distinct O.* From Org O' +
    ' Left Join OrgRoles Rs on Rs.Org_Id = O.Id' +
    ' Where O.Close_Date is null and Rs.OrgRole_Id in (' + Role + ')' +
    ' and O.Kadm_Code = ?';
  Result := QueryXml(sql, [Code]);
end;

{~GetAccountsByBudget
  Получаем единый счет бюджета и счет по учету спецсредств по бюджету}
function GetAccountsByBudget(Budget: String): Variant;
begin

    try
      //получаем данные по счетам по Id бюджета
      Result := QueryXml(
                    ' Select A.Id, A.Account_Number, O.Id Org_Id,'
                   +' O.Taxcode Org_Taxcode,'
                   +' O.Kpp Org_Kpp, O.Description Org_Description,'
                   +' Aspec.Id Spec_Acc_Id, Aspec.Account_Number Spec_account,'
                   +' Ospec.Id Spec_Id, Ospec.Taxcode Spec_Taxcode,'
                   +' Ospec.Kpp Spec_Kpp, Ospec.Description Spec_Description'
                   +' From Budget B'
                   +' Left Join OrgAccount A on A.Id = B.Common_Acc_Id'
                   +' Left Join OrgAccount Aspec on Aspec.Id = B.Sf_Account_Id'
                   +' Left Join Org O on O.Id = A.Org_Id'
                   +' Left Join Org Ospec on Ospec.Id = Aspec.Org_id'
                   +' Where B.Id = ?',
                    [Budget]);
      except
        ExceptionLog( 'Сбой GetAccountsByBudget');
    end;

end;


{~GetLinkIdforIK
  поиск ЭД для линковки с ЭД 5/24го классов.

  ищуются классы: 11,75,118,80 + 195,194

  Exchange #2380
   для поиска слинкованных документов оставить только гуид, бюджет.
   сумму, номер и дату документа исключить.

  exchange #2600
    2.3.3.	При обработке блока BDPD и создании по нему приложения
    к выписке дебетового учитывать документ на статусе «Готов к исполнению»
    при поиске документа для линковки  без учета внешнего статуса.
    Поиск производить по первым 36 символам GUID Приложения к выписке
    дебетового, искать документ с таким же GUID_FK.
    пп. 2.4.3 - поиск 194го класса по тому же критерию.
    в результате нужно добавить поиск ЭД 195го (по ZR) и 194-го (по ZS)
    классов на 86м статусе.

  exchange #2749
    убрана проверка на отсутствие связки с родительским документом
    у всех классов ЭД.

  exchange #2961
    поскольку после доработки ацк-ф в строки эд стали тиражироваться некоторые
    поля из шапки, то доработаны запросы чтобы возвращались только шапки эд}
function GetLinkIdforIK(Doc_Date: TDate; Amount: Double; Doc_Number,
  BudgetId, guid: String): Variant;

  procedure DoSubSQL_Exch2380_( var aSQL: string;
                                aQueryLink: TRunQuery;
                                aDispStatus_Id, aDocumentClass_Id: string;
                                aTable, aField: string);
  var
    xSubQuery: string;
  begin
  
      try
        xSubQuery := FORMAT( ' Select A1.Id, A1.DocumentClass_Id'
//                            +' From Budgorder A1'
                            +' From ' + aTable + ' A1'
                            +' Join Document Pd on Pd.Id = A1.Document_Id'
                            +' Where A1.Budget_Id = ? '
                            // exchange #2961 - возвращает только шапку эд
                            // нужно учесть, что при добавлении новых эд
                            // в поиск, нужно убедится что у них есть
                            // поле title_id
                            +' and (a1.title_id=a1.id or a1.title_id is null)'
                            +' and A1.DocumentClass_Id = %s'
                            +' and A1.DispStatus_Id = %s '
                            +' and A1.' + aField + ' = ? ',
                            // exchange #2749
                            // убрана проверка на отсутствие связки с
                            // родительским документом у всех классов ЭД.
//                            +' and Pd.parent_Id is null',
                             [ aDocumentClass_Id,
                               aDispStatus_Id]);
        aQueryLink.addStr(BudgetId);
        aQueryLink.addStr(guid);
        if (LENGTH( aSQL) > 0)
          then aSQL := aSQL + ' union ' + xSubQuery
          else aSQL := aSQL + ' ' + xSubQuery;
  
        except
          ExceptionLog( 'Сбой QueryWork.GetLinkIdforIK');
      end;
  
  end;

var
//  i: Integer;
  sql: String;
  Xml: Variant;
  QueryLink: TRunQuery;
begin

    try
      QueryLink := TRunQuery.Create;
      try
        sql := '';
        // Exchange #2380
        // для поиска слинкованных документов оставить только гуид, бюджет.
        // сумму, номер и дату документа исключить.
        DoSubSQL_Exch2380_( sql, QueryLink, '13', '11', 'Budgorder', 'Guid_Fk');
        DoSubSQL_Exch2380_( sql, QueryLink, '13', '75', 'PayRequest', 'Guid_Fk');
        DoSubSQL_Exch2380_( sql, QueryLink, '6', '118', 'SrcRequest', 'Guid_Fk');
        DoSubSQL_Exch2380_( sql, QueryLink, '16', '80', 'SrcOrder', 'Guid_Fk');
        // exchange #2600
        // 2.3.3.	При обработке блока BDPD и создании по нему приложения
        // к выписке дебетового учитывать документ на статусе «Готов к исполнению»
        // при поиске документа для линковки  без учета внешнего статуса.
        // Поиск производить по первым 36 символам GUID Приложения к выписке
        // дебетового, искать документ с таким же GUID_FK.
        // пп. 2.4.3 - поиск 194го класса по тому же критерию.
        // в результате нужно добавить поиск ЭД 195го (по ZR) и 194-го (по ZS)
        // классов на 86м статусе.
        DoSubSQL_Exch2380_( sql, QueryLink, '86', '195', 'AUBUCASHREQUEST',
                                                              'Foreign_key');
        DoSubSQL_Exch2380_( sql, QueryLink, '86', '194', 'AUBUCASHREQUEST',
                                                              'Foreign_key');
(*
        sql := ' Select A1.Id, A1.DocumentClass_Id From Budgorder A1' +
          ' Join Document Pd on Pd.Id = +A1.Document_Id' +
          ' Where A1.Budget_Id = ? and A1.DocumentClass_Id = 11' +
          ' and A1.DispStatus_Id = 13 and LTrim(A1.Doc_Number) = ?' +
          ' and A1.Amount = ? and A1.Doc_Date = ?' +
          ' and A1.Guid_Fk = ? and Pd.parent_Id is null' +

          ' Union Select A1.Id, A1.DocumentClass_Id From PayRequest A1' +
          ' Join Document Pd on Pd.Id = +A1.Document_Id' +
          ' Where A1.Budget_Id = ? and A1.DocumentClass_Id = 75' +
          ' and A1.DispStatus_Id = 13 and LTrim(A1.Doc_Number) = ?' +
          ' and A1.Amount = ? and A1.Doc_Date = ?' +
          ' and A1.Guid_Fk = ? and Pd.parent_Id is null' +

          ' Union Select A1.Id, A1.DocumentClass_Id From SrcRequest A1' +
          ' Join Document Pd on Pd.Id = +A1.Document_Id' +
          ' Where A1.Budget_Id = ? and A1.DocumentClass_Id = 118' +
          ' and A1.DispStatus_Id = 6 and LTrim(A1.Doc_Number) = ?' +
          ' and A1.Amount = ? and A1.Doc_Date = ?' +
          ' and A1.Guid_Fk = ? and Pd.parent_Id is null' +

          ' Union Select A1.Id, A1.DocumentClass_Id From SrcOrder A1' +
          ' Join Document Pd on Pd.Id = +A1.Document_Id' +
          ' Where A1.Budget_Id = ? and A1.DocumentClass_Id = 80' +
          ' and A1.DispStatus_Id = 16 and LTrim(A1.Doc_Number) = ?' +
          ' and A1.Amount = ? and A1.Doc_Date = ?' +
          ' and A1.Guid_Fk = ? and Pd.parent_Id is null';
        for i := 1 to 4 do
        begin
          QueryLink.addStr(BudgetId);
          QueryLink.addStr(Doc_Number);
          QueryLink.addCurr(Amount);
          QueryLink.addDate(Doc_Date);
          QueryLink.addStr(guid);
        end;
        *)

        Xml := CreateOleObject('Microsoft.XmlDom');
        Xml.LoadXml(QueryLink.Run(sql));

        if Xml.documentElement.childNodes.Length = 1
          then Result := Xml.documentElement.childNodes.Item[0]
          else Result := null;
      finally
        QueryLink.Free;
      end;
      except
        ExceptionLog( 'Сбой QueryWork.GetLinkIdforIK');
    end;

end;

//получает реквизиты организации по коду и бюджету.
//Сначало ищем организацию по коду ФК на закладке дополнительно,
//если однозначно не нашли то по полю name таблицы org. Результат в Xml.
function GetOrgByBudgIdCode(BudgetId, Code: String): Variant;
var
  sql: String;
begin
  sql := 'Select O.* ' +
    ' From Org O' +
    ' Join OrgBudgetDet Obd on Obd.Org_Id = O.Id' +
    ' Where Obd.Code_Fk = ? and Obd.Budget_Id = ?';
  Result := QueryXml(sql, [Code, BudgetId]);
  if Result.documentElement.childNodes.Length <> 1 then
    Result := QueryXml(sqlOrgName, [Code]);
end;

//проверка есть ли у данного счета актуальное разрешение
//true - нет разрешения
function CheckAccOnPermission(DocXml: Variant): Boolean;
var
  sql: String;
  Xml: Variant;
begin

    try
  Result := False;
  //Запрос не кэшируется скриптами из-за того что в кэше криво определ. даты.
  //Кривь в ValidDate(parValue) функции QueryStr
  sql := 'Select * From Permission' +
    ' Where Budget_Id = ? and OrgAccount_Id = ?' +
    '  and Dispstatus_Id = 1 and Start_Date <= ? and End_Date >= ?';
  Query.AddStr(DocXml.getAttribute('BUDGET_ID'));
  Query.AddStr(DocXml.getAttribute('ORGACCOUNT_ID'));
  Query.AddDate(XmlToDateTime(DocXml.getAttribute('DOC_DATE')));
  Query.AddDate(XmlToDateTime(DocXml.getAttribute('DOC_DATE')));
  Xml := CreateOleObject('Microsoft.XmlDom');
  Xml.LoadXml(Query.Run(sql));
  Result := Xml.documentElement.childNodes.Length <> 1;
      except
        ExceptionProc( 'CheckAccOnPermission');
    end;


end;

{~GetAccFromSettingsOfAccount
  Возвращает реквизиты незакрытого счета, вместе с ТОФК, УФК и прочее
  по Id бюджета из закладки бюхгалтерия - основной бюджетный счет. Результат в Xml}
function GetAccFromSettingsOfAccount(BudgetId: String): Variant;
var
  sql: String;
begin

    try
  sql :=  ' Select A.Id Id, A.account_number,  Ofk.Description Ofk_Description,' +
    ' Ufk.Description Ufk_Description, UfkAcc.Account_Number Ufk_Account_Number,' +
    ' UfkAcc.Id Ufk_Acc_Id, Ufkb.Bic Bic, Ufkb.Description B_Name, Ufkb.CorAccount CorAccount,' +
    ' SpecAcc.Account_Number SpecUfk_Account_Number, SpecAcc.Id SpecUfk_Acc_Id,' +
    ' Specb.Bic SpecBic, Specb.Description Specb_Name, Specb.CorAccount SpecCorAccount,' +
    ' Bk.Bic Bic_Bank, Bk.Description Name_Bank, Bk.CorAccount CorAccount_Bank' +
    ' From OrgAccount A' +
    ' Left Join Org Ofk on Ofk.Id = A.Keeper_Id' +
    ' Left Join Org Ufk on Ufk.Id = A.Executer_Id' +
    ' Left Join OrgAccount UfkAcc on UfkAcc.Id = A.ExecuterAcc_Id' +
    ' Left Join Bank Ufkb on Ufkb.Id = UfkAcc.Bank_Id' +
    ' Left Join OrgAccount SpecAcc on SpecAcc.Id = A.SpecialFundsAcc_Id' +
    ' Left Join Bank Specb on Specb.Id = SpecAcc.Bank_Id' +
    ' Left Join Budget B on B.MainAcc_Id = A.Id' +
    ' Left Join Bank Bk on Bk.Id = A.Bank_Id' +
    ' Where A.Close_Date is null and B.Id = ?';
  Result := QueryXml(sql, [BudgetId]);
      except
        ExceptionProc( 'GetAccFromSettingsOfAccount');
    end;

end;

{~GetAccFromAccID
  Возвращает реквизиты указанного счета, вместе с ТОФК, УФК и прочее по Id счета.
  Результат в виде Xml.
  Операцию Result.documentElement.childNodes.Item[0] выполнять не нужно !
  запрос выполнен по аналогии с функцией GetAccFromSettingsOfAccount.}
function GetAccFromAccID( aAccID: String): Variant;
begin

    try
      Result := QueryXml(
                  ' Select A.Id Id, A.account_number,  Ofk.Description Ofk_Description,'
                 +' Ufk.Description Ufk_Description, UfkAcc.Account_Number Ufk_Account_Number,'
                 +' UfkAcc.Id Ufk_Acc_Id, Ufkb.Bic Bic, Ufkb.Description B_Name, Ufkb.CorAccount CorAccount,'
                 +' SpecAcc.Account_Number SpecUfk_Account_Number, SpecAcc.Id SpecUfk_Acc_Id,'
                 +' Specb.Bic SpecBic, Specb.Description Specb_Name, Specb.CorAccount SpecCorAccount,'
                 +' Bk.Bic Bic_Bank, Bk.Description Name_Bank, Bk.CorAccount CorAccount_Bank'
                 +' From OrgAccount A'
                 +' Left Join Org Ofk on Ofk.Id = A.Keeper_Id'
                 +' Left Join Org Ufk on Ufk.Id = A.Executer_Id'
                 +' Left Join OrgAccount UfkAcc on UfkAcc.Id = A.ExecuterAcc_Id'
                 +' Left Join Bank Ufkb on Ufkb.Id = UfkAcc.Bank_Id'
                 +' Left Join OrgAccount SpecAcc on SpecAcc.Id = A.SpecialFundsAcc_Id'
                 +' Left Join Bank Specb on Specb.Id = SpecAcc.Bank_Id'
                 +' Left Join Budget B on B.MainAcc_Id = A.Id'
                 +' Left Join Bank Bk on Bk.Id = A.Bank_Id'
                 +' Where A.Id = ?',
                  [ aAccId]);
      Result := Result.documentElement.childNodes.Item[0];
      except
        ExceptionLog( 'Сбой QueryWork.GetAccFromAccID');
    end;

end;

//Проверяет актуальность организации. True - актуальная
function IsActual(OrgId, BudgetId: String): Boolean;
var
  Xml: Variant;
  sql: String;
begin
  sql :=  ' Select distinct O.* From Org O' +
    ' Join Contractor C on C.Org_Id = O.Id' +
    ' Left Join Budget B on B.Org_Id = C.Inspector_Id' +
    ' Where O.Id = ? and B.Id = ?';
  Xml := QueryXml(sql, [Orgid, BudgetId], False);
  Result := Xml.documentElement.childNodes.Length = 1;
end;

//используется для поиска 114 класса для блока SPD файлов IK, SP и SF
function GetAnswerUf(Doc, DocXml: Variant): Variant;
var
  sql: String;
  QueryLink: TRunQuery;
begin

    try
QueryLink := TRunQuery.Create;
try
  sql := ' Select A.* From Document D' +
    ' Left Join PayDetail A on A.Document_Id = D.Id' +
    ' Where D.Budget_Id = ? and D.DispStatus_Id in (10, 16)' +
    ' and D.DocumentClass_Id = 114 and LTrim(D.Doc_Number) = ?' +
    ' and D.Doc_Date = ?';
  QueryLink.AddStr(Doc.getAttribute('F_BUDGET_ID'));
  QueryLink.AddStr(DocXml.getAttribute('NUM_DOC'));
  QueryLink.AddDate(StrToDate(DocXml.getAttribute('DATE_DOC')));
  Result := CreateOleObject('Microsoft.XmlDom');
  Result.LoadXml(QueryLink.Run(sql));
finally
  QueryLink.Free;
end;
      except
        ExceptionProc( 'GetAnswerUf');
    end;

end;

//Определяет загружался ли документ с указанным GUID
//True - загружался.
function IsLoaded_SPIK( BudgetId, Guid: String;
                        DPFlag: Boolean = False): Boolean;
var
//  i, j: Integer;
  Xml: Variant;
  sql: String;
  QueryLink: TRunQuery;
begin

    try
      QueryLink := TRunQuery.Create;
      //  j := 4;
      try
        sql := 'Select Id, Document_Id From SrcOrder' +
          ' Where Budget_Id = ? and DocumentClass_Id = 39 and Guid_Fk = ?' +
          ' and DispStatus_Id > -1' +
          ' Union Select Id, Document_Id From IncOrder' +
          ' Where Budget_Id = ? and DocumentClass_Id = 35 and Guid_Fk = ?' +
          ' and DispStatus_Id > -1';
        QueryLink.addStr(BudgetId);
        QueryLink.addStr(Guid);
        QueryLink.addStr(BudgetId);
        QueryLink.addStr(Guid);

        if not DPFlag then begin
          sql := sql + ' Union Select Id, Document_Id From ExpOrder' +
            ' Where Budget_Id = ? and DocumentClass_Id = 40 and Guid_Fk = ?' +
            ' and DispStatus_Id > -1' +
            ' Union Select Id, Document_Id From Payorder' +
            ' Where Budget_Id = ? and DocumentClass_Id = 24 and Foreign_Key = ?' +
            ' and DispStatus_Id > -1';
          QueryLink.addStr(BudgetId);
          QueryLink.addStr(Guid);
          QueryLink.addStr(BudgetId);
          QueryLink.addStr(Guid);
        end;
      {
        if DPFlag then j := 2;
        for i := 1 to j do
        begin
          QueryLink.addStr(BudgetId);
          QueryLink.addStr(Guid);
        end;}
        Xml := CreateOleObject('Microsoft.XmlDom');
        Xml.LoadXml(QueryLink.Run(sql));

        Result := Xml.documentElement.childNodes.Length > 0;
      finally
        QueryLink.Free;
      end;
      except
        ExceptionProc( 'IsLoaded_SPIK');
    end;

end;

function CheckDispStatusDoc(Id, DocumentClass_Id: String): Boolean;
begin

    try

      case DocumentClass_Id of
        '11':
          Result := QueryField(' Select * From Budgorder Where Id =?', [Id], 'DISPSTATUS_ID') = '13';
        '80':
          Result := QueryField(' Select * From SrcOrder Where Id =?', [Id], 'DISPSTATUS_ID') = '16';
        '75':
          Result := QueryField(' Select * From PayReQuest Where Id =?', [Id], 'DISPSTATUS_ID') = '13';
        '118':
          Result := QueryField(' Select * From SrcReQuest Where Id =?', [Id], 'DISPSTATUS_ID') = '6';
        else
          Raise('CheckDispStatusDoc: Класс ' + DocumentClass_Id + ' не поддерживается.');
      end;
      except
        ExceptionProc( 'CheckDispStatusDoc');
    end;

end;

// Возвращает организацию-владельца счета, реквизиты счета "Счет для наличных"
// по Id счета, для которого производится поиск счета для наличных
function GetOrgByCashAcc(AccountId: String): Variant;
var
  sql: String;
begin
  Result := '';
  sql := ' Select O.Taxcode, O.Kpp, O.Id Org_Id, O.Description Org_Description,' +
    ' KeeperAcc.Id Account_Id, KeeperAcc.Account_Number,' +
    ' B.Id Bank_Id, B.Bic, B.Coraccount, B.Description Bank_Description' +
    ' From OrgAccount Oa' +
    ' Join OrgAccount KeeperAcc on Oa.Keeperacc_Id = KeeperAcc.Id' +
    ' Join Org O on O.Id = KeeperAcc.Org_Id' +
    ' Join Bank B On B.Id = KeeperAcc.Bank_Id' +
    ' Where Oa.Id = ?';
  Result := QueryXml(sql, [AccountId]);
end;

//Возвращает реквизиты незакрытого счета, вместе с ТОФК, УФК и прочее
//по Id счета. Результат в Xml
function GetAccAllRekByAccId(Acc_Id: String; IncomeAcc: Boolean = False): Variant;
var
  sql: String;
begin

    try
  if IncomeAcc then begin
  sql := 'Select A.Id Id, Ofk.Description Ofk_Description,' +
    ' Ufk.Description Ufk_Description, UfkAcc.Account_Number Ufk_Account_Number,' +
    ' UfkAcc.Id Ufk_Acc_Id, Ufkb.Bic Bic, Ufkb.Description B_Name, Ufkb.CorAccount CorAccount,' +
    ' SpecAcc.Account_Number SpecUfk_Account_Number, SpecAcc.Id SpecUfk_Acc_Id, ' +
    ' Specb.Bic SpecBic, Specb.Description Specb_Name, Specb.CorAccount SpecCorAccount, ' +
    ' IncAcc.Account_Number IncUfk_Account_Number, IncAcc.Id IncUfk_Acc_Id, Incb.Bic IncBic,' +
    ' Incb.Description Incb_Name, Incb.CorAccount IncCorAccount, IncUfkf.Name IncUfk_Filial_Name' +
    ' From OrgAccount A' +
    ' Left Join Org Ofk on Ofk.Id = A.Keeper_Id' +
    ' Left Join Org Ufk on Ufk.Id = A.Executer_Id' +
    ' Left Join OrgAccount UfkAcc on UfkAcc.Id = A.ExecuterAcc_Id' +
    ' Left Join Bank Ufkb on Ufkb.Id = UfkAcc.Bank_Id' +
    ' Left Join OrgAccount SpecAcc on SpecAcc.Id = A.SpecialFundsAcc_Id' +
    ' Left Join Bank Specb on Specb.Id = SpecAcc.Bank_Id' +
    ' Left Join OrgAccount IncAcc on IncAcc.Id = A.IncomeAcc_Id' +
    ' Left Join Bank Incb on Incb.Id = IncAcc.Bank_Id' +
    ' Left Join Filial IncUfkf on IncUfkf.Id = IncAcc.Filial_Id' +
    ' Where A.Close_Date is null and A.Id = ?';
    Result := QueryXml(sql, [Acc_Id]);
  end else
    Result := QueryXml(sqlAccAllRek + ' and A.Id = ?', [Acc_Id]);
      except
        ExceptionProc( 'GetAccAllRekByAccId');
    end;

end;

//получает реквизиты организации по ИНН + КПП + код + бюджет + роль организации.
//сначала поиск производится по коду ФК на закладке дополнительно, потом по общей
//пока используется для IK файлов, но возможна дальнейшая модификация для всех
//Результат в Xml.
//RoleFlag - не имеет указанных ролей
function GetOrgByTaxKppBudgIdCode(Taxcode, Kpp, BudgetId, Code: String;
  Role: String = ''; RoleFlag: Boolean = False): Variant;
var
  sql: String;
  NoKpp: Boolean;
begin
  sql := 'Select distinct O.*' +
    ' From Org O' +
    ' Join OrgBudgetDet Obd on Obd.Org_Id = O.Id' +
    ' Join Contractor C on C.Org_Id = O.Id' +
    ' Left Join OrgRoles Ors on O.Id = Ors.Org_Id' +
    ' Left Join Budget B on B.Org_Id = C.Inspector_Id' +
    ' Where O.Close_Date is null and O.Taxcode = ?' +
    ' and Obd.Code_Fk = ? and Obd.Budget_Id = ?';
  if Trim(Role) <> '' then
    sql := sql + ' and Ors.OrgRole_Id in (' + Role + ')';
  if RoleFlag then
    sql := StringReplace(sql, 'Ors.OrgRole_Id in', 'Ors.OrgRole_Id not in');
  NoKpp := Trim(StringReplace(Kpp, '0', '')) = '';
  if NoKpp then
    Result := QueryXml(sql, [Taxcode, Code, BudgetId])
  else begin
    sql := sql + ' and O.Kpp = ?';
    Result := QueryXml(sql, [Taxcode, Code, BudgetId, Kpp]);
  end;
  if Result.documentElement.childNodes.Length <> 1 then
  begin
    sql := ' Select distinct O.*' +
      ' From Org O' +
      ' Join Contractor C on C.Org_Id = O.Id' +
      ' Left Join OrgRoles Ors on O.Id = Ors.Org_Id' +
      ' Left Join Budget B on B.Org_Id = C.Inspector_Id' +
      ' Where O.Close_Date is null and O.Taxcode = ?' +
      ' and O.Name = ? and B.Id = ?';
    if Trim(Role) <> '' then
      sql := sql + ' and Ors.OrgRole_Id in (' + Role + ')';
    if RoleFlag then
      sql := StringReplace(sql, 'Ors.OrgRole_Id in', 'Ors.OrgRole_Id not in');
    if NoKpp then
      Result := QueryXml(sql, [Taxcode, Code, BudgetId])
    else begin
      sql := sql + ' and O.Kpp = ?';
      Result := QueryXml(sql, [Taxcode, Code, BudgetId, Kpp]);
    end;
  end;
  //Exchange#2059
  //не нашли однозначно организацию по основному КПП, продолжаем поиск по дополнительному КПП
  if (AzkCompareVersion('2.25.0.14') > 0) and (not NoKpp)
    and (Result.documentElement.childNodes.Length <> 1) then
  begin
    sql := 'Select distinct O.*' +
      ' From Org O' +
      ' Join OrgKpp Ok on O.Id = Ok.Org_Id' +
      ' Join OrgBudgetDet Obd on Obd.Org_Id = O.Id' +
      ' Join Contractor C on C.Org_Id = O.Id' +
      ' Left Join OrgRoles Ors on O.Id = Ors.Org_Id' +
      ' Left Join Budget B on B.Org_Id = C.Inspector_Id' +
      ' Where O.Close_Date is null and O.Taxcode = ?' +
      ' and Obd.Code_Fk = ? and Obd.Budget_Id = ? and Ok.Kpp = ?';
    if Trim(Role) <> '' then
      sql := sql + ' and Ors.OrgRole_Id in (' + Role + ')';
    if RoleFlag then
      sql := StringReplace(sql, 'Ors.OrgRole_Id in', 'Ors.OrgRole_Id not in');
    Result := QueryXml(sql, [Taxcode, Code, BudgetId, Kpp]);
    if Result.documentElement.childNodes.Length <> 1 then
    begin
      sql := ' Select distinct O.*' +
        ' From Org O' +
        ' Join OrgKpp Ok on O.Id = Ok.Org_Id' +
        ' Join Contractor C on C.Org_Id = O.Id' +
        ' Left Join OrgRoles Ors on O.Id = Ors.Org_Id' +
        '  Left Join Budget B on B.Org_Id = C.Inspector_Id' +
        ' Where O.Close_Date is null and O.Taxcode = ?' +
        ' and O.Name = ? and B.Id = ? and Ok.Kpp = ?';
      if Trim(Role) <> '' then
        sql := sql + ' and Ors.OrgRole_Id in (' + Role + ')';
      if RoleFlag then
        sql := StringReplace(sql, 'Ors.OrgRole_Id in', 'Ors.OrgRole_Id not in');
      Result := QueryXml(sql, [Taxcode, Code, BudgetId, Kpp]);
    end;
  end;
end;

{~isDirectionControl
  Получает данные из сис. параметров, о включении контроля заполнения
  расходного обязательства
  Documentclass_Id - класс документа;
  AttrName - наименование атрибута, который надо проверить.}
function isDirectionControl(Documentclass_Id, AttrName: String): String;
var
  ParamValues, Node: Variant;
begin

    try
      Result := '';
      if (VarIsNull( Documentclass_Id)) or (AttrName = '') then EXIT;
      if (VarIsNull( AttrName)) or (AttrName = '') then EXIT;

      ParamValues := GetValueFromSysparam('direction.required.classes.new');
      if not VarIsNull(ParamValues) then begin
        ParamValues := ParamValues.documentElement;
//        
        Node := ParamValues.selectNodes(
                  FORMAT( '//direction.required.classes.new[@ID=%s]',
                          [ Documentclass_Id]));
        //Параметр = Контролировать
        if NOT VarIsNull( Node)
          then begin
            // Найдено значение параметра
            if Node.Length <> 0
              then Result := Node.Item[0].getAttribute(AttrName);
          end;
      end;
      except
        ExceptionProc( 'isDirectionControl');
    end;

end;

{~GetLineExpbudget
  Получает данные строки из РЧБ по бланку расходов, бюджетополучателю,
  кбк. результат в Xml.

  Exchange #2449 - доработка
    В случае если в файле загрузке присланном органом Федерального казначейства
  указано значение "Кода цели", поиск бюджетной строки в РЧБ осуществлять по
  текущему алгоритму с учетом данного значения.
    Если в файле загрузки значение "Кода цели" не указано, поиск строки в РЧБ
  осуществлять так, как реализовано в настоящее время.

  эта же функция вызывается из порожденного ЭД 25-го класса из 24-го класса:
  Un_Import.CreateChildDoc25. в этом случае код цели будет взят еще из
  24-го класса (из файла), и только потом, если код цели не заполнен,
  код цели будет определятся по #2389. поэтому эта же функция в VB будет
  работать по новому, только если код цели будет заполнен в файле для
  24-го документа.

  exchange #3062
  отмена косгу - требуется удалить косгу из поиска}
function GetLineExpbudget( aDoc: Variant; aBudgetId: String): Variant;
var
  xPURPOSEFULGRANT_ID: string;
begin

    try
      // код цели для расходов берем из PURPOSEFULGRANT_ID
      xPURPOSEFULGRANT_ID := GetNodeAttributeEx( aDoc, 'PURPOSEFULGRANT_ID');
      if (xPURPOSEFULGRANT_ID = '') then begin

        Result := QueryXml( ' Select * From ExpBudget'
                           +' Where Budget_Id = ? and Estimate_Id = ?'
                           +' and Recipient_Id = ? and Kfsr_Code = ?'
                           +' and Kvr_Code = ?'
//                           +' and Kesr_Code = ?'
                           +' and Kcsr_Code = ?'
                           +' and Kadmr_Code = ?',
                            [ aBudgetId,
                              aDoc.getAttribute('ESTIMATE_ID'),
                              aDoc.getAttribute('RECIPIENT_ID'),
                              aDoc.getAttribute('KFSR_CODE'),
                              aDoc.getAttribute('KVR_CODE'),
                              //aDoc.getAttribute('KESR_CODE'),
                              aDoc.getAttribute('KCSR_CODE'),
                              aDoc.getAttribute('KADMR_CODE')]);
      end else begin

        Result := QueryXml( ' Select * From ExpBudget'
                           +' Where Budget_Id = ? and Estimate_Id = ? and '
                           +' Recipient_Id = ? and Kfsr_Code = ?'
                           +' and Kvr_Code = ?'
//                           +' and Kesr_Code = ?'
                           +' and Kcsr_Code = ? and Kadmr_Code = ?'
                           +' and PURPOSEFULGRANT_ID = ?',
                            [ aBudgetId,
                              aDoc.getAttribute('ESTIMATE_ID'),
                              aDoc.getAttribute('RECIPIENT_ID'),
                              aDoc.getAttribute('KFSR_CODE'),
                              aDoc.getAttribute('KVR_CODE'),
                              //Doc.getAttribute('KESR_CODE'),
                              aDoc.getAttribute('KCSR_CODE'),
                              aDoc.getAttribute('KADMR_CODE'),
                              xPURPOSEFULGRANT_ID]);
      end;
      except
        ExceptionLog( 'Сбой QueryWork.GetLineExpbudget');
    end;

end;

{~GetOrgByOrgCodeAccNum
//Получает данные организации и бюджет по коду организации, фин.году, счету организации.результат в Xml.
//сначала поиск производится по закладке дополнительно
//не смогли определить однозначно, поиск производится по общей закладке}
function GetOrgByOrgCodeAccNum(Code, Year, Role, Ls, AccType: String): Variant;
var
  sql: String;
  Xml: Variant;
begin

    try
      sql := ' Select distinct Obd.Budget_Id, O.Id Org_Id, O.Taxcode, O.Kpp, O.Description,' +
        ' Oa.Id Account_Id, Oa.Account_Number, Ofk.Description Ofk_Description,' +
        ' Ufk.Description Ufk_Description, UfkAcc.Id Ufk_Acc_Id, UfkAcc.Account_Number Ufk_Account_Number,' +
        ' Ufkb.Bic Bic, Ufkb.Description B_Name, ufkf.Name Ufk_Filial_Name' +
        ' From OrgBudgetDet Obd' +
        ' Join Org O on O.Id = Obd.Org_Id' +
        ' Left Join Budget B on Obd.Budget_Id = B.Id' +
        ' Left Join OrgRoles Ors on O.Id = Ors.Org_Id' +
        ' Join OrgAccount Oa on Oa.Org_Id = O.Id' +
        ' Left Join Org Ofk on Ofk.Id = Oa.Keeper_Id' +
        ' Left Join Org Ufk on Ufk.Id = Oa.Executer_Id' +
        ' Left Join OrgAccount UfkAcc on UfkAcc.Id = Oa.ExecuterAcc_Id' +
        ' Left Join Bank Ufkb on Ufkb.Id = UfkAcc.Bank_Id' +
        ' Left Join Filial Ufkf on Ufkf.Id = UfkAcc.Filial_Id' +
        ' Where O.Close_Date is null and Obd.Code_Fk = ?' +
        ' and B.FinYear = ? and Ors.OrgRole_Id = ?' +
        ' and Oa.Close_Date is null and Oa.Account_Number = ?' +
        ' and Oa.Orgacctype_Id = ? and Oa.Budget_Flag = 0 and Oa.Distributive_Flag = 0';
      Result := QueryXml(sql, [Code, Year, Role, Ls, AccType]);
      if Result.documentElement.childNodes.Length <> 1 then
      begin
        sql := ' Select distinct B.Id Budget_Id, O.Id Org_Id, O.Taxcode, O.Kpp, O.Description,' +
        ' Oa.Id Account_Id, Oa.Account_Number, Ofk.Description Ofk_Description,' +
        ' Ufk.Description Ufk_Description, UfkAcc.Id Ufk_Acc_Id, UfkAcc.Account_Number Ufk_Account_Number,' +
        ' Ufkb.Bic Bic, Ufkb.Description B_Name, ufkf.Name Ufk_Filial_Name' +
          ' From Budget B' +
          ' Join Org Fo on Fo.Id = B.Org_Id' +
          ' Join Contractor Inspector on Inspector.Inspector_Id = Fo.Id' +
          ' Join Org O on O.Id = Inspector.Org_Id' +
          ' Left Join OrgRoles Ors on O.Id = Ors.Org_Id' +
          ' Join OrgAccount Oa on Oa.Org_Id = O.Id' +
          ' Left Join Org Ofk on Ofk.Id = Oa.Keeper_Id' +
          ' Left Join Org Ufk on Ufk.Id = Oa.Executer_Id' +
          ' Left Join OrgAccount UfkAcc on UfkAcc.Id = Oa.ExecuterAcc_Id' +
          ' Left Join Bank Ufkb on Ufkb.Id = UfkAcc.Bank_Id' +
          ' Left Join Filial Ufkf on Ufkf.Id = UfkAcc.Filial_Id' +
          ' Where O.Close_Date is null and O.Name = ?' +
          ' and B.FinYear = ? and Ors.OrgRole_Id = ?' +
          ' and Oa.Close_Date is null and Oa.Account_Number = ?' +
          ' and Oa.Orgacctype_Id = ? and Oa.Budget_Flag = 0 and Oa.Distributive_Flag = 0';
        Result := QueryXml(sql, [Code, Year, Role, Ls, AccType]);
      end;
      except
        ExceptionLog( 'Сбой QueryWork.GetOrgByOrgCodeAccNum');
    end;

end;

{~GetOrgByOrgCodeAccNumEx
//Получает данные организации и бюджет по коду организации, фин.году, счету организации.результат в Xml.
//сначала поиск производится по закладке дополнительно
//не смогли определить однозначно, поиск производится по общей закладке.
 exchange #2516
    добавлен параметр aCfg_IncludeClosedLS:
    если параметр aCfg_IncludeClosedLS=TRUE, то при проверке л/с не проверяется
дата закрытия л/с.
    если параметр aCfg_IncludeClosedLS=FALSE, выполняется проверка л/с, чтобы
дата закрытия л/с не была указана (=null) (по старому - пп.2.1.4 exchange #2436).

 exchange #2599
 Если условие 1.2 не выполняется (организация актуальна для нескольких бюджетов),
 то Бюджет определяется следующим образом:
  ищем код в поле «Код организации» на закладке «Общая информация».
  Если найдена только одна организация с таким кодом среди незакрытых,
  то смотрим в ее карточке ссылку на ППО в поле «Публично-правовое образование».
  Затем, находим в справочнике бюджетов Бюджет текущего финансового года,
  «Публично-правовое образование» которого равно ППО организации,
  берем этот бюджет

 exchange #2778
    иногда имеется несколько орг, связанные каждая со своим бюджетом через ППО.
  в результате получается неоднозначный результат.
  поэтому добавлено поле NAME_BUD (параметр aBudgetName), определяющее
  название искомого бюджета.}
function GetOrgByOrgCodeAccNumEx( Code, Year, Role, Ls, AccType: String;
                                  aCfg_IncludeClosedLS: boolean;
                                  aBudgetName: string): Variant;
var
  sql: String;
  Xml: Variant;
  xSQLCheckClosedLS: string;
begin

    try
      // exchange #2516
      // если параметр aCfg_IncludeClosedLS=TRUE, исключаем из запросов
      // проверку закрытия л/с.
      if aCfg_IncludeClosedLS
        then xSQLCheckClosedLS := ''
        else xSQLCheckClosedLS := ' and Oa.Close_Date is null ';

      sql := ' Select distinct Obd.Budget_Id, O.Id Org_Id, O.Taxcode, O.Kpp, O.Description,' +
        ' Oa.Id Account_Id, Oa.Account_Number, Ofk.Description Ofk_Description,' +
        ' Ufk.Description Ufk_Description, UfkAcc.Id Ufk_Acc_Id, UfkAcc.Account_Number Ufk_Account_Number,' +
        ' Ufkb.Bic Bic, Ufkb.Description B_Name, ufkf.Name Ufk_Filial_Name' +
        ' From OrgBudgetDet Obd' +
        ' Join Org O on O.Id = Obd.Org_Id' +
        ' Left Join Budget B on Obd.Budget_Id = B.Id' +
        ' Left Join OrgRoles Ors on O.Id = Ors.Org_Id' +
        ' Join OrgAccount Oa on Oa.Org_Id = O.Id' +
        ' Left Join Org Ofk on Ofk.Id = Oa.Keeper_Id' +
        ' Left Join Org Ufk on Ufk.Id = Oa.Executer_Id' +
        ' Left Join OrgAccount UfkAcc on UfkAcc.Id = Oa.ExecuterAcc_Id' +
        ' Left Join Bank Ufkb on Ufkb.Id = UfkAcc.Bank_Id' +
        ' Left Join Filial Ufkf on Ufkf.Id = UfkAcc.Filial_Id' +
        ' Where O.Close_Date is null and Obd.Code_Fk = ?' +
        ' and B.FinYear = ? and Ors.OrgRole_Id = ?'
       +xSQLCheckClosedLS
//        ' and Oa.Close_Date is null '
       +' and Oa.Account_Number = ?' +
        ' and Oa.Orgacctype_Id = ? and Oa.Budget_Flag = 0 and Oa.Distributive_Flag = 0';
      Result := QueryXml(sql, [Code, Year, Role, Ls, AccType]);
      if Result.documentElement.childNodes.Length <> 1 then
      begin
        sql := ' Select distinct B.Id Budget_Id, O.Id Org_Id, O.Taxcode, O.Kpp, O.Description,' +
        ' Oa.Id Account_Id, Oa.Account_Number, Ofk.Description Ofk_Description,' +
        ' Ufk.Description Ufk_Description, UfkAcc.Id Ufk_Acc_Id, UfkAcc.Account_Number Ufk_Account_Number,' +
        ' Ufkb.Bic Bic, Ufkb.Description B_Name, ufkf.Name Ufk_Filial_Name' +
          ' From Budget B' +
          ' Join Org Fo on Fo.Id = B.Org_Id' +
          ' Join Contractor Inspector on Inspector.Inspector_Id = Fo.Id' +
          ' Join Org O on O.Id = Inspector.Org_Id' +
          ' Left Join OrgRoles Ors on O.Id = Ors.Org_Id' +
          ' Join OrgAccount Oa on Oa.Org_Id = O.Id' +
          ' Left Join Org Ofk on Ofk.Id = Oa.Keeper_Id' +
          ' Left Join Org Ufk on Ufk.Id = Oa.Executer_Id' +
          ' Left Join OrgAccount UfkAcc on UfkAcc.Id = Oa.ExecuterAcc_Id' +
          ' Left Join Bank Ufkb on Ufkb.Id = UfkAcc.Bank_Id' +
          ' Left Join Filial Ufkf on Ufkf.Id = UfkAcc.Filial_Id' +
          ' Where O.Close_Date is null and O.Name = ?' +
          ' and B.FinYear = ? and Ors.OrgRole_Id = ?'
         +xSQLCheckClosedLS
//          ' and Oa.Close_Date is null '
         +' and Oa.Account_Number = ?' +
          ' and Oa.Orgacctype_Id = ? and Oa.Budget_Flag = 0 and Oa.Distributive_Flag = 0';
        Result := QueryXml(sql, [Code, Year, Role, Ls, AccType]);
        // exchange #2599
        // если неоднозначность пп.1.2 - ищем по ППО
        if Result.documentElement.childNodes.Length <> 1 then begin
          sql := ' Select distinct B.Id Budget_Id, O.Id Org_Id, O.Taxcode, O.Kpp, O.Description,' +
          ' Oa.Id Account_Id, Oa.Account_Number, Ofk.Description Ofk_Description,' +
          ' Ufk.Description Ufk_Description, UfkAcc.Id Ufk_Acc_Id, UfkAcc.Account_Number Ufk_Account_Number,' +
          ' Ufkb.Bic Bic, Ufkb.Description B_Name, ufkf.Name Ufk_Filial_Name' +
            ' From Budget B' +
            // связь: бюджет->ППО<-организация.
            // т.е. поиск организации и бюджета с одним и тем же ППО.
            ' join org o on o.ppo_id=b.ppo_id' +
            ' Left Join OrgRoles Ors on O.Id = Ors.Org_Id' +
            ' Join OrgAccount Oa on Oa.Org_Id = O.Id' +
            ' Left Join Org Ofk on Ofk.Id = Oa.Keeper_Id' +
            ' Left Join Org Ufk on Ufk.Id = Oa.Executer_Id' +
            ' Left Join OrgAccount UfkAcc on UfkAcc.Id = Oa.ExecuterAcc_Id' +
            ' Left Join Bank Ufkb on Ufkb.Id = UfkAcc.Bank_Id' +
            ' Left Join Filial Ufkf on Ufkf.Id = UfkAcc.Filial_Id' +
            ' Where O.Close_Date is null and O.Name = ?' +
            ' and B.FinYear = ? and Ors.OrgRole_Id = ?'
           +xSQLCheckClosedLS
  //          ' and Oa.Close_Date is null '
           +' and Oa.Account_Number = ?'
           +' and Oa.Orgacctype_Id = ? and Oa.Budget_Flag = 0 and Oa.Distributive_Flag = 0';
           // exchange #2778 - добавлено название бюджета.
          if (LENGTH( aBudgetName) > 0)
            then begin
              sql := sql +' and upper(B.caption) = ?';
              Result := QueryXml( sql,
                                  [ Code, Year, Role, Ls, AccType,
                                    UPPERCASE( aBudgetName)]);
            end else
              Result := QueryXml(sql, [Code, Year, Role, Ls, AccType]);
        end;
      end;
      except
        ExceptionLog( 'Сбой QueryWork.GetOrgByOrgCodeAccNumEx');
    end;

end;


{~getGrantInvestment
  поиск кода субсидии по коду цели и ид.организации.
  возвращается ид. кода субсидии из GrantInvestment, у которого учредитель
  это организация, у которой вышестоящая организация указана как ид.орг
  в параметре, а код цели есть в строках "расшифровка учредителя".
  если код цели или ид.орг пустые - возвращается пустая строка. }
function getGrantInvestment(Purposefulgrant_Id, Rec_Id: String): String;
var
  sql: String;
begin

    try
      Result := '';
      // exchange #2926
      // поправлена проверка: если код цели или ид.орг не указаны, то
      // поиск кода субсидии не выполняется.
      if ((Purposefulgrant_Id <> '') AND ( Rec_Id <> '')) then
      begin
        sql := 'Select distinct Gi.Id From GrantInvestment Gi' +
          ' Join Grantinv_Line Gl on Gl.Grantinvestment_Id = Gi.Id' +
          ' Join Purposefulgrant Pfg on Pfg.id = Gl.Purposefulgrant_Id' +
          ' Left Join Org O on O.Id = Gi.Org_Id' +
          ' Left Join Org Pbs on O.Id = Pbs.Manager_Id' +
          ' Where pfg.id = ? and Pbs.id = ?';
        Result := QueryField(sql, [Purposefulgrant_Id, Rec_Id], 'ID');
      end;
      except
        ExceptionLog( 'Сбой getGrantInvestment');
    end;

end;

function ParceDescription(Description: String; var Contract_Name, Contract_Number,
  Contract_Date, Payment_Name, Payment_Number, Payment_Date: String; PP: Boolean = False): String;
var
  i, j, k, DescLength: Integer;
begin
  Contract_Number := '';
  Contract_Name := '';
  Contract_Date := '';
  Payment_Number := '';
  Payment_Name := '';
  Payment_Date := '';
  DescLength := Length(Description);
  i := Pos(' № ', Description);
  if i <= 0 then
  begin
    // проверяем на символ N вместо №
    i := Pos(' N ', Description);
    if i <= 0  then
      // не нашли номер БО, выходим
      Exit;
  end;
  // общий поиск
  for j := i - 2  downto 1 do
    if Description[j] = ' ' then
      break;
  // наименование документа-обязательства
  Contract_Name := Copy(Description, j + 1, i - j);
  j := Pos(' от ', Copy(Description, i, DescLength));
  // номер документа-обязательства; + 3 символа от знака №
  Contract_Number := Copy(Description, i + 3, j - 4);
  // дата документа-обязательства
  Contract_Date := Copy(Description, i + j + 3, 10);
  // проверка валидности даты
  if not ValidDate(Contract_Date) then
  begin
    Contract_Date := Copy(Description, i + j + 3, 8);
    if not ValidDate(Contract_Date) then
      Contract_Date := '';
  end;
  // если разбор для ПП, поиск дальше не нужен
  if PP then Exit;
  Description := Copy(Description, i + j + 3, DescLength);
  DescLength := Length(Description);
  i := Pos(' № ', Description);
  if i <= 0 then
  begin
    // проверяем на символ N вместо №
    i := Pos(' N ', Description);
    if i <= 0  then
      // не нашли номер документ-оплаты, выходим
      Exit;
  end;
  for j := i - 2 downto 1 do
    if Description[j] = ' ' then
      break;
  // наименование документа-обязательства
  Payment_Name := Copy(Description, j + 1, i - j - 1);
  j := Pos(' от ', Copy(Description, i, DescLength));
  // номер документа-обязательства; + 3 символа от знака №
  Payment_Number := Copy(Description, i + 3, j - 4);
  // дата документа-обязательства
  Payment_Date := Copy(Description, i + j + 3, 10);
  // проверка валидности даты
  if not ValidDate(Payment_Date) then
  begin
    Payment_Date := Copy(Description, i + j + 3, 8);
    if not ValidDate(Payment_Date) then
      Payment_Date := '';
  end;
end;

//Поиск типа договора и сам договор
function GetContract(Contract_Name, Contract_Number, Contract_Date, BudgetId: String): Variant;
var
  sql: String;
begin
  sql := 'Select C.* From Contract C' +
    ' Join Contype Ct on Ct.Id = C.Contype_Id' +
    ' Where C.Budget_id = ? and C.Documentclass_Id = 3' +
    ' and C.Dispstatus_Id = 6 and Trim(C.Doc_Number) = ? and C.Doc_Date = ?' +
    ' and Ct.Description like ?';
  Query.AddStr(BudgetId);
  Query.AddStr(Copy(Trim(Contract_Number), 0, 45));
  Query.AddDate(StrToDate(Contract_Date));
  Query.AddStr('%' + Trim(Contract_Name) + '%');
  Result := CreateOleObject('Microsoft.XmlDom');
  Result.LoadXml(Query.Run(sql));
end;

//Поиск типа договора и сам договор
function GetContractWOName(Contract_Number, Contract_Date, BudgetId: String): Variant;
var
  sql: String;
begin
  sql := 'Select C.* From Contract C' +
    ' Where C.Budget_id = ?' +
    ' and C.Dispstatus_Id = 6 and Trim(C.Doc_Number) = ? and C.Doc_Date = ?';
  Query.AddStr(BudgetId);
  Query.AddStr(Copy(Trim(Contract_Number), 0, 45));
  Query.AddDate(StrToDate(Contract_Date));
  Result := CreateOleObject('Microsoft.XmlDom');
  Result.LoadXml(Query.Run(sql));
end;

{~GetPpByDescription
 Поиск платежного поручения, на основании которого проводится возврат.

 exchange #2385
 требуется при поиске искать не соответствие номеру документа, а
 вхождение номера ЭД в строку номера (справа).
 поэтому используется: Trim(D.Doc_Number) like %НОМЕР
 в результате будут найдены все ЭД с номерами: xxxНОМЕР.

 предыдущий (до #2385) параметр в запросе был таким:
    Trim(D.Doc_Number) = ?
 соответственно:
    Query.AddStr( Copy(Trim(PayDoc_Number), 0, 20));}
function GetPpByDescription(PayDoc_Number, PayDoc_Date, BudgetId: String): Variant;
var
  sql: String;
begin
  sql := 'Select D.Id PP_Document_Id, D.Amount PP_Amount,' +
    ' D.Instance_link PP_Id, D.Description PP_Description,' +
    ' Pd.DocumentClass_Id Pd_Class_Id, Pd.Id Pd_Id, D.Budget_Id' +
    ' From Document D' +
    ' Left Join Document Pd on D.Parent_id = Pd.Id' +
    ' Where D.Budget_id = ? and D.Documentclass_Id = 13' +
    ' and D.Dispstatus_Id <> -1 and Trim(D.Doc_Number) like ? and D.Doc_Date = ?';
  Query.AddStr(BudgetId);
  Query.AddStr( '%' + Copy(Trim(PayDoc_Number), 0, 20));
  Query.AddDate(StrToDate(PayDoc_Date));
  Result := CreateOleObject('Microsoft.XmlDom');
  Result.LoadXml(Query.Run(sql));
end;


//Поиск типа договора и сам договор
function GetBoByContractandKBK(Contract, Doc: Variant): Variant;
var
  sql: String;
begin
  sql := ' Select B.* From Budgorder B' +
    ' Join Document D on D.Id = B.Document_Id' +
    ' Join Document DContr on DContr.Id = D.Parent_Id' +
    ' Where D.Budget_Id = ? and D.Dispstatus_Id = 6 and DContr.id = ?' +
    ' and B.Kfsr_Code = ? and B.Kcsr_Code = ? and B.Kvr_Code = ?' +
    ' and B.Kesr_Code = ? and B.Kadmr_Code = ? and B.Fsr_Id = ?' +
    ' and B.Kdf_Code = ? and B.Kde_Code = ? and B.Kdr_Code = ?';
  Result := QueryXml(sql, [Contract.getAttribute('BUDGET_ID'),
    Contract.getAttribute('DOCUMENT_ID'), Doc.getAttribute('KFSR_CODE'),
    Doc.getAttribute('KCSR_CODE'), Doc.getAttribute('KVR_CODE'),
    Doc.getAttribute('KESR_CODE'), Doc.getAttribute('KADMR_CODE'),
    Doc.getAttribute('FSR_ID'), Doc.getAttribute('KDF_CODE'),
    Doc.getAttribute('KDE_CODE'), Doc.getAttribute('KDR_CODE')]);
end;

//Поиск типа первичного документа-оплаты и сам документ-оплаты
function GetCondebts(Payment_Name, Payment_Number, Payment_Date, ContractId: String): Variant;
var
  sql: String;
begin
  sql := 'Select C.* From Condebts C' +
    ' Join PrimarydocType Pt on Pt.Id = C.PrimarydocType_Id' +
    ' Where Trim(C.Doc_Number) = ? and C.Doc_Date = ?' +
    ' and Pt.Description like ?';
  Query.AddStr(Copy(Trim(Payment_Number), 0, 45));
  Query.AddDate(StrToDate(Payment_Date));
  Query.AddStr('%' + Trim(Payment_Name) + '%');
  Result := CreateOleObject('Microsoft.XmlDom');
  Result.LoadXml(Query.Run(sql));
end;

function CheckLineFor25Class(Doc, PayDoc: Variant): Boolean;
var
  sql: String;
  Xml: Variant;
begin
  try
    
  sql := ' Select B.* From Budgorder B';
  if PayDoc.getAttribute('PD_CLASS_ID') = '11' then
    sql := sql + ' Where B.Document_Id = ?'
  else if PayDoc.getAttribute('PD_CLASS_ID') = '110' then
      sql := sql + ' Join Chequeorderdoc Cd on Cd.Slave_Id = B.Document_Id' +
        ' Join Chequeorder C on Cd.Master_Id = C.Document_Id' +
      ' Where C.Document_Id = ?'
  else if PayDoc.getAttribute('PD_CLASS_ID') = '111' then
      sql := StringReplace(sql, 'Select B.*', ' Select distinct B.*') +
        ' Join Chequeorderdoc Cd on Cd.Slave_Id = B.Document_Id' +
        ' Join Chequeorder C on Cd.Master_Id = C.Document_Id' +
        ' Join Chequeregisterdoc Crd on Crd.Slave_Id =C.Document_Id' +
        ' Join Chequeregister Cr on Crd.Master_Id = Cr.document_id' +
      ' Where Cr.Document_Id = ?'
  else begin
      Result := False;
    Exit;
  end;
  sql := sql + ' and B.Budget_Id = ? and B.Estimate_Id = ? ' +
    ' and B.Recipient_Id = ? and B.Amount = ? and B.Kfsr_Code = ? and B.Kcsr_Code = ? ' +
    ' and B.Kvr_Code = ? and B.Kesr_Code = ? and B.Kadmr_Code = ? and B.Fsr_Id = ?' +
    ' and B.Kdf_Code = ? and B.Kde_Code = ? and B.Kdr_Code = ?';
  Query.AddStr(PayDoc.getAttribute('PD_ID'));
  Query.AddStr(PayDoc.getAttribute('BUDGET_ID'));
  Query.AddStr(Doc.getAttribute('ESTIMATE_ID'));
  Query.AddStr(Doc.getAttribute('RECIPIENT_ID'));
  Query.AddCurr(Doc.getAttribute('AMOUNT'));
  Query.AddStr(Doc.getAttribute('KFSR_CODE'));
  Query.AddStr(Doc.getAttribute('KCSR_CODE'));
  Query.AddStr(Doc.getAttribute('KVR_CODE'));
  Query.AddStr(Doc.getAttribute('KESR_CODE'));
  Query.AddStr(Doc.getAttribute('KADMR_CODE'));
  Query.AddStr(Doc.getAttribute('FSR_ID'));
  Query.AddStr(Doc.getAttribute('KDF_CODE'));
  Query.AddStr(Doc.getAttribute('KDE_CODE'));
  Query.AddStr(Doc.getAttribute('KDR_CODE'));
  if (not VarIsNull(Doc.getAttribute('PERMISSIONLINE_ID')))
      and (Doc.getAttribute('PERMISSIONLINE_ID')<> '') then
  begin
    sql := sql + ' and B.Permissionline_Id = ?';
    Query.AddStr(Doc.getAttribute('PERMISSIONLINE_ID'));
  end;
  if (not VarIsNull(Doc.getAttribute('FUNDSOURCE_ID')))
      and (Doc.getAttribute('FUNDSOURCE_ID') <> '') then
  begin
    sql := sql + ' and B.Fundsource_Id = ?';
    Query.AddStr(Doc.getAttribute('FUNDSOURCE_ID'));
  end;
  if (not VarIsNull(Doc.getAttribute('BO_ID')))
      and (Doc.getAttribute('BO_ID') <> '') then
  begin
    sql := sql + ' and B.Bo_Id = ?';
    Query.AddStr(Doc.getAttribute('BO_ID'));
  end;
  if (not VarIsNull(Doc.getAttribute('CONDEBTS_ID')))
      and (Doc.getAttribute('CONDEBTS_ID') <> '') then
  begin
    sql := sql + ' and B.Condebts_Id = ?';
    Query.AddStr(Doc.getAttribute('CONDEBTS_ID'));
  end;
  if (not VarIsNull(Doc.getAttribute('ADVANCE_PAYMENT')))
      and (Doc.getAttribute('ADVANCE_PAYMENT') <> '') then
  begin
    sql := sql + ' and B.Advance_Payment = ?';
    Query.AddStr(Doc.getAttribute('ADVANCE_PAYMENT'));
  end;
  if (not VarIsNull(Doc.getAttribute('DIRECTION_ID')))
      and (Doc.getAttribute('DIRECTION_ID') <> '') then
  begin
    sql := sql + ' and B.Direction_Id = ?';
    Query.AddStr(Doc.getAttribute('DIRECTION_ID'));
  end;
  if (not VarIsNull(Doc.getAttribute('PURPOSEFULGRANT_ID')))
      and (Doc.getAttribute('PURPOSEFULGRANT_ID') <> '') then
  begin
    sql := sql + ' and B.Purposefulgrant_Id = ?';
    Query.AddStr(Doc.getAttribute('PURPOSEFULGRANT_ID'));
  end;
  Xml := CreateOleObject('Microsoft.XmlDom');
  Xml.LoadXml(Query.Run(sql));
  Result := Xml.documentElement.childNodes.Length = 1;
    
    except
      ExceptionLog( 'Сбой скрипта: "QueryWork.CheckLineFor25Class".');
  end;
end;

//Получает данные организации и бюджет по коду организации, фин.году, единому счету бюджета.результат в Xml.
//сначала поиск производится по закладке дополнительно
//не смогли определить однозначно, поиск производится по общей закладке
function GetBudgetByCodeOrgAndBS(OrgCode, Account, FinYear: String): Variant;
var
  sql: String;
  Xml: Variant;
begin
  sql := ' Select distinct Obd.Budget_Id, O.Id Org_Id, B.Common_Acc_Id, B.MainAcc_Id' +
    ' From OrgBudgetDet Obd' +
    ' Join Org O on O.Id = Obd.Org_Id' +
    ' Left Join Budget B on Obd.Budget_Id = B.Id' +
    ' Join OrgAccount Oa on Oa.Id = B.Common_Acc_Id' +
    ' Join Contractor Inspector on (Inspector.Inspector_Id = B.Org_Id and O.Id = Inspector.Org_Id)' +
    ' Where O.Close_Date is null and Obd.Code_Fk = ? and B.FinYear = ?' +
    ' and Oa.Close_Date is null and Oa.Account_Number = ?';
  Result := QueryXml(sql, [OrgCode, FinYear, Account]);
  if Result.documentElement.childNodes.Length <> 1 then
  begin
    sql := ' Select distinct B.Id Budget_Id, O.Id Org_Id, B.Common_Acc_Id, B.MainAcc_Id' +
      ' From Budget B' +
      ' Join Contractor Inspector on (Inspector.Inspector_Id = B.Org_Id)' +
      ' Join Org O on O.Id = Inspector.Org_Id' +
      ' Join OrgAccount Oa on Oa.Id = B.Common_Acc_Id' +
      ' Where O.Close_Date is null and O.Name = ? and B.FinYear = ?' +
      ' and Oa.Close_Date is null and Oa.Account_Number = ?';
    Result := QueryXml(sql, [OrgCode, FinYear, Account]);
  end;
end;

//Проверяет, является ли счет единым счетом бюджета.
function IsAccountMain(Account, BudgetID: String): boolean;
var
  sql, accNumber: String;
  Xml: Variant;
begin
  accNumber := '';
  sql := ' select oa.account_number acc_number, oa.orgacctype_id acc_type from budget b ' +
         ' join orgaccount oa on b.mainacc_id = oa.id ' +
         ' where b.id = ?';
  Xml := QueryXml(sql, [BudgetID]);
  if (Xml.documentElement.childNodes.Length  = 1) then
  begin
    if (Xml.documentElement.childNodes.Item[0].getAttribute('ACC_TYPE') = '2') then
      accNumber := Xml.documentElement.childNodes.Item[0].getAttribute('ACC_NUMBER')
    else if (Xml.documentElement.childNodes.Item[0].getAttribute('ACC_TYPE') = '5')
      or (Xml.documentElement.childNodes.Item[0].getAttribute('ACC_TYPE') = '9') then
    begin
      sql := ' select oa1.account_number acc_number, oa1.orgacctype_id acc_type from budget b ' +
         ' join orgaccount oa on b.mainacc_id = oa.id ' +
         ' join orgaccount oa1 on oa1.id = oa.executeracc_id ' +
         ' where b.id = ?';
      Xml := QueryXml(sql, [BudgetID]);
      if Xml.documentElement.childNodes.Length  = 1 then
          accNumber := Xml.documentElement.childNodes.Item[0].getAttribute('ACC_NUMBER');
    end;
  end;
  Result := accNumber = Account;
end;


function GetAccountMainID(BudgetID: String): String;
var
  sql, accID: String;
  Xml: Variant;
begin
  accID := '';
  sql := ' select oa.id acc_id, oa.orgacctype_id acc_type from budget b ' +
         ' join orgaccount oa on b.mainacc_id = oa.id ' +
         ' where b.id = ?';
  Xml := QueryXml(sql, [BudgetID]);
  if (Xml.documentElement.childNodes.Length  = 1) then
    accID := Xml.documentElement.childNodes.Item[0].getAttribute('ACC_ID');
  Result := accID;
end;

//Возвращает получателей доходов с флагом по умолчанию по Id организации.
function GetIncReceiverByBudgetOrgTaxcodeKpp(BudgetId, Taxcode, Kpp: String): Variant;
var
  sql: String;
begin
  sql := ' Select distinct R.Id From Receiver R' +
    ' Join Org O on R.Org_Id  = O.Id' +
    ' Where R.IsDefault = 1 and R.Budget_Id = ?';
  if (Taxcode <> '') and (Kpp <> '') then
  begin
    sql := sql + ' and O.Taxcode = ? and O.Kpp = ?';
    Result := QueryXml(sql, [BudgetId, Taxcode, Kpp]);
  end
  else
    Result := QueryXml(sql, [BudgetId]);
end;

//Функция возвращает Id бюджета в случае однозначного определения бюджета
//по коду организации,указанного на закладке Дополнительно организации.
//если не нашли по дополнительно, поиск производится по справочнику организации по
//коду организации,указанного на закладке "Общая информация" организации
//если и так не нашли, ищем с учетом ППО.
function GetBudgetByOrgCodePPO(OrgCode, FinYear: String): Variant;
var
  sql: String;
  Xml: Variant;
begin
  sql := ' Select distinct Obd.Budget_Id, Obd.Org_Id, O.Description' +
    ' From OrgBudgetDet Obd' +
    ' Join Org O on O.Id = Obd.Org_id' +
    ' Left Join Budget B on Obd.Budget_Id = B.Id' +
    ' Left Join OrgAccount Oa on O.Id = Oa.Org_Id' +
    ' Join OrgRoles Ors on O.Id = Ors.Org_Id' +
    ' Where Obd.Code_Fk = ? and B.FinYear = ? and O.Close_Date is null ' +
    ' and Oa.Orgacctype_Id = 5 and Oa.Budget_Flag = 0 and Oa.Distributive_Flag = 0' +
    ' and Oa.Close_Date is null and (Ors.OrgRole_Id = 18 or Ors.OrgRole_Id = 19)';
  Xml := QueryXml(sql, [OrgCode, FinYear]);
  if Xml.documentElement.childNodes.Length = 1 then
    Result := Xml.documentElement.childNodes.Item[0]
  else begin
    sql := ' Select distinct B.Id Budget_Id, O.Id Org_Id, O.Description From Org O' +
      ' Left Join Contractor C on C.Org_Id = O.Id' +
      ' Left Join Budget B on B.Org_id = C.Inspector_Id' +
      ' Left Join OrgAccount Oa on O.Id = Oa.Org_Id' +
      ' Join OrgRoles Ors on O.Id = Ors.Org_Id' +
      ' Where O.Name = ? and B.FinYear = ? and O.Close_Date is null' +
      ' and Oa.Orgacctype_Id = 5 and Oa.Budget_Flag = 0 and Oa.Distributive_Flag = 0' +
      ' and Oa.Close_Date is null and (Ors.OrgRole_Id = 18 or Ors.OrgRole_Id = 19)';
    Xml := QueryXml(sql, [OrgCode, FinYear]);
    if Xml.documentElement.childNodes.Length = 1 then
      Result := Xml.documentElement.childNodes.Item[0]
    // добавляем в поиск ППО
    else if (AzkCompareVersion('2.26.43.16') >= 0) then
    begin
      sql := ' Select distinct B.Id Budget_Id, O.Id Org_Id,O.Description From Org O' +
        ' Left Join Contractor C on C.Org_Id = O.Id' +
        ' Left Join Budget B on B.Org_id = C.Inspector_Id and B.Ppo_Id = O.Ppo_id' +
        ' Left Join OrgAccount Oa on O.Id = Oa.Org_Id' +
        ' Join OrgRoles Ors on O.Id = Ors.Org_Id' +
        ' Where O.Name = ? and B.FinYear = ? and O.Close_Date is null' +
        ' and Oa.Orgacctype_Id = 5 and Oa.Budget_Flag = 0 and Oa.Distributive_Flag = 0' +
        ' and Oa.Close_Date is null and (Ors.OrgRole_Id = 18 or Ors.OrgRole_Id = 19)';
      Xml := QueryXml(sql, [OrgCode, FinYear]);
      if Xml.documentElement.childNodes.Length = 1 then
        Result := Xml.documentElement.childNodes.Item[0];
    end;
  end;
end;

// Получает первичные документы, по которым пришел запрос на выяснение по АУ/БУ
// Результат в Xml.
function GetParentDocument(Budget, Foreign_key: String): Variant;
var
  sql: String;
  Xml: Variant;
begin
  sql := ' Select distinct M.Document_Id From Payorder P' +
    ' Join Document D on D.Id = P.Document_Id' +
    ' Left Join Document Dp on Dp.Parent_Id = D.Id' +
    ' Left Join MoneyTransferOrder M on M.Document_Id = Dp.Id' +
    ' Where D.Budget_id = ? and D.Documentclass_Id = 24 and D.Dispstatus_Id = 10' +
    ' and P.Foreign_Key like ? and Dp.dispstatus_id = 10' +
    ' and Dp.documentclass_id = 193 and not exists (select null from explainreq e' +
    ' where e.paydoc_id = dp.id and e.dispstatus_id <> -1)';
  Xml := QueryXml(sql, [Budget, Foreign_key  + '%']);
  if Xml.documentElement.childNodes.Length = 1 then
  begin
    sql := ' Select * From MoneyTransferOrder' +
      ' Where Document_Id = ? and (Title_Id is null or Id = Title_Id)';
    Result := QueryXml(sql, [Xml.documentElement.childNodes.item[0].getAttribute('DOCUMENT_ID')]);
  end
  else
    Result := null;
end;

{~getIndustryCodeDefault
  поиск нулевого отр кода
  Exchange #2333
  ацк-ф 21918
  поправлено - после перехода на симв.кбк нужно указывать полный код.}
function getIndustryCodeDefault( aBudgetId: String): String;
begin

    try
    Result := QueryField( ' Select I.Id Z From IndustryCode I'
                         +' Where I.Budget_Id = ? and I.Org_Id = 0'
                         +' and I.Code = ?',
                          [ aBudgetId,
                            FormatKbk( 'INDUSTRYCODE', '0', aBudgetId)],
                          'Z');
      except
        ExceptionProc( 'getIndustryCodeDefault');
    end;

end;


{~getGrantinvestmentCode
  получение кода цели.
    DefFlag - способ получения кода:
        =true - в начале выполняется поиск по бюджету, Code и OrgId.
                если однозначно не распознается, тогда выполняется поиск только
                по бюджету.
        =false - поиск кода только по бюджету.
  возвращает:
    ID организации или пустая строка}
function getGrantinvestmentCode(BudgetId: String; DefFlag: Boolean = False;
  Code: String = ''; OrgId: String = ''): String;
var
  sql: String;
  Xml: Variant;
begin

    try
      if DefFlag then
        // exchange #2616
        // если организация не указана, то поиск с учетом организации
        // не выполняем и ищем только по бюджету
        if (LENGTH( OrgId) > 0) then begin
          sql := ' Select distinct Gi.Id From GrantInvestment Gi' +
            ' Left Join Org O on O.Id = Gi.Org_Id' +
            ' Left Join Org Pbs on O.Id = Pbs.Manager_Id' +
            ' Where Gi.Budget_Id = ? and Gi.Code = ? and Pbs.Id = ?';
          Xml := QueryXml(sql, [BudgetId, Code, OrgId]);
          if Xml.documentElement.childNodes.Length = 1 then begin
            Result := Xml.documentElement.childNodes.item[0].getAttribute('ID');
            EXIT;
          end;
        end;
      // exchange #2515
      // GrantInvestment.Code не цифровой, а символьны тип, поэтому,
      // если использовать =0 (как число), если в поле будут введены
      // символьные значения, будет ошибка в запросе. поэтому не =0
      // а должно быть ='0'!
      // к тому же убрано лишнее дублирование кода.
      // #exchange #2591
      // при переходе на символьные КБК, код цели ищем через маску.
      Result := QueryField(  'Select G.Id From GrantInvestment G'
                            +' Where G.Budget_Id = ? and G.Org_Id = 0 '
                            +' and G.Code = ?',
                             [ BudgetId,
                               FormatKbk( 'GRANTINVESTMENT', '0', BudgetId)],
                             'ID');
      except
        ExceptionLog( 'Сбой QueryWork.getGrantinvestmentCode');
    end;

(*
    else begin
      sql := 'Select G.Id' +
        ' From GrantInvestment G' +
        ' Where G.Budget_Id = ? and G.Org_Id = 0 and G.Code = '#39'0'#39;
      Result := QueryField(sql, [BudgetId], 'ID');
    end;
  end
  else begin
    sql := 'Select G.Id' +
      ' From GrantInvestment G' +
      ' Where G.Budget_Id = ? and G.Org_Id = 0 and G.Code = '#39'0'#39;
    Result := QueryField(sql, [BudgetId], 'ID');
  end;
  *)
end;

// Получает данные по организации-владельцу вышестоящего бланка расходов документа,
// включенного в расходное расписание
// Результат в Xml.
function GetOrgFromRelationDocument(Id: String): Variant;
var
  sql: String;
begin
  sql := ' Select O.Name, O.Description' +
    ' From ExpSchedule E' +
    ' Join RegisterDoc R On R.Master_Id = E.Document_Id' +
    ' Join Document D On D.Id = R.Slave_Id' +
    ' Join BudgOrder B On B.Document_id = D.Id And Coalesce(B.Title_Id, B.Id) = B.Id' +
    ' Left Join Estimate Est On Est.Id = B.Estimate_Id' +
    ' Left Join Estimate Ep On Est.Parent_Id = Ep.Id' +
    ' Left Join Org O on O.Id = Ep.Org_id' +
    ' Where E.Id = ?' +
    ' Union Select O.Name, O.Description' +
    ' From ExpSchedule E' +
    ' Join RegisterDoc R On R.Master_Id = E.Document_Id' +
    ' Join Document D On D.Id = R.Slave_Id' +
    ' Join ExpAssignment B On B.Document_id = D.Id And Coalesce(B.Title_Id, B.Id) = B.Id' +
    ' Left Join Estimate Est On Est.Id = B.Estimate_Id' +
    ' Left Join Estimate Ep On Est.Parent_Id = Ep.Id' +
    ' Left Join Org O on O.Id = Ep.Org_id' +
    ' Where E.Id = ?';
  Result := QueryXml(sql, [Id, Id]);
end;

{~GetUchrGrantInvestment
   Получает данные по организации-учредителю субсидии и инвестиции
   Результат в Xml.
   Exchange #2334
   aFilterGrandInvesment - список идентификаторов выбранных строк из
   справочника"субсидии и инвестиции".
   exchange #2782 - доработка запроса.}
function GetUchrGrantInvestment(BudgetId, aFilterGrandInvesment: String): Variant;
var
  sql: String;
begin
  sql := ' Select distinct G.Org_Id, Coalesce(Ob.Code_Fk, O.Name) Org_Code, ' +
    ' O.Caption, O.Description, O.Okpo, O.Kadm_Code' +
    ' From Grantinvestment G Join Org O on O.Id = G.Org_Id' +
    ' Left Join OrgBudgetDet Ob on Ob.Org_Id = O.Id and Ob.Budget_Id = ?' +
    ' Where G.Budget_Id = ? and G.Org_Id <> 0 '
    // Exchange #2334
    // Exchange #2782
    + BuildQueryByIDListString( aFilterGrandInvesment, 'G.ID', ' and %s');
//    ' and (G.ID in ('+aFilterGrandInvesment+'))';
  Result := QueryXml(sql, [BudgetId, BudgetId]);
end;


{~GetDirectionID
// получение идентификатора расходного обязательства (DIRECTION_ID)
// aEstimateID - бюджетополучатель (организация расходной строки)
// aClassID - класс документа (193,215,...)
// aLine - строка документа}
function GetDirectionID( aBudgetId, aEstimateID, aClassID: string; aLine: Variant): string;
var
  xEstKind: string;
  xData: Variant;
  xFlag: boolean;
  i: integer;
begin
  try

    xEstKind := GetEstimateKind( aEstimateID);
    
    xFlag := (isDirectionAutoFill(aBudgetId) and (isDirectionControl( aClassID, xEstKind) <> '2'));



    if xFlag then begin
      // создаем данные для запроса
      xData := aLine.ownerDocument.Createelement( 'LINE');
      CopyXmlNodeAttributes( aLine, xData);
      //aLine.cloneNode( FALSE);
//      xData.NodeName := 'LINE';
      xData.setAttribute( 'DOCUMENTCLASS_ID', aClassID);
      xData.setAttribute( 'DIRECTION_ID', '');
      xData.setAttribute( 'ESTIMATE_ID', aEstimateID);

      Result := DirectionAutoFillEx( aBudgetId, xData);
      
    end else begin
      Result := '';
      
    end;
    
    except
      ExceptionLog( 'Сбой: QueryWork.GetDirectionID');
  end;
end;
{==============================================================================}
{~GetIndustryCode
  возвращает код "Отраслевой код" по полю идентификатора aIndustryID.
  ~Результат~
    строка отраслевого кода}
function GetIndustryCode( aIndustryID: string): string;
begin

    try

      if ( LENGTH( TRIM( aIndustryID)) <= 0)
        then Result := ''
        else Result := QueryField( 'select CODE from INDUSTRYCODE where ID=?',
                                    [ TRIM( aIndustryID)],
                                    'CODE');

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

end;

{~GetGroundNameByID
  Возвращает код показателя основания налогового платежа по идентификатору aID.}
function GetGroundNameByID( aID: String): String;
begin

    try
      if ( LENGTH( TRIM( aID)) <= 0)
        then Result := ''
        else Result := QueryField( 'Select Name From PayGround Where id = ?',
                                    [ aID],
                                    'NAME');
      except
        ExceptionLog( 'Сбой QueryWork.GetGroundNameByID');
    end;

end;


{~GetPayTypeNameByID
  Возвращает код налогового платежа по идентификатору}
function GetPayTypeNameByID( aID: String): String;
begin

    try
      if ( LENGTH( TRIM( aID)) <= 0)
        then Result := ''
        else Result := QueryField( 'Select Name From PayType Where ID = ?',
                                    [ aID],
                                    'NAME');
      except
        ExceptionLog( 'Сбой QueryWork.GetPayTypeNameByID');
    end;

end;

{~ExtStatusCaptionByID
  возвращает описание внешнего статуса aExtStatusID.}
function ExtStatusCaptionByID( aExtStatusID: string): string;
begin

    try
      if ( LENGTH( aExtStatusID) <= 0)
        then Result := ''
        else Result := QueryField( 'select es.caption from extstatus es '
                                  +'where es.id=?',
                                   [ aExtStatusID],
                                   'CAPTION');

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

end;


{~OperTypeDefaultForClassEx
 определяем тип операции по умолчанию для класса aClassID.
 см.справочник: справочники/документооборот/типы операций по умолчанию.
 Параметр:
   aClassID - номер класса (строка).
 результат:
   значение типа операции (строка).}
function OperTypeDefaultForClassEx( aClassID: string): string;
var
  xXml: Variant;
begin

    try
      xXml := QueryXml( ' Select O.* From DEFOPERTYPE O'
                      +' Where O.DOCUMENTCLASS_ID = ?',
                       [ aClassID]);
      xXml := xXml.documentElement.childNodes;
      if (xXml.Length = 1)
        then Result := xXml.childNodes.Item[0].getAttribute('OPERTYPE_ID')
        else Result := '0';   // по умолчанию "НЕ УКАЗАНО"
      except
        ExceptionLog( 'Сбой QueryWork.OperTypeDefaultForClass');
    end;

end;


{~SearchDoc198ByNomDateLS
   exchange #2600
   добавлено для обработки раздела IK.UK п.2.7
   поиск ЭД 198 класса по Номеру, Дате, Лицевому счету (тип счета = 5)
   (на основной закладке) ищем документ на статусе
   «Готов к исполнению» внешний статус «Выгружен».}
function SearchDoc198ByNomDateLS( aBudgetID, aNomDoc, aDateDoc, aLS: string): String;
var
  xXml: Variant;
begin

    try
      xXml := QueryXml( ' Select P.Id From Document D'
                       +' Join PayDetail P on P.Document_Id = D.Id'
                       +' Join OrgAccount Oa on Oa.Id = P.Org_Acc_Id'
                       +' Where D.Budget_Id = ? and D.DispStatus_Id = 86'
                       +' and D.DocumentClass_Id = 198 and LTrim(D.Doc_Number) = ?'
                       +' and D.Doc_Date = ? and P.Extstatus_Id = 1'
                       +' and Oa.OrgAccType_Id = 5 And P.ORG_ACCOUNT = ?',
                        [ aBudgetID,
                          aNomDoc,
                          StrToDate( aDateDoc),
                          aLS]);
      if (xXml.documentElement.childNodes.Length = 1)
        then Result := xXml.documentElement.childNodes.Item[0].getAttribute('ID')
        else Result := '';
      except
        ExceptionLog( 'Сбой QueryWork.SearchDoc198ByNomDateLS');
    end;

end;


{~GetBudgetLevel
  получение кода типа бюджета aBudgetID}
function GetBudgetLevel( aBudgetID: string): string;
begin

    try
      Result := QueryField( ' Select Bl.BUDGTYPE From Budget B'
                           +' Join BudgLevel Bl on'
                           +' (B.BudgLevel_Id = Bl.Id) Where B.Id = ?',
                            [ aBudgetId],
                            'BUDGTYPE');

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

end;


{~GetBudgetName
  получение названия бюджета aBudgetID}
function GetBudgetName( aBudgetID: string): string;
begin

    try
      Result := QueryField( ' Select B.CAPTION From Budget B Where B.Id = ?',
                            [ aBudgetId],
                            'CAPTION');

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

end;


{~UpdateDocumentForegnKey
  обновление поля ForegnKey документа класса aClass, ид.ЭД =aID
  на значение aFOREIGN_KEY.}
procedure UpdateDocumentForegnKey( aClass, aID, aFOREIGN_KEY: string);
var
  xVersion: string;
begin

    try
      try
        WriteLog('Обновление поля FOREIGN_KEY...');
        // для обновления необходимо указать версию ЭД aVersion
        // на случай блокирования многопользовательского изменения ЭД.
        // поэтому тут получаем версию ЭД по ид.ЭД
        // в таблице бд, с названием, определяемым по классу эд.
        xVersion := QueryField(
                          FORMAT( ' Select Version From %s  where ID = ?',
                                  [ TableForClass( aClass)]),
                          [ aID],
                          'VERSION');

        ExecProc( 'EXCHPROC',
                  [ 'action', 'foreign_key',
                    'class', aClass,
                    'ID', aID,
                    'VERSION', xVersion,
                    'FOREIGN_KEY', aFOREIGN_KEY]);
        WriteLog('Обновление поля FOREIGN_KEY документа выполнено успешно.');
        except
          WriteInfo( 'Ошибка при обновлении поля FOREIGN_KEY: '
                      + LastException.Message);
      end;
      except
        ExceptionLog( 'Сбой QueryWork.UpdateDocumentForegnKey');
    end;

end;

begin
end.
