//Exchange #2295
function CheckPayOrder_Ekaterinburg: Boolean;
var
  xIndustryCode: string;   // exchange #2732
  xIndustryCodeDef: string;
  
  //результат поиска отраслевого кода и кода субсиди
  //для счетов в 5,6 разряде которых указано 10 или 20, значения:
  //0 - не нашли ни отр.код ни кода субсидии
  //1 - нашли что то одно: либо код субсидии либо отр.код
  //2 - нашли и код субсидии и отраслевой код.
  xFindIndustryGrantInvestCode: Integer;

  Unclassified, isOneMask, ls1020, ls1121, ls1223: Boolean;
begin
    try
      Result := False;

      if NOT vIsAzkVersion2_26_46_11 then begin
        CDSListField_Message('Модуль проверки работает начиная с версии АЦК-Финансы 2.26.46.11');
        Exit;
      end;

      //проверяются только документы, у которых счет получателя совпал со счетом
      //указанным в справочнике Бухгалтерия-Настройка счетов, поле расчетный счет,
      //тип счета "Счет для учета операций БУ/АУ".
      if NOT DoCheckRecAccountGeneral then EXIT;

      CDSListField_Enroll( NULL);

      //устанавливаем флаг неклассифицированных поступлений
      Unclassified := False;

      //определяет Id получателя из выписки
      if NOT DoCheckOrg( Unclassified) then EXIT;

      //лс
      if (not Unclassified) then
        if NOT DoSearchOrgAccount( 1, 3, Unclassified)
          then EXIT;

      //инициализирует значения отраслевого кода, косгу и кода субсидии
      CDSListField_Kesr_Code( '');
      CDSListField_Industry_Code( '');
      CDSListField_Industrycode_Id( '');

      xFindIndustryGrantInvestCode := 0;

      // сброс полей описания кода субсидии
      DoResetGrantInvestment;

      //флаги необходимых номеров в нужных разрядах лицевых счетов
      ls1020 := Copy( CDSListField_LS_Number_Get, 5, 2) in ['10', '20'];
      ls1121 := Copy( CDSListField_LS_Number_Get, 5, 2) in ['11', '21'];
      ls1223 :=
        Copy(CDSListField_LS_Number_Get, 5, 2) in ['12', '13', '22', '23'];

      //получает код субсидии
      if (not Unclassified) then begin
        if (ls1121) or (ls1020) then begin
          if (not isParceDescription_Ekaterinburg({cds,} 'код субсидии')) then begin
            if ls1121 then begin
              CDSListField_Message('Не удалось получить код субсидии из назначения платежа');
              Unclassified := True;
            end;
          end else begin
            if StringReplace(CDSListField_GrantInvestment_Code_Get{cds.FieldByName('GrantInvestment_Code').AsString}, '0', '') = '' then begin
              CDSListField_Message('В назначении платежа указан нулевой код субсидии');
              Unclassified := True;
              // #2369 подставляем описание системного кода субсидии и инвестиции
              DoGrantInvestmentSetSystem;//( cds);
            end else
              if ls1020 then Inc(xFindIndustryGrantInvestCode);
          end;
        end else begin
          //если код субсидии указан в других счетах то неклассифицированные
          if isParceDescription_Ekaterinburg({cds, }'код субсидии') then begin
            CDSListField_Message(
                 'Указан код субсидии в назначении для счетов, у которых'
                +' в 5 и 6 разряде лс нет значений 10, 11, 20, 21');
            Unclassified := True;
          end else begin
            // #2369 подставляем описание системного кода субсидии и инвестиции
            DoGrantInvestmentSetSystem{( cds)};
          end;
        end;
      end;

      //проверяет код субсидии в базе
      if (not Unclassified) then
        // Exchange 2363
        // если код субсидии не распознан как системный то нужно найти
        // код субсидии из справочника. при этом организация должна быть указана!
        if DoGrantInvestmentValidate({ cds,} FALSE)
          then Unclassified := True;

      //получает косгу и отраслевой код
      // exchange #2732
      // Если в пятом-шестом разрядах ЛС стоят значения: 10, 20,
      // Код субсидии указан в Назначении платежа, то:
      // 1. если указан отр.код в назначении платежа - ставим на невыясненные
      // 2. если заполнен Pi_Budget_Code, значением, отличным от 0, - ставим на
      //   невыясненные.
      // 3. если Pi_Budget_Code запонен "0" (не 20ть нулей, а один ноль) или пусто,
      // не ставим на невыясненные, отр.код в 193 классе заполнить не пытаемся
      // (ставим системное значение 0).
      // согласовано с АО: если поле Pi_Budget_Code не заполнено (или содержит
      // один ноль), то отр код ищется в назначениии.
      // если Pi_Budget_Code имеет несколько символов или все нулевые, то
      // отр.код и КОСГУ берется из Pi_Budget_Code.

      // получаем значение Pi_Budget_Code и если там первые 17 знаков = нулю,
      // то считаем что поле Pi_Budget_Code не заполнено.
      // при этом код удобнее реализовать через промежуточную локальную
      // переменную, нежели каждый раз обращаться к полю записи.
      xIndustryCode := CDSListField_Pi_Budget_Code_Get;
      if Copy(xIndustryCode, 1, 17) = '00000000000000000'  //17 нулей   (Exchange, #3250)
        then xIndustryCode := '';

      if (not Unclassified) and (xIndustryCode <> '') then
      begin
        //ищет отраслевой код если в 5 и 6 разрядах лс стоит 10, 20, 12, 13, 22, 23
        if (ls1223) or (ls1020) then begin
          CDSListField_Industry_Code( Copy(xIndustryCode, 1, 17));
          CDSListField_Kesr_Code( Copy(xIndustryCode, 18, 3));
          if ls1020 then Inc(xFindIndustryGrantInvestCode);
        end;
      end else
        if (not Unclassified) and (xIndustryCode = '') then begin
          if (ls1223) or (ls1020) then begin
            if not isParceDescription_Ekaterinburg('отр.код') then begin
              if ls1223 then begin
                CDSListField_Message(
                    'Не удалось получить отраслевой код и КОСГУ из назначения платежа');
                Unclassified := True;
              end;
            end else begin
              if ls1020 then Inc(xFindIndustryGrantInvestCode);
            end;
          end;
        end;

      // эта проверка (только для случая, когда в пятом-шестом разрядах ЛС стоят
      // значения: 10, 20):
      // 1) если одновременно заполнен отр код (в Pi_Budget_Code или
      // назначении), то на невыясненные.
      // 2) если в Pi_Budget_Code пусто или один ноль, и отр кода в назначении нет
      // то тоже на невыясненные.
      if (not Unclassified) and (ls1020) then begin
        if xFindIndustryGrantInvestCode <> 1 then begin
          Unclassified := True;
          if (xFindIndustryGrantInvestCode = 0)
            then CDSListField_Message(
                      'Не указан ни отраслевой код ни код субсидии для счетов,'
                     +' у которых в 5 и 6 разряде лс есть значения 10 или 20')
            else CDSListField_Message(
                      'Указан отраслевой код и код субсидии для счетов,'
                     +' у которых в 5 и 6 разряде лс есть значения 10 или 20');
        end;
      end;

      xIndustryCodeDef := FormatKbk( 'INDUSTRYCODE', '0', CDSListField_Budget_Id_Get); //Exchange, #3250
      
      //проверяет отраслевой код в базе
      // exchange #2667 и #2666 исправлен поиск отр.кода.
      if (not Unclassified) then
        if (CDSListField_Industry_Code_Get <> '') then
          if (NOT CheckIndustryCode) or (CDSListField_Industry_Code_Get = xIndustryCodeDef) //( cds)
            then Unclassified := True;

      //квфо
      if (not Unclassified) then
        if DoSearchMatchLS_Ekaterinburg(ls1020)
          then Unclassified := TRUE;

      //косгу
      if not Unclassified then
      begin
        // если КОСГУ не определили выше и при этом счет 10,20, проставляем 130, иначе 180
        if (ls1020 and ((CDSListField_Fsr_Id_Get = '2') or (CDSListField_Fsr_Id_Get = '4'))) then
          Unclassified := (NOT CheckKES('130'))
        else
          Unclassified := (NOT CheckKES('180'))
      end;

      //формирование данных неклассифицированых поступлений
      if Unclassified then begin
        if NOT DoUnclassified then EXIT;
        Result := True;
      end
      else begin
        DoCheckOk;
        Result := True;
      end;
      except
        ExceptionProc( 'CheckPayOrder_Ekaterinburg');
    end;
end;
{------------------------------------------------------------------------------}
{~isParceDescription_Ekaterinburg
//разбирает основание платежа.
//параметры:
//cds - набор данных
//keyword - ключевое слово
//MustBeSpace - должен быть пробел между ключевым словом и значением
//если в основании платежа не встречаются ключевые слова или встречаются более
//одного раза то False. В зависимости от ключевого слова заполняются поля в наборе
//данных}
function isParceDescription_Ekaterinburg( aKeyword: String;
                                          aMustBeSpace: Boolean = True): Boolean;
begin
    try
      Result := ParceDescriptionCDS( aKeyword, aMustBeSpace);
      except
        ExceptionProc( 'isParceDescription_Ekaterinburg');
    end;
end;
{------------------------------------------------------------------------------}
{~DoSearchMatchLS_Ekaterinburg
  возвращает =true, если л/с не найден по маске.
  в этом случае ЭД нужно ставить на невыясненный.}
function DoSearchMatchLS_Ekaterinburg(ls1020: boolean): boolean;
  {----------------------------------------------------------------------------}
  function DoSearchMatchLS_( aSQLResult: string): boolean;
  var
    xXml: Variant;
    xRootXml: Variant;
    xNodeXml: Variant;
    i: integer;
  begin
      try
        Result := FALSE;

        xXml := vXML_Doc;
        xXml.LoadXML( aSQLResult);
        xRootXml := xXml.documentElement;

        for i := 0 to xRootXml.childNodes.Length - 1 do begin
          xNodeXml := xRootXml.childNodes.Item[i];
          if (CDSListField_Industry_Code_Get = '') then begin
            if (MatchesMask( CDSListField_LS_Number_Get,
                             xNodeXml.getAttribute('ACCOUNTNUMBER_MASK'))) then
              if not Result then begin
                Result := True;
                CDSListField_Fsr_Id( xNodeXml.getAttribute('FSR_ID'));
              end else begin
                Result := False;
                CDSListField_Message('Маска счета не совпадает с правилом соответствия классификаторов');
                Break;
              end;
          end else begin
            if (  MatchesMask( CDSListField_LS_Number_Get,
                               xNodeXml.getAttribute('ACCOUNTNUMBER_MASK'))
                and
                  MatchesMask( CDSListField_Industry_Code_Get,
                             xNodeXml.getAttribute('INDUSTRYCODE_MASK'))) then
              if not Result then begin
                Result := True;
                CDSListField_Fsr_Id( xNodeXml.getAttribute('FSR_ID'));
              end else begin
                Result := False;
                CDSListField_Message('Маски счета и отраслевого кода не совпадают с правилом' +
                  ' соответствия классификаторов');
                Break;
              end;
          end;
        end;//for//
        except
          ExceptionProc( 'DoSearchMatchLS_');
      end;
  end;
  {----------------------------------------------------------------------------}
var
  sql: string;
  xFlag: boolean;
  isOneMask: boolean;
begin
    try
      //проверяем найденные счет и отраслевой код подпадает под маски
      sql := 'Select Accountnumber_Mask, Industrycode_Mask, Fsr_Id'
            +' From AubuclassifiersRules'
              // exchange #2872 - добавлен бюджет в запрос
            + ' where BUDGET_ID=? ';

      { Exchange #2369
        Если код субсидии для строки  заполняется  значением, отличным от
        системного 0 «Не указан» (Код «0», наименование «Не указан»,
        Учредитель «Не указан», тип «Не указан»)}
      xFlag := FALSE;   // алгоритм 2
      if NOT DoGrantInvestmentCodeIsSystem then
        { если в поле «Тип субсидии» (GRANTINVESTMENTTYPE) которых указан тип,
          отличный от «Не указан» (3) - алгоритм 1}
        if (CDSListField_Grantinvestment_Type_Get <> '3')
          then xFlag := TRUE;   // алгоритм 1

      if xFlag then begin
        // алгоритм 1
        Query.AddStr( CDSListField_Budget_Id_Get);    // #2872
        Query.AddStr( CDSListField_Grantinvestment_Type_Get);
        isOneMask := DoSearchMatchLS_(
                          Query.Run(sql + ' and GrantinvestmentType = ?'));
      end else begin
        { алгоритм 2
          1)	Выбираются все правила, у которых в поле «Тип субсидии»
          (GRANTINVESTMENTTYPE) указан код с типом 3 «Не указан»}
        Query.AddStr( CDSListField_Budget_Id_Get);    // #2872
        isOneMask := DoSearchMatchLS_(
                          Query.Run(sql + ' and GrantinvestmentType = 3'));
        { 4)	Если, в результате выполнения пунктов 1-3 Алгоритма2 не было
          найдено подходящее правило, то пункты 2 и 3 Алгоритма2 выполняются
          для правил, у которых в поле «Тип субсидии» (GRANTINVESTMENTTYPE)
          указаны коды с типами 0, 1, 2.}
        if NOT isOneMask then begin
          Query.AddStr( CDSListField_Budget_Id_Get);    // #2872
          isOneMask := DoSearchMatchLS_(
                          Query.Run(sql + ' and GrantinvestmentType in (0,1,2)'));
        end;
      end;

      // если подходящего л/с не нашли - ПП не линкуется
      if isOneMask then
        Result := FALSE
      else
      begin
        // Если счет 10,20 - просто проставляем в КВФО 4
        if (ls1020) then
        begin
          CDSListField_Fsr_Id('4');
          Result := false;
        end
        else
        begin
          if NOT DoGrantInvestmentCodeIsSystem{( cds) } then
            CDSListField_Message( {cds,} 'Не найдены правила соответствия классификаторов' +
              ' по типу Кода субсидии или маска счета не совпадает с полученными' +
              ' правилами')
          else
            CDSListField_Message( {cds,} 'Не найдены правила соответствия классификаторов' +
              ' или маска счета не совпадает с полученными правилами');
          Result := TRUE;
        end;
      end;
      except
        ExceptionProc( 'DoSearchMatchLS_Ekaterinburg');
    end;
end;

begin
end.