{~FillLineED24_21918_VI_VJ_VK
  exchange #3101 (ацк-ф 21918)
  ФТ-1:при загрузке выписок по конфигурациям Imp_FK_VJ, Imp_FK_VK, Imp_FK_VI
    формировать из файла BD для ЭД класса 24формировать аналитическую строку
    (бюджетную строку не рассматриваем), если блок BDPDST имеет непустые
    значения KBK  и TYPE_KBK и/или ADD_KLASS. Иначе не формировать строку.
  ФТ-2: Если значение ADD_КLASS не пустое, то присваивать его значение полю
    "Код Субсидии" (проверка в справочнике стандартная, замена на "не указана"
    по стандартному условию). Иначе заполнять системным "Не указана".
  ФТ-3: Если поле "Код субсидии" имеет значение отличное от "Не указана",
    то значение КВФО определять из поля "Тип субсидии" (брать значение
    поля "КВФО") карточки редактирования кода субсидии. Иначе заполнять
    по правилу из значения двух первых знаков лицевого счета получателя
    (30 или 20 = 8, 21 или 31 = 9) - по параметру aLS_FSR.
  ФТ-4: Значение отраслевого кода определять из справочника соответствия
    классификаторов АУ/БУ по значению лицевого счета получателя + КВФО,
    если определн однозначно, то заполнять найденным значением,
    иначе системным "Не указана". - по параметру aLS_GI}
function FillLineED24_21918_VI_VJ_VK( aBudgetID: string;
                                       aXmlLineED, aXmlBDPDST: Variant;
                                       aOrgID, aLS_FSR, aLS_GI: string;
                                       aClassED: string): boolean;
var
  xID: string;
  xFoundGrantDefault: string;
  xAUBU_FSR_ID: string;
begin

    try
      Result := TRUE;

      // поле anal_kind обязательное =аналитическая строка
      aXmlLineED.SetAttribute( 'ANAL_KIND', '3');

      // exchange #3081
      // заполнение полей для ау/бу (AUBU_xxx) для эд 24го класса
      if NOT FillAndCheck_LineED_AuBu_by3081(
                            aBudgetID,
                            aXmlLineED,
                            GetNodeAttributeEx( aXmlBDPDST, 'KBK'),
                            GetNodeAttributeEx( aXmlBDPDST, 'TYPE_KBK'),
                            aClassED,
                            5,
                            aOrgID)
        then begin
          WriteInfo( 'ЭД не создан. Не найдены коды БК для аналитической строки.',
                      True);
          Result := FALSE;
        end;

      // exchange #3081 - направление платежа
      case aClassED of
        '5': UpdateLineED_AuBu_by3081_Direction( aXmlLineED, 2);  // эд 5й
       '24': UpdateLineED_AuBu_by3081_Direction( aXmlLineED, 3);  // эд 24й
      end;//case//

      // код субсидии
      FillGrantinvestment2979( aBudgetID,
                               aXmlLineED,
                               GetNodeAttributeEx( aXmlBDPDST, 'ADD_KLASS'),
                               aOrgID,
                               'AUBU_GRANTINVESTMENT_ID',
                               FALSE);

      xID := GetNodeAttributeEx( aXmlLineED, 'AUBU_GRANTINVESTMENT_ID');

      // поле "код субсидии и инвестиции" заполняем из "код субсидии"
      // аналитической строки
      aXmlLineED.SetAttribute( 'GRANTINVESTMENT_ID', xID);

      // проверка кода субсидии на "не указано" выполняем по ID
      if StrIsEmpty( xID)
        then xFoundGrantDefault := '1'
        else xFoundGrantDefault :=
                      QueryField(  ' select count( * ) N from GrantInvestment'
                                  +' where lower(caption) like ? and id = ?',
                                   [ 'не указан%',
                                     xID],
                                   'N');

      // если код субсидии <> "не указано" берем первый квфо из типа субсидии
      if (xFoundGrantDefault = '0')
        then aXmlLineED.SetAttribute(
                      'AUBU_FSR_ID',
                      QueryField(   ' select t.fsr_id Z'
                                   +' from GRANTINVTYPE_FINSOURCE t'
                                   +' join GrantInvestment g on'
                                   +' t.grantinvestmenttype_id = g.ftype'
                                   +' where g.id=?',
                                   [ xID],
                                   'Z'))
        else
          case COPY( aLS_FSR, 1, 2) of
            '30','20': aXmlLineED.SetAttribute( 'AUBU_FSR_ID', '8');
            '31','21': aXmlLineED.SetAttribute( 'AUBU_FSR_ID', '9');
            else       aXmlLineED.SetAttribute( 'AUBU_FSR_ID', '0');
          end;//case//

      // отр код
      xAUBU_FSR_ID := GetNodeAttributeEx( aXmlLineED, 'AUBU_FSR_ID');
      if (QueryField( ' select count( * ) Z from AUBUCLASSIFIERSRULES r'
                     +' where r.accountnumber_mask=? and r.fsr_id=?'
                     +' and r.budget_id=?',
                      [ aLS_GI,
                        xAUBU_FSR_ID,
                        aBudgetID],
                      'Z') = '1')
        then aXmlLineED.SetAttribute(
                      'AUBU_INDUSTRYCODE_ID',
                      QueryField( ' select r.industrycode_mask Z'
                                 +' from AUBUCLASSIFIERSRULES r'
                                 +' where r.accountnumber_mask=?'
                                 +' and r.fsr_id=? and r.budget_id=?',
                                  [ aLS_GI,
                                    xAUBU_FSR_ID,
                                    aBudgetID],
                                  'Z'))
        else aXmlLineED.SetAttribute(
                      'AUBU_INDUSTRYCODE_ID',
                      getIndustryCodeDefault( aBudgetID));
      except
        ExceptionProc( 'FillLineED24_21918_VI_VJ_VK');
    end;

end;


{~IsExistsKBK_into_BDPDST
  exchange #3101
  проверка полей кбк и типа кбк в разделе BDPDST.
  результат:
    =true - в строке заполнены поля KBK и TYPE_KBK.
    =false - пустое одно из полей или оба.}
function IsExistsKBK_into_BDPDST( aXmlBDPDST: Variant): boolean;
begin

  try
    Result := not ( (StrIsEmpty( GetNodeAttributeEx( aXmlBDPDST, 'KBK'))) or (StrIsEmpty( GetNodeAttributeEx( aXmlBDPDST, 'TYPE_KBK'))) ) ;
  except
    ExceptionProc( 'IsExistsKBK_into_BDPDST');
  end;

end;



{~CalcAmount_by_BDPDST
  exchange #3101
  суммирует у строк BDPDST раздела aXmlBDPD поля SUM и сохраняет результат
  в поле AMOUND ЭД aXmlED.
  строки, у которых поля BDPDST.KBK и TYPE_KBK пустые в подсчете
  сумм не учитываются.
  если есть единственная строка BDPDST то сумма берется оттуда независимо
  от заполнения кбк.
  возвращает:
    >0 - если есть строки с заполненным кбк
    =0 - есть одна стрка без кбк: это для безстрокового эд.
    =-1 - если все строки пустые}
function CalcAmount_by_BDPDST( aXmlED, aXmlBDPD: Variant): integer;
var
  xAmount, xCurr: Currency;
  i: integer;
//  xNode: Variant;
  xCountFillLines: integer;
begin

    try
      Result := -1;
      if (aXmlBDPD.childNodes.Length <= 0) then EXIT;

      //инициализим сумму шапки
      xAmount := 0.0;
      for i := 0 to aXmlBDPD.childNodes.Length - 1 do
        if CurrAttributeIsNotZero_( aXmlBDPD.childNodes.Item[ i], 'SUM', xCurr)
          then xAmount := xAmount + xCurr;
      SetCurrAttribute_( aXmlED, 'AMOUNT', xAmount);

      // проверка заполнение КБК в строках
      xCountFillLines := 0;
      if (aXmlBDPD.childNodes.Length = 1) then begin
        if IsExistsKBK_into_BDPDST( aXmlBDPD.childNodes.Item[ 0])
          then INC( xCountFillLines)
          else aXmlED.SetAttribute('NOROW', 'True');
      end else begin
        for i := 0 to aXmlBDPD.childNodes.Length - 1 do
          if IsExistsKBK_into_BDPDST( aXmlBDPD.childNodes.Item[ i])
            then INC( xCountFillLines);
        // если есть несколько разделов BDPDST и все они пустые,
        // тогда результат функции должен быть отрицательным,
        // что говорит о том, эд с такими строками создать нельзя.
        if (xCountFillLines <= 0)
          then xCountFillLines := -1;
      end;
      Result := xCountFillLines;
      except
        ExceptionProc( 'CalcAmount_by_BDPDST');
    end;

end;


{~DoCopyKBK_from_BDPDST
  exchange #3101
  копируем поля кбк из раздела BDPDST (aXmlBDPDST)
  в раздел строки эд aXmlED_Line.

  это нужно для старого механизма проверки кбк функцией CheckKBK.
  но в принципе это лишние поля для xml строки эд!

  реализовано вместо копирования всех полей раздела BDPDST в строку ЭД
  в загрузчике VI/VJ/VK по старому механизму.}
procedure DoCopyKBK_from_BDPDST( aXmlBDPDST, aXmlED_Line: Variant);
begin

    try
      CopyAttrValue( aXmlBDPDST, 'KBK'        , aXmlED_Line, 'KBK');
      CopyAttrValue( aXmlBDPDST, 'TYPE_KBK'   , aXmlED_Line, 'TYPE_KBK');
      CopyAttrValue( aXmlBDPDST, 'ADD_KLASS'  , aXmlED_Line, 'ADD_KLASS');
      except
        ExceptionProc( 'DoCopyKBK_from_BDPDST');
    end;

end;


{~DoSearch_BDPD_by_GUID
  поиск разделов BDPD с подразделами BDPDST по VJ.GUID/VI.GUID_DOC.
  результат формируется в переменной aXmlBDPD.
  результат:
    =true - раздел BDPD найден и сформирован;
    =false - раздел по GUID не найден.}
function DoSearch_BDPD_by_GUID( aGuidList: TStrings;
                                aXmlVJ: variant;
                                aXmlBD: variant;
                                aGuidFieldName: string;
                                var aXmlBDPD: Variant): boolean;
var
  xIndex: Integer;
  xGUID: string;
begin

    try
      Result := FALSE;
      aXmlBDPD := NULL;

      xGUID := TRIM( GetNodeAttributeEx( aXmlVJ, aGuidFieldName));

      // exchange #2571
      // пропускать строку, в которой поле GUID не указано
      if StrIsEmpty( xGUID) then begin
        WriteInfo(
            FORMAT( 'В документе %s номер %s от %s не заполнено поле %s.',
                    [ GetNodeAttributeEx( aXmlVJ, 'NAME_DOC'),
                      GetNodeAttributeEx( aXmlVJ, 'NUM_DOC'),
                      GetNodeAttributeEx( aXmlVJ, 'DATE_DOC'),
                      aGuidFieldName]));

        Exit;
      end;

      // доработка с учетом изменения имен файлов схем
      LoadSchema( GetFileNameSchemaTFF( 'bd_txbd*'));

      WriteLog(
            FORMAT( 'Данные строки файла: Марк.стр.=%s, Guid документа=%s'
                   +', подтвержд.документ=%s',
                    [ aXmlVJ.NodeName,
                      xGUID,
                      GetNodeAttributeEx( aXmlVJ, 'NAME_DOC')]),
            True);

      //ищем по GUID информацию из расчетных документов.
      WriteLog(
            FORMAT( 'Поиск документа по %s = %s',
                    [ aGuidFieldName,
                      xGUID]));

      xIndex := aGuidList.indexOfName( xGUID);
      if xIndex < 0 then begin
        // exchange #2571
        // изменено сообщение, если по GUID строка не найдена в файле BD
        WriteInfo( FORMAT( 'Документ %s номер %s от %s не найден в связанном файле BD.',
                            [ GetNodeAttributeEx( aXmlVJ, 'NAME_DOC'),
                              GetNodeAttributeEx( aXmlVJ, 'NUM_DOC'),
                              GetNodeAttributeEx( aXmlVJ, 'DATE_DOC')]));

        Exit;
      end;

      xIndex := StrToInt(aGuidList.ValueFromIndex(xIndex));
      aXmlBDPD := aXmlBD.childNodes.items[xIndex];
      Inc(xIndex);
      while aXmlBD.childNodes.items[xIndex].nodeName <> 'BDPD' do begin
        aXmlBDPD.appendChild(aXmlBD.childNodes.items[xIndex].cloneNode(False));
        Inc(xIndex);
        if xIndex > aXmlBD.childNodes.length - 1
          then Break;
      end;

      Result := TRUE;
      except
        ExceptionProc( 'DoSearch_BDPD_by_GUID');
    end;

end;


begin
end.
