//uses 'Un_GrantInvestmentList';

function CheckPayOrder(cds: TClientDataSet; IniPath: String): Boolean;
var
  sql, GrantInvestment_Id: String;
  Xml: Variant;
  i: Integer;
  Unclassified, isOneMask, MustBeGrantInvestCode: Boolean;
  fsScript: TfsScript;
  FileStream: TFileStream;
  procedure SetMessage(Text: String);
  begin
    cds.Edit;
    cds.FieldByName('ResText').AsString := Text;
    cds.Post;
  end;
begin
  Result := False;
  if AzkCompareVersion('2.26.42.11') < 0 then
  begin
    SetMessage('Модуль проверки работает начиная с версии АЦК-Финансы 2.26.42.11');
    Exit;
  end;
  Xml := CreateOleObject('Microsoft.XmlDom');
  //проверяются только документы, у которых счет получателя совпал со счетом
  //указанным в справочнике Бухгалтерия-Настройка счетов, поле расчетный счет,
  //тип счета "Счет для учета операций БУ/АУ".
  if AzkCompareVersion('2.26.46.1') >= 0 then
    sql := 'Select P.Rec_Acc_Id, Oa.Org_Id' +
      ' From Payorder P' +
      ' Join BudgetOrgAccount B on P.Rec_Acc_Id = B.OrgAccount_Id' +
      '   and P.Budget_Id = B.Budget_Id' +
      ' Join OrgAccount Oa on Oa.Id = B.OrgAccount_Id' +
      ' Where P.Id = ? and B.BudgetOrgAccountType_Id = 1'
  else
    //проверяются только документы, у которых счет получателя совпал со счетом
    //для учета операций по БУ, АУ в справочнике бюджетов.
    sql := 'Select P.Rec_Acc_Id, Oa.Org_Id' +
      ' From Payorder P' +
      ' Join Budget B on P.Rec_Acc_Id = B.AutonomAcc_Id and P.Budget_Id = B.Id' +
      ' Join OrgAccount Oa on Oa.Id = B.AutonomAcc_Id' +
      ' Where P.Id = ?';
  Query.AddStr(cds.FieldByName('Id').asString);
  Xml.LoadXML(Query.Run(sql));
  Xml := Xml.documentElement.childNodes;
  if (Xml.Length = 1) and (Xml.Item[0].getAttribute('REC_ACC_ID') <> '') then
  begin
    cds.Edit;
    cds.FieldByName('Rec_Acc_Id').Value := Xml.Item[0].getAttribute('REC_ACC_ID');
    cds.FieldByName('Rec_Id').Value := Xml.Item[0].getAttribute('ORG_ID');
    cds.Post;
  end
  else begin
    SetMessage('Счет не совпадает со счетом для учета операций по БУ, АУ' +
      ' или не найден в базе');
    Exit;
  end;
  cds.Edit;
  cds.FieldByName('Enroll').Value := Null;
  cds.Post;
  //устанавливаем флаг неклассифицированных поступлений
  Unclassified := False;
  //определяет Id получателя из выписки
  if cds.FieldByName('Org_Id').asString = '' then
  begin
    if cds.FieldByName('Org_TaxCode').asString = '' then
    begin
      SetMessage('Не заполнен ИНН в блоке "Получатель из выписки"' +
        ' ЭД "Приложение к выписке кредитовое"');
      Exit;
    end;
     //Exchange #2263 добавляем при поиске роли организации
    sql := 'Select O.Id' +
      ' From Org O' +
      ' Join Orgroles Orl on Orl.Org_Id = O.Id' +
      ' Where O.Taxcode = ? and O.Close_Date is null and Orl.OrgRole_Id in (18, 19)';
    Query.AddStr(cds.FieldByName('Org_Taxcode').asString);
    if cds.FieldByName('Org_Kpp').asString <> '' then
    begin
      sql := sql + ' and O.Kpp = ?';
      Query.AddStr(cds.FieldByName('Org_Kpp').asString);
    end;
    Xml := CreateOleObject('Microsoft.XmlDom');
    Xml.LoadXML(Query.Run(sql));
    Xml := Xml.documentElement.childNodes;
    if Xml.Length = 1 then
    begin
      cds.Edit;
      cds.FieldByName('Org_Id').AsString := Xml.items[0].getAttribute('ID');
      cds.Post;
    end
    else begin
      SetMessage('Id получателя из выписки в базе не найден');
      Unclassified := True;
    end;
  end;
  if (not Unclassified) then
  begin
    //Определяем список лицевых счетов открытых на б/с счете получателя 24 класса
    sql := 'Select Ls.Account_Number, Ls.Id' +
      ' From OrgAccount Ls' +
      ' Join Org O on O.Id = Ls.Org_Id' +
      ' Join OrgAccount Bs on Bs.Id = Ls.KeeperAcc_Id' +
      ' Where Ls.Org_Id = ? and Bs.Id = ? and Ls.OrgAccType_Id = 1' +
      '   and Ls.Close_Date is null and Ls.Budget_Flag = 0' +
      ' Union' +
      ' Select Ls.Account_Number, Ls.Id' +
      ' From OrgAccount Ls' +
      ' Join Org O on O.Id = Ls.Org_Id' +
      ' Join OrgAccount Bs on Bs.Id = Ls.ExecuterAcc_Id' +
      ' Where Ls.Org_Id = ? and Bs.Id = ? and Ls.OrgAccType_Id = 5' +
      '   and Ls.Close_Date is null and Ls.Budget_Flag = 0';
    Query.AddStr(cds.FieldByName('Org_Id').AsString);
    Query.AddStr(cds.FieldByName('Rec_Acc_Id').asString);
    Query.AddStr(cds.FieldByName('Org_Id').AsString);
    Query.AddStr(cds.FieldByName('Rec_Acc_Id').asString);
    Xml := CreateOleObject('Microsoft.XmlDom');
    Xml.LoadXML(Query.Run(sql));
    if not isSearchAccount(cds, Xml) then
    begin
      SetMessage('Не удалось получить счет из наименования получателя или' +
        ' назначения платежа');
      Unclassified := True;
    end;
  end;
      
  if (not Unclassified) and (cds.FieldByName('Pi_Budget_Code').asString <> '') then
  begin
    cds.Edit;
    //получает отраслевой код
    cds.FieldByName('Industry_Code').AsString :=
      Copy(cds.FieldByName('Pi_Budget_Code').asString, 1, 17);
    //получает КОСГУ
    cds.FieldByName('Kesr_Code').AsString :=
      Copy(cds.FieldByName('Pi_Budget_Code').asString, 18, 3);
    cds.Post;
  end
  //104 поле не заполнено
  else if (not Unclassified) and (cds.FieldByName('Pi_Budget_Code').asString = '') then
  begin
    //инициализирует значения отраслевого кода и косгу
    cds.Edit;
    cds.FieldByName('Industry_Code').AsString := '';
    cds.FieldByName('Kesr_Code').AsString := '';
    cds.Post;
    //получает отраслевой код и косгу из назначения
    if not isParceDescription(cds, 'отр.код') then
      //Exchange #2281, если нет отр.кода, ищем один косгу,
      //без него классифицироать не будем
      if not isParceDescription(cds, 'косгу') then
      begin
        SetMessage('Не удалось получить КОСГУ из назначения платежа');
        Unclassified := True;
      end
  end
  else Unclassified := True;
  
  //проверка отраслевого кода на 17 нулей и замена на один системный ноль
  if not (Unclassified) then
  begin
    if (StringReplace(cds.FieldByName('Industry_Code').AsString, '0', '') = '')
      or (Trim(cds.FieldByName('Industry_Code').AsString) = '') then
    begin
      cds.Edit;
      cds.FieldByName('Industry_Code').AsString := '0';
      cds.Post;
    end;
  end;
  
  
  //инициализирует значениe кода субсидии
  cds.Edit;
  cds.FieldByName('GrantInvestment_Code').AsString := '';
  cds.Post;
  
  //Exchange #2281, Exchange #2332
  //Код субсидии ищем только если второй разаряд лс отличен от 0 и 2
  MustBeGrantInvestCode :=
    not(Copy(cds.FieldByName('LS_Number').asString, 2, 1) in ['0','2']);
//    (Copy(cds.FieldByName('LS_Number').asString, 2, 1) <> '0') AND
//    (Copy(cds.FieldByName('LS_Number').asString, 2, 1) <> '2');
  if (not Unclassified) then
    if (not isParceDescription(cds, 'код субсидии')) then
      if MustBeGrantInvestCode then
      begin
        SetMessage('Не удалось получить код субсидии из назначения платежа');
        Unclassified := True;
      end;


  //приведение косгу к числовому типу
  if (not Unclassified) then
  begin
    cds.Edit;
    try
      cds.FieldByName('Kesr_Code').asInteger :=
        StrToInt(StringReplace(cds.FieldByName('Kesr_Code').asString, ' ', ''));
    except
      cds.FieldByName('Kesr_Code').asInteger := 0;
      cds.FieldByName('ResText').AsString :=
        'Не удалось преобразовать КОСГУ в числовой тип';
      Unclassified := True;
    end;
    cds.Post;
  end;
  
  //проверяем полученные коды
  //КОСГУ
  if (not Unclassified) and (cds.FieldByName('Kesr_Code').AsInteger <> 0) then
  begin
    sql := 'Select Id From Kes Where Budget_Id = ? and Code = ?';
    Query.AddStr(cds.FieldByName('Budget_Id').AsString);
    Query.AddStr(cds.FieldByName('Kesr_Code').asString);
    Xml := CreateOleObject('Microsoft.XmlDom');
    Xml.LoadXML(Query.Run(sql));
    if Xml.documentElement.childNodes.Length <> 1 then
    begin
      Unclassified := True;
      SetMessage('КОСГУ: ' + cds.FieldByName('Kesr_Code').AsString
        + ' не найден в базе данных');
    end
  end
  else if (not Unclassified) and (cds.FieldByName('Kesr_Code').AsInteger = 0) then
  begin
    Unclassified := True;
    SetMessage('Не удалось получить КОСГУ или КОСГУ равен 0');
  end
  else Unclassified := True;

  //Код субсидии
  if (not Unclassified) then
    if (Trim(cds.FieldByName('Grantinvestment_Code').AsString) <> '') then
    begin
      sql := 'Select G.Id, G.FType' +
        ' From Grantinvestment G' +
        ' Join Org O on O.Manager_Id = G.Org_id' +
        ' Where G.Budget_Id = ? and O.Id = ? and G.Code = ?' +
        ' Union Select G.Id, G.FType' +
        ' From Grantinvestment G' +
        ' Where G.Budget_Id = ? and G.Org_Id = 0 and G.Code = ?';
      Query.AddStr(cds.FieldByName('Budget_Id').AsString);
      Query.AddStr(cds.FieldByName('Org_Id').AsString);
      Query.AddStr(cds.FieldByName('Grantinvestment_Code').AsString);
      Query.AddStr(cds.FieldByName('Budget_Id').AsString);
      Query.AddStr(cds.FieldByName('Grantinvestment_Code').AsString);
      Xml := CreateOleObject('Microsoft.XmlDom');
      Xml.LoadXML(Query.Run(sql));
      if Xml.documentElement.childNodes.Length = 1 then
      begin
        cds.Edit;
        cds.FieldByName('Grantinvestment_Id').AsString :=
          Xml.documentElement.childNodes.Item[0].getAttribute('ID');
        cds.FieldByName('Grantinvestment_Type').AsString :=
          Xml.documentElement.childNodes.Item[0].getAttribute('FTYPE');
        cds.Post;
      end
      else if Xml.documentElement.childNodes.Length > 1 then
      begin
        fsScript := TFsScript.create(nil);
        fsScript.Parent := fsGlobalUnit;
        FileStream := TFileStream.Create(IniPath + 'Un_GrantInvestmentList.pfe', fmOpenRead);
        try
          if not fsScript.SetILCode(FileStream) then
            raise(fsScript.ErrorMsg);
          if not fsScript.Find('GetGrantIntvestmentId') then
          begin
            SetMessage('Код субсидии в базе не однозначен. В модуле: ' +
              'Un_GrantInvestmentList не найдена функция: GetGrantIntvestmentId');
            Unclassified := True;
          end
          else begin
            //for testing
            //GrantInvestment_Id := GetGrantIntvestmentId(cds, IniPath);
            GrantInvestment_Id := fsScript.CallFunction(IniPath + 'Un_GrantInvestmentList',
              'GetGrantIntvestmentId', [cds, IniPath]);
            if Trim(GrantInvestment_Id) <> '' then
            begin
              sql := 'Select G.FType From Grantinvestment G Where G.Id = ?';
              Query.AddStr(GrantInvestment_Id);
              Xml := CreateOleObject('Microsoft.XmlDom');
              Xml.LoadXML(Query.Run(sql));
              cds.Edit;
              cds.FieldByName('Grantinvestment_Id').AsString := Trim(GrantInvestment_Id);
              cds.FieldByName('Grantinvestment_Type').AsString :=
                Xml.documentElement.childNodes.Item[0].getAttribute('FTYPE');
              cds.Post;
            end
            else begin
              SetMessage('Код субсидии не выбран из справочника');
              Unclassified := True;
            end;
          end;
        finally
          FileStream.Free;
        end;
      end
      //код субсидии не найден в справочнике
      else if (not MustBeGrantInvestCode) then
      begin
        cds.Edit;
        cds.FieldByName('Grantinvestment_Code').asString := '0';
        cds.Post;
        //получает Id системного(0-го) кода субсидии и инвестиции
        sql := ' Select Id' +
        ' From GrantInvestment' +
        ' Where Org_Id = 0 and Budget_Id = ? and Code = ?';
        Query.AddStr(cds.FieldByName('Budget_Id').asString);
        Query.AddStr(cds.FieldByName('Grantinvestment_Code').asString);
        Xml := CreateOleObject('Microsoft.XmlDom');
        Xml.LoadXML(Query.Run(sql));
        if Xml.documentElement.childNodes.Length = 1 then
        begin
          cds.Edit;
          cds.FieldByName('Grantinvestment_Id').AsString :=
            Xml.documentElement.childNodes.Item[0].getAttribute('ID');
          cds.Post;
        end
        else begin
          SetMessage('Не найден ID системного кода субсидии с нулевым значением');
          Unclassified := True;
        end;
      end
      else begin
        Unclassified := True;
        SetMessage('Код субсидии: ' + cds.FieldByName('Grantinvestment_Code').AsString
          + ' не найден в базе данных');
      end;
    end
    //если код субсидии не заполнен
    else begin
      if (not MustBeGrantInvestCode) then
      begin
        cds.Edit;
        cds.FieldByName('Grantinvestment_Code').asString := '0';
        cds.Post;
        //получает Id системного(0-го) кода субсидии и инвестиции
        sql := ' Select Id' +
        ' From GrantInvestment' +
        ' Where Org_Id = 0 and Budget_Id = ? and Code = ?';
        Query.AddStr(cds.FieldByName('Budget_Id').asString);
        Query.AddStr(cds.FieldByName('Grantinvestment_Code').asString);
        Xml := CreateOleObject('Microsoft.XmlDom');
        Xml.LoadXML(Query.Run(sql));
        if Xml.documentElement.childNodes.Length = 1 then
        begin
          cds.Edit;
          cds.FieldByName('Grantinvestment_Id').AsString :=
            Xml.documentElement.childNodes.Item[0].getAttribute('ID');
          cds.Post;
        end
        else begin
          SetMessage('Не найден ID системного кода субсидии с нулевым значением');
          Unclassified := True;
        end;
      end
      else Unclassified := True;
    end;
  
  //Отраслевой код
  if (not Unclassified) then
  begin
    if cds.FieldByName('Industry_Code').AsString <> '0' then
    begin
      sql := 'Select I.Id' +
        ' From IndustryCode I' +
        ' Join Org O on O.Manager_Id = I.Org_id' +
        ' Where I.Budget_Id = ? and O.Id = ? and I.Code = ?' +
        ' Union Select I.Id' +
        ' From IndustryCode I' +
        ' Where I.Budget_Id = ? and I.Org_Id = 0 and I.Code = ?';
      Query.AddStr(cds.FieldByName('Budget_Id').AsString);
      Query.AddStr(cds.FieldByName('Org_Id').AsString);
      Query.AddStr(cds.FieldByName('Industry_Code').AsString);
      Query.AddStr(cds.FieldByName('Budget_Id').AsString);
      Query.AddStr(cds.FieldByName('Industry_Code').AsString);
    end
    else begin
      sql := 'Select I.Id' +
        ' From IndustryCode I' +
        ' Where I.Budget_Id = ? and I.Org_Id = 0 and I.Code = ?';
      Query.AddStr(cds.FieldByName('Budget_Id').AsString);
      Query.AddStr(cds.FieldByName('Industry_Code').AsString);
    end;
    Xml := CreateOleObject('Microsoft.XmlDom');
    Xml.LoadXML(Query.Run(sql));
    if Xml.documentElement.childNodes.Length <> 1 then
    begin
      if cds.FieldByName('Industry_Code').AsString <> '0' then
      begin
        cds.Edit;
        cds.FieldByName('Industry_Code').AsString := '0';
        cds.Post;
        sql := 'Select I.Id' +
          ' From IndustryCode I' +
          ' Where I.Budget_Id = ? and I.Org_Id = 0 and I.Code = ?';
        Query.AddStr(cds.FieldByName('Budget_Id').AsString);
        Query.AddStr(cds.FieldByName('Industry_Code').AsString);
        Xml := CreateOleObject('Microsoft.XmlDom');
        Xml.LoadXML(Query.Run(sql));
        if Xml.documentElement.childNodes.Length = 1 then
        begin
          cds.Edit;
          cds.FieldByName('Industrycode_Id').AsString :=
            Xml.documentElement.childNodes.Item[0].getAttribute('ID');
          cds.Post;
        end
        else begin
          SetMessage('Не найден ID системного отраслевого кода с нулевым значением');
          Unclassified := True;
        end;
      end
      else begin
        SetMessage('Не найден ID системного отраслевого кода с нулевым значением');
        Unclassified := True;
      end;
    end
    else begin
      cds.Edit;
      cds.FieldByName('Industrycode_Id').AsString :=
        Xml.documentElement.childNodes.Item[0].getAttribute('ID');
      cds.Post;
    end;
  end;
  
  //КВФО
  if not Unclassified then
  begin
    //проверяем найденные счет и отраслевой код подпадает под маски
    sql := 'Select Accountnumber_Mask, Industrycode_Mask, Fsr_Id' +
      ' From AubuclassifiersRules' +
      ' Where 1 = 1';
    if AzkCompareVersion('2.26.46.1') < 0 then
      sql := sql + ' and Unknown_Flag = 0';
    if cds.FieldByName('Grantinvestment_Code').AsString <> '0' then
    begin
      sql := sql + ' and GrantinvestmentType = ?';
      Query.AddStr(cds.FieldByName('Grantinvestment_Type').AsString);
    end;
    Xml :=  CreateOleObject('Microsoft.XmlDom');
    Xml.LoadXML(Query.Run(sql));
    Xml := Xml.documentElement;
    isOneMask := False;
    for i := 0 to Xml.childNodes.Length - 1 do
    begin
      Xml := Xml.childNodes.Item[i];
      if cds.FieldByName('Industry_Code').AsString = '0' then
      begin
        if (MatchesMask(cds.FieldByName('LS_Number').asString,
          Xml.getAttribute('ACCOUNTNUMBER_MASK'))) then
          if not isOneMask then
          begin
            isOneMask := True;
            cds.Edit;
            cds.FieldByName('Fsr_Id').AsString := Xml.getAttribute('FSR_ID');
            cds.Post;
          end
          else begin
            isOneMask := False;
            SetMessage('Маска счета не совпадает с правилом соответствия классификаторов');
            Break;
          end;
      end
      else begin
        if (MatchesMask(cds.FieldByName('LS_Number').asString,
          Xml.getAttribute('ACCOUNTNUMBER_MASK')))
            and (MatchesMask(cds.FieldByName('Industry_Code').asString,
              Xml.getAttribute('INDUSTRYCODE_MASK'))) then
          if not isOneMask then
          begin
            isOneMask := True;
            cds.Edit;
            cds.FieldByName('Fsr_Id').AsString := Xml.getAttribute('FSR_ID');
            cds.Post;
          end
          else begin
            isOneMask := False;
            SetMessage('Маски счета и отраслевого кода не совпадают с правилом' +
              ' соответствия классификаторов');
            Break;
          end;
      end;
      Xml := Xml.parentNode;
    end;
    Unclassified := not isOneMask;
    if Unclassified then
      SetMessage('Не найдены правила соответствия классификаторов' +
        ' по типу Кода субсидии или маска счета не совпадает с полученными' +
        ' правилами');
  end;
  
  if Unclassified then
  begin
    if AzkCompareVersion('2.26.46.1') < 0 then
    begin
      Xml :=  CreateOleObject('Microsoft.XmlDom');
      Xml.LoadXML(Query.Run('Select Accountnumber_Mask Acc, Industrycode_Mask Code, Fsr_Id' +
        ' From AubuclassifiersRules Where Unknown_Flag = 1'));
      if Xml.documentElement.childNodes.Length <> 1 then
      begin
        SetMessage('Зачисление неклассифицированных, причина: ' +
          cds.FieldByName('ResText').asString +
          '. Контроль не пройден: В правилах соответствия классификаторов' +
          ' не найдено однозначно правила невыясненных поступлений');
        Exit;
      end;
      Xml := Xml.documentElement.childNodes.Item[0];
      cds.Edit;
      cds.FieldByName('LS_Number').asString := Xml.getAttribute('ACC');
      cds.FieldByName('Industry_Code').asString := Xml.getAttribute('CODE');
      cds.FieldByName('Fsr_Id').asString := Xml.getAttribute('FSR_ID');
      cds.Post;
      //получаем Id лицевого счета
      sql := 'Select Ls.Id Acc_Id' +
        ' From OrgAccount Ls' +
        ' Join Org O on O.Id = Ls.Org_Id' +
        ' Join OrgAccount Bs on Bs.Id = Ls.KeeperAcc_Id' +
        ' Where Ls.Org_Id = ? and Bs.Id = ? and Ls.OrgAccType_Id = 1' +
        '   and Ls.Close_Date is null and Ls.Budget_Flag = 0 and Ls.Account_Number = ?' +
        ' Union' +
        ' Select Ls.Id Acc_Id' +
        ' From OrgAccount Ls' +
        ' Join Org O on O.Id = Ls.Org_Id' +
        ' Join OrgAccount Bs on Bs.Id = Ls.ExecuterAcc_Id' +
        ' Where Ls.Org_Id = ? and Bs.Id = ? and Ls.OrgAccType_Id = 5' +
        '   and Ls.Close_Date is null and Ls.Budget_Flag = 0 and Ls.Account_Number = ?';
      Query.AddStr(cds.FieldByName('Rec_Id').AsString);
      Query.AddStr(cds.FieldByName('Rec_Acc_Id').AsString);
      Query.AddStr(cds.FieldByName('LS_Number').asString);
      Query.AddStr(cds.FieldByName('Rec_Id').AsString);
      Query.AddStr(cds.FieldByName('Rec_Acc_Id').AsString);
      Query.AddStr(cds.FieldByName('LS_Number').asString);
      Xml :=  CreateOleObject('Microsoft.XmlDom');
      Xml.LoadXML(Query.Run(sql));
      if Xml.documentElement.childNodes.Length = 1 then
      begin
        Xml := Xml.documentElement.childNodes.Item[0];
        cds.Edit;
        cds.FieldByName('LS_Id').AsString := Xml.getAttribute('ACC_ID');
        cds.Post;
      end
      else begin
        SetMessage('Зачисление неклассифицированных, причина: ' +
          cds.FieldByName('ResText').asString +
            '. Контроль не пройден: Не найден лс по правилу соответствия для' +
            ' невыясненных поступлений');
        Exit;
      end;
      // проверка отраслевого кода на присутсвие в базе
      sql := 'Select I.Id' +
        ' From IndustryCode I' +
        ' Where I.Budget_Id = ? and I.Org_Id = 0 and I.Code = ?';
      Query.AddStr(cds.FieldByName('Budget_Id').AsString);
      Query.AddStr(cds.FieldByName('Industry_Code').AsString);
      Xml := CreateOleObject('Microsoft.XmlDom');
      Xml.LoadXML(Query.Run(sql));
      if Xml.documentElement.childNodes.Length = 1 then
      begin
        Xml := Xml.documentElement.childNodes.Item[0];
        cds.Edit;
        cds.FieldByName('IndustryCode_Id').AsString := Xml.getAttribute('ID');
        cds.Post;
      end
      else begin
        SetMessage('Зачисление неклассифицированных, причина: ' +
          cds.FieldByName('ResText').asString +
            '. Контроль не пройден: Не найден отраслевой код по правилу соответствия для' +
            ' невыясненных поступлений');
        Exit;
      end;
      cds.Edit;
      cds.FieldByName('Enroll').AsInteger := 1;
      cds.FieldByName('Unclassified').AsInteger := 1;
      cds.Post;
      SetMessage('Зачисление неклассифицированных, причина: ' +
        cds.FieldByName('ResText').asString);
      Result := True;
    end
    else begin // версия системы выше чем 2.26.46.1
      sql := 'Select O.Id Unclass_Org_Id, O.Taxcode Unclass_Org_Taxcode,' +
        '   O.Kpp Unclass_Org_Kpp, O.Description Unclass_Org_Name, Oa.Id Ls_Id,' +
        '   Oa.Account_Number Ls_Number' +
        ' From Payorder P' +
        ' Join BudgetOrgAccount B on P.Rec_Acc_Id = B.OrgAccount_Id' +
        '   and P.Budget_Id = B.Budget_Id' +
        ' Join OrgAccount Oa on Oa.Id = B.Unclassified_Id' +
        ' Join Org O on O.Id = Oa.Org_Id' +
        ' Where P.Id = ? and B.BudgetOrgAccountType_Id = 1';
      Query.AddStr(cds.FieldByName('Id').asString);
      Xml := CreateOleObject('Microsoft.XmlDom');
      Xml.LoadXML(Query.Run(sql));
      Xml := Xml.documentElement.childNodes;
      if (Xml.Length = 1) and (Xml.Item[0].getAttribute('LS_ID') <> '') then
      begin
        cds.Edit;
        cds.FieldByName('Unclass_Org_Id').asString :=
          Xml.Item[0].getAttribute('UNCLASS_ORG_ID');
        cds.FieldByName('Unclass_Org_Taxcode').asString :=
          Xml.Item[0].getAttribute('UNCLASS_ORG_TAXCODE');
        cds.FieldByName('Unclass_Org_Kpp').asString :=
          Xml.Item[0].getAttribute('UNCLASS_ORG_KPP');
        cds.FieldByName('Unclass_Org_Name').asString :=
          Xml.Item[0].getAttribute('UNCLASS_ORG_NAME');
        cds.FieldByName('Ls_Id').asString :=
          Xml.Item[0].getAttribute('LS_ID');
        cds.FieldByName('Ls_Number').asString :=
          Xml.Item[0].getAttribute('LS_NUMBER');
        cds.Post;
      end
      else begin
        SetMessage('Зачисление неклассифицированных, причина: ' +
          cds.FieldByName('ResText').asString +
            '. Контроль не пройден: Не заполнен лицевой счет для учета' +
            ' невыясненных');
        Exit;
      end;
      //получает данные по кодам для неклассифицированных из системных параметров
      Xml := GetValueFromSysparam('aubu.unclassified.rules.' +
        cds.FieldByName('Budget_Id').asString);
      if VarIsNull(Xml) then
      begin
        SetMessage('Зачисление неклассифицированных, причина: ' +
          cds.FieldByName('ResText').asString +
            '. Контроль не пройден: Не задана настройка классификации для' +
            ' невыясненных');
        Exit;
      end;
      if (Xml.documentElement.getAttribute('KESR_CODE') <> '')
        and (Xml.documentElement.getAttribute('INDUSTRYCODE_ID') <> '')
        and (Xml.documentElement.getAttribute('FSR_ID') <> '') then
      begin
        cds.Edit;
        cds.FieldByName('Kesr_Code').AsString :=
          Xml.documentElement.getAttribute('KESR_CODE');
        cds.FieldByName('Industrycode_Id').AsString :=
          Xml.documentElement.getAttribute('INDUSTRYCODE_ID');
        cds.FieldByName('Fsr_Id').AsString :=
          Xml.documentElement.getAttribute('FSR_ID');
        cds.Post;
      end
      else begin
        SetMessage('Зачисление неклассифицированных, причина: ' +
          cds.FieldByName('ResText').asString +
            '. Контроль не пройден: Не заполнена настройка классификации для' +
            ' невыясненных');
        Exit;
      end;
      //получает Id системного(0-го) кода субсидии и инвестиции
      sql := ' Select Id' +
        ' From GrantInvestment' +
        ' Where Org_Id = 0 and Budget_Id = ? and Code = ''0''';
      Query.AddStr(cds.FieldByName('Budget_Id').asString);
      Xml := CreateOleObject('Microsoft.XmlDom');
      Xml.LoadXML(Query.Run(sql));
      if Xml.documentElement.childNodes.Length = 1 then
      begin
        cds.Edit;
        cds.FieldByName('Grantinvestment_Id').AsString :=
          Xml.documentElement.childNodes.Item[0].getAttribute('ID');
        cds.Post;
      end
      else begin
        SetMessage('Зачисление неклассифицированных, причина: ' +
          cds.FieldByName('ResText').asString +
            '. Контроль не пройден: Не найден ID системного кода субсидии с' +
            ' нулевым значением');
        Exit;
      end;
      cds.Edit;
      cds.FieldByName('Enroll').AsInteger := 1;
      cds.FieldByName('Unclassified').AsInteger := 1;
      cds.Post;
      SetMessage('Зачисление неклассифицированных, причина: ' +
        cds.FieldByName('ResText').asString);
      Result := True;
    end;
  end
  else begin
    cds.Edit;
    cds.FieldByName('Enroll').AsInteger := 1;
    cds.FieldByName('Unclassified').AsInteger := 0;
    cds.Post;
    SetMessage('Контроль пройден');
    Result := True;
  end;
end; {End CheckPayOrder}

function ObjectName: String;
begin
  Result := 'Общий';
end; {End ObjectName}

//Ищет Id л/с. По наименованию счета ищем сначало его вхождение
//в наименование получателя из выписки, не нашли там, ищем в основании платежа.
//Где нить нашли - вернули True и Id записали в cds LS_ID, иначе вернули False.
//MaskXml - возвращает все маски лс, под которые попал найденный лс.
function isSearchAccount(cds: TClientDataSet; Xml: Variant): Boolean;
var
  i: Integer;
  isFound: Boolean;
begin
  Result := False;
  cds.Edit;
  cds.FieldByName('LS_ID').asString := '';
  cds.Post;
  Xml := Xml.documentElement;
  isFound := False;
  //ищем в наименовании получателя
  for i := 0 to Xml.ChildNodes.Length - 1 do
  begin
    Xml := Xml.ChildNodes.Item[i];
    isFound := Pos(Xml.getAttribute('ACCOUNT_NUMBER'),
      cds.FieldByName('Org_Name').asString) > 0;
    if (not Result) and (isFound) then
    begin
      Result := True;
      cds.Edit;
      cds.FieldByName('LS_ID').asString := Xml.getAttribute('ID');
      cds.FieldByName('LS_Number').asString := Xml.getAttribute('ACCOUNT_NUMBER');
      cds.Post;
    end
    else if isFound then
    begin
      //нашелся дубль
      Result := False;
      Xml := Xml.parentNode;
      Break;
    end;
    Xml := Xml.parentNode;
  end;
  isFound := False;
  //ищем в основании платежа
  if not Result then
    for i := 0 to Xml.ChildNodes.Length - 1 do
    begin
      Xml := Xml.ChildNodes.Item[i];
      isFound := Pos(Xml.getAttribute('ACCOUNT_NUMBER'),
        cds.FieldByName('Description').asString) > 0;
      if (not Result) and (isFound) then
      begin
        Result := True;
        cds.Edit;
        cds.FieldByName('LS_ID').asString := Xml.getAttribute('ID');
        cds.FieldByName('LS_Number').asString := Xml.getAttribute('ACCOUNT_NUMBER');
        cds.Post;
      end
      else if isFound then
      begin
        //нашелся дубль
        Result := False;
        Xml := Xml.parentNode;
        Break;
      end;
      Xml := Xml.parentNode;
    end;
  Xml := Xml.ownerDocument;
end;

//разбирает основание платежа.
//параметры:
//cds - набор данных
//keyword - ключевое слово
//если в основании платежа не встречаются ключевые слова или встречаются более
//одного раза то False. В зависимости от ключевого слова заполняются поля в наборе
//данных
function isParceDescription(cds: TClientDataSet; Keyword: String): Boolean;
var
  i, DescLength, offsetKeyword: Integer;
  Description, Code: String;
begin
  Result := False;
  Code := '';
  Description := cds.FieldByName('Description').asString;
  DescLength := Length(Description);
  offsetKeyword := Length(Keyword) + 1;
  Keyword := LowerCase(Keyword);
  i := Pos(Keyword, LowerCase(Description));
  if (i > 0) and
    (Pos(Keyword, Copy(LowerCase(Description), i + 1, DescLength - i)) > 0) then
    //дубль
    Exit
  else if i > 0 then
  begin
    //увеличиваем индекс на длину ключевого слова + пробел
    i := i + offsetKeyword;
    //между ключевым словом и кодом должен быть пробел
    if (i <= DescLength) and (Description[i - 1] = ' ') then
      while (i <= DescLength) and (Description[i] <> ' ') do
      begin
        Code := Code + Description[i];
        inc(i);
      end;
  end;
  Result := Code <> '';
  if Result then
  begin
    case Keyword of
      'код субсидии':
        begin
          cds.Edit;
          cds.FieldByName('GrantInvestment_Code').asString := Code;
          cds.Post;
        end;
      'отр.код':
        begin
          cds.Edit;
          cds.FieldByName('Industry_Code').asString := Copy(Code, 1, 17);
          cds.FieldByName('Kesr_Code').asString := Copy(Code, 18, 3);
          cds.Post;
        end;
      'косгу':
        begin
          cds.Edit;
          cds.FieldByName('Kesr_Code').asString := Copy(Code, 1, 3);
          cds.Post;
        end;
    end;
  end;
end;

//получает данные по кодам невыясненных поступлений из системных параметров
function GetValueFromSysparam(param_name: String): Variant;
var
  Xml: Variant;
begin
  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
    Result := CreateOleObject('Microsoft.XmlDom');
    Result.loadXml(Xml.items[0].firstChild.data);
  end;
end;

begin
end.