{не удалять эту строку}
const
  cnCfgCreateDoc_Topic = 'Создание ЭД';
    cnCfgCreateDoc_215 = 'справка по внебанковским операциям';
    cnCfgCreateDoc_193 = 'распоряжение на зачисление средств на л/с';

  cnCfgIgnoreBadKBK_Topic  = 'Игнорировать незаведенные КБК';
    cnCfgIgnoreBadKBK_No   = 'нет';
  cnCfgResetBadKBK_Topic   = 'Разрешить заменять незаведенные КБК на 0';
    cnCfgResetBadKBK_Yes   = 'да';
{не удалять эту строку}

{==============================================================================}
{~ImportKBK_BH
  подпрограмма записывает в строку документа xDocLine описание КБК.
  xTypeKBK - тип КБК (10,20,31/32)
  xKBK - код КБК)
  xDocLine - строка документа
  xDocLineComment - дополнительное название строки (например: "Строка 1").
                    эта строка запишется в лог (WriteLog) и к этой строке будет
                    дописан тип словами: ( - расходны,  - дроходнаы,  - источники)}
procedure ImportKBK_BH( xTypeKBK, xKBK: string;
                        var xDocLine: Variant;
                        xDocLineComment: string;
                        aBudgetID: string);
begin
  try
    
    case xTypeKBK of
      // расходная строка
      '10': begin
            WriteLog( FORMAT( '%s - Расходная.', [ xDocLineComment]), TRUE);
            xDocLine.setAttribute('ANAL_KIND', '1');
            // exchange #3062 - отмена косгу и унификация кода
            DoEncodeKBK_R_ToXml( xKBK, xDocLine, FALSE);
            {
            // КВСР Код по БК получателя - Первые три знака KBK_RCP
            xDocLine.setAttribute( 'KADMR_CODE', COPY(xKBK, 1, 3));
            // КФСР	Код по БК получателя -	С 4 по 7 знак KBK_RCP включительно
            xDocLine.setAttribute( 'KFSR_CODE', COPY(xKBK, 4, 4));
            // КЦСР	Код по БК получателя - С 8 по 14 знак KBK_RCP включительно
            xDocLine.setAttribute( 'KCSR_CODE', COPY(xKBK, 8, 7));
            // КВР	Код по БК получателя - С 15 по 17 знак KBK_RCP включительно
            xDocLine.setAttribute( 'KVR_CODE', COPY(xKBK, 15, 3));
            // КОСГУ Код по БК получателя	- С 18 по 20 знак KBK_RCP включительно
            xDocLine.setAttribute( 'KESR_CODE', COPY(xKBK, 18, 3));
            }
            // КВФО	Устанавливать 1
            xDocLine.setAttribute( 'FSR_ID', '1');
          end;

      // источники
      '31','32': begin
            WriteLog( FORMAT( '%s - Источники.', [ xDocLineComment]), TRUE);
            xDocLine.setAttribute('ANAL_KIND', '3');
            // exchange #3062 - отмена косгу и унификация кода
            DoEncodeKBK_I_ToXml( xKBK, xDocLine, FALSE);
            {
            // Гл.администратор	Код по БК получателя: Первые три знака KBK_RCP
            xDocLine.setAttribute( 'KADMI_CODE', COPY(xKBK, 1, 3));
            // КВИ: Код по БК получателя	С 4 по 17 знак KBK_RCP включительно
            xDocLine.setAttribute( 'KI_CODE', COPY(xKBK, 4, 14));
            // КОСГУ Код по БК получателя	- С 18 по 20 знак KBK_RCP включительно
            xDocLine.setAttribute( 'KESI_CODE', COPY(xKBK, 18, 3));
            }
            // КВФО	Устанавливать 1
            xDocLine.setAttribute( 'FSI_ID', '1');
          end;

      // доходы
      '20': begin
            WriteLog( FORMAT( '%s - Доходная.', [ xDocLineComment]), TRUE);
            xDocLine.setAttribute('ANAL_KIND', '2');
            // тип дохода - =1 (доходы)
            xDocLine.setAttribute( 'KDT_CODE', '1');
            // exchange #3062 - отмена косгу и унификация кода
            DoEncodeKBK_D_ToXml( xKBK, xDocLine, FALSE);
            {
            // Гл.администратор	Код по БК получателя: Первые три знака KBK_RCP
            xDocLine.setAttribute( 'KADMD_CODE', COPY(xKBK, 1, 3));
            // КВИ: Код по БК получателя	С 4 по 17 знак KBK_RCP включительно
            xDocLine.setAttribute( 'KD_CODE', COPY(xKBK, 4, 14));
            // КОСГУ Код по БК получателя	- С 18 по 20 знак KBK_RCP включительно
            xDocLine.setAttribute( 'KESD_CODE', COPY(xKBK, 18, 3));
            }
            // КВФО	Устанавливать 1
            xDocLine.setAttribute( 'FSD_ID', '1');
          end;
    end;//case//

    // Доп.коды	- Заполнять нулями
    // exchange #2591 - символьные КБК
    // требуется вместо нулей форматировать коды с учетом маски
    xDocLine.setAttribute( 'KDF_CODE', FormatKbk( 'KDF', '0', aBudgetId));
    xDocLine.setAttribute( 'KDE_CODE', FormatKbk( 'KDE', '0', aBudgetId));
    xDocLine.setAttribute( 'KDR_CODE', FormatKbk( 'KDR', '0', aBudgetId));

    
    except
      ExceptionLog( 'Сбой скрипта: "Imp_FK_BH.ImportKBK_BH".');
  end;
end;
{==============================================================================}
{~CopyDescriptionRecipientXML
  копирование реквизитов организации из xFrom в чЕщю
  копируются: ИНН, КПП, номер и идентификатор организации.
}
procedure CopyDescriptionRecipientXML( var xFrom: Variant; var xTo: Variant);
begin
  try
    
    
    
    xTo.setAttribute( 'ORG_ID'      , GetNodeAttributeValue( xFrom, '//*/@ID'));
    xTo.setAttribute( 'ORG_TAXCODE' , GetNodeAttributeValue( xFrom, '//*/@TAXCODE'));
    xTo.setAttribute( 'ORG_KPP'     , GetNodeAttributeValue( xFrom, '//*/@KPP'));
    xTo.setAttribute( 'ORG_NAME'    , GetNodeAttributeValue( xFrom, '//*/@CAPTION'));
    {
    xTo.setAttribute( 'ORG_ID'      , xFrom.getAttribute( 'ORG_ID'));
    xTo.setAttribute( 'ORG_TAXCODE' , xFrom.getAttribute( 'ORG_TAXCODE'));
    xTo.setAttribute( 'ORG_KPP'     , xFrom.getAttribute( 'ORG_KPP'));
    xTo.setAttribute( 'ORG_NAME'    , xFrom.getAttribute( 'ORG_CAPTION'));

    xTo.setAttribute( 'ORG_ID'      , GetNodeAttributeValue( xFrom, '@ORG_ID'));
    xTo.setAttribute( 'ORG_TAXCODE' , GetNodeAttributeValue( xFrom, '@ORG_TAXCODE'));
    xTo.setAttribute( 'ORG_KPP'     , GetNodeAttributeValue( xFrom, '@ORG_KPP'));
    xTo.setAttribute( 'ORG_NAME'    , GetNodeAttributeValue( xFrom, '@ORG_CAPTION'));
    }
    
    except
      ExceptionLog( 'Сбой Imp_FK_BH_Tools.CopyDescriptionRecipientXML');
  end;
end;


function GetEstimateId_Ex(BudgetId, Org_Id, aAccount: String; Line: Variant): String;
var
  Xml: Variant;
  i,n: Integer;
  xID_List: string;
begin

    try
      Result := '';

      Xml := QueryXml( ' Select e.Id'
//                    +', oa.account_number, oa.orgacctype_id --, oa2.account_number'
                      +' From Estimate e'
//                      +' join orgaccount oa on oa.id=e.face_acc'
//--join orgaccount oa2 on oa2.id=oa.keeperacc_id
                      +' Where e.EstKind_Id in (1, 7) and e.Actual_Flag = 1'
                      +' and e.Budget_Id = ? and e.Org_Id = ?'
                      +' and ('
                      +'   exists( select * from orgaccount oa1'
                      +'            where oa1.id=e.face_acc and'
                      +'            oa1.orgacctype_id=5 and oa1.ACCOUNT_NUMBER = ?'
                      +'            and oa1.DISTRIBUTIVE_FLAG = 0 )'
                      +'  or'
                      +'   exists( select * from orgaccount oa2'
                      +'            join orgaccount oa3 on oa3.id=oa2.keeperacc_id'
                      +'            where oa2.id=e.face_acc and'
                      +'            oa2.orgacctype_id=1 and oa3.ACCOUNT_NUMBER = ?'
                      +'            and       oa2.DISTRIBUTIVE_FLAG = 0)'
                      +')',
                       [ BudgetId,
                          Org_Id,
                          aAccount,
                          aAccount]);
      // здесь проверяем, если не найдено ни одной записи, то бланк расходов
      // считаем не найденным
      n := Xml.documentElement.childNodes.Length;
      if (n <= 0) then EXIT;
      if (n = 1)
        then Result := Xml.documentElement.childNodes.item[0].getAttribute('ID')
        else begin
          // получаем список ид.через запятую
          xID_List := '';
          for i := 0 to n - 1 do begin
            if (i > 0) then xID_List := xID_List + ',';
            xID_List := xID_List
                          + Xml.documentElement.childNodes.Item[i].getAttribute('ID')
          end;//for//

          Xml := QueryXml( 'Select E.Estimate_Id Id'
                          +' From Expbudget E'
                          +' Where E.Budget_Id = ? and E.Estimate_Id in ('
                          + xID_List
                          +')   and E.Kfsr_Code = ?'
                          +'   and E.Kvr_Code = ? and E.Kesr_Code = ? '
                          +' and E.Kcsr_Code = ? and E.Kadmr_Code = ?'
                          +' Group by E.Estimate_Id',
                          [ BudgetId,
                            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')
            else Result := '';
        end;
      except
        ExceptionLog( 'Сбой QueryWork.GetEstimateId');
    end;

end;


{==============================================================================}
(*
procedure CopyDescriptionRecipientExXML( var xFrom: Variant; var xTo: Variant);
begin
  try
    
    
    
    xTo.setAttribute( 'ORG_ID'      , GetNodeAttributeValue( xFrom, '//*/@ID'));
    xTo.setAttribute( 'ORG_TAXCODE' , GetNodeAttributeValue( xFrom, '//*/@TAXCODE'));
    xTo.setAttribute( 'ORG_KPP'     , GetNodeAttributeValue( xFrom, '//*/@KPP'));
    xTo.setAttribute( 'ORG_NAME'    , GetNodeAttributeValue( xFrom, '//*/@CAPTION'));
    
    except
      ExceptionLog( 'Сбой Imp_FK_BH_Tools.CopyDescriptionRecipientExXML');
  end;
end;
*)

{==============================================================================}
{~ImportDocLine10_BH
O.Taxcode = '5221002084'
Ok.Kpp = '123456789'

and oa1.ACCOUNT_NUMBER='02323003030'   // ФК
and oac2.account_number='40201810400000100016'  // ФО


  ZR:
    Result := ImportDocLine10_BH( aBudgetID,
                                  xDocLine,
                                  aBH_LS,
                                  xZR_BS_RCP,
                                  xZR_INN_RCP,
                                  xZR_KPP_RCP,
                                  xZR_LS_UBP_RCP);
  PPT:
    Result := ImportDocLine10_BH( aBudgetID,
                                  xDocLine,
                                  aBH_LS,
                                  xPPT_BS_RCP,
                                  xPPT_INN_RCP,
                                  xPPT_KPP_RCP,
                                  xPPT_LS_PAY_RCP);

}
function ImportDocLine10_BH( //var aSource: Variant;
                             aBudgetID: string;
                             var xDocLine: Variant;
                             aBH_LS,
                             xLS_UFK,    // л/с УФК
                             xINN,
                             xKPP,
                             xLS: string): integer;
var
  xRecipientID: string;
  xOrgAccountID: string;
  xEstimateID: string;
  xOrgXml: Variant;
  xOrgAccountXml: Variant;
//  xOrgID: string;
//  xOrgReceiver: string;
begin
  try
    
    try
      { бюджетополучатель
        ИНН контрагента, КПП контрагента, Лицевой счет контрагента
        Определяется по сочетанию:

        ZR:
          ИНН получателя: ZR.INN_RCP
          КПП получателя: ZR.KPP_RCP
          л/с: ZR.LS_UBP_RCP.
        PPT:
          ИНН получателя: PPT.INN_RCP
          КПП получателя: PPT.KPP_RCP
          л/с: PPT.LS_PAY_RCP.
        
        контрагента среди актуальных незакрытых организаций для данного бюджета
        с ролью "Бюджетополучатель" и имеющих счет с типом 5 нераспорядительный
        с номером, равным LS_UBP_RCP или с типом 1 нераспорядительный
        с номером счета финоргана в карточке, равным л/с}
      WriteLog('Поиск референса бюджетополучателя по ИНН и КПП', True);
      if NOT SearchRecipientID(
                aBudgetID,
                xINN,
                xKPP,
                xLS,
                'account1', '0',
                xRecipientID)
        then begin
          WriteInfo('Не определен референс бюджетополучателя');
          Result := 15;
          Exit;
        end;
      
      // копируем реквизиты организации из xml организации -> в атрибуты строки
//      CopyDescriptionRecipientXML( xOrgXml, xDocLine);
      // бюджетополучатель для строки
      xDocLine.setAttribute( 'RECIPIENT_ID', xRecipientID);

      // пробуем определить бланк расходов
      xEstimateID := GetEstimateId_Ex( aBudgetID,
                                       xRecipientID,
                                       aBH_LS,
                                       xDocLine);

      if (LENGTH( xEstimateID) > 0) then begin
        xDocLine.setAttribute('ESTIMATE_ID', xEstimateID);

        { exchange #2635
          если бланк расходов найден, проверяем, если у него заполнено поле
          счета - берем счет оттуда.}
        xOrgAccountID := QueryField( 'select FACE_ACC from estimate where ID=?',
                                      [ xEstimateID],
                                      'FACE_ACC');
        if (LENGTH( xOrgAccountID) > 0) then begin
          if (GetOrgAccountGetter_ToXML(
                  xOrgAccountXml,            // результат добавляем к строке
                  'id='+xOrgAccountID,
                  null) <> 1)
            then begin
              WriteInfo('Не найдено описание счета, указанного в бланке расходов.');
              Result := 15;
              EXIT;
            end;
        end else begin
          { Лицевой счет
            Искать с номером, равным BH.LS, нераспорядительный.
            В строке с типом КБК "Расходы" искать среди счетов
            организаии-оператора бланка расходов с типом 1 (BH.LS в
            карточке л/с) или 5 }
          if (GetOrgAccountGetter_ToXML(
                  xOrgAccountXml,            // результат добавляем к строке
                  #13#10'account1=' //xRecipientID
                    + QueryField( 'select Org_ID from estimate where ID=?',
                                  [ xEstimateID],
                                  'ORG_ID')
                 +#13#10'ls_bs='+xLS_UFK  // л/с УФК
                 +#13#10'account='+ aBH_LS
                 // exchange #2581 - только не закрытые л/с
                 +#13#10'closed=is null',
                  null) <> 1)
            then begin
              WriteInfo('Не распознан л/с из организации бланка расходов.');
              Result := 15;
              EXIT;
            end;
        end;
        //берем идентификатор л/с
        CopyXmlNodeAttributes( xOrgAccountXml, xDocLine);
        xOrgAccountID := GetNodeAttributeValue( xOrgAccountXml, '@ORGACCOUNT_ID');
  
      end else begin
(*
      { ищем описание счета из бланка расходов в справочнике счетов по номеру счета.
        это нужно для поиска бланка расхода. }
      if (GetOrgAccountGetter_ToXML(
              xOrgAccountXml,            // результат добавляем к строке
//                    'account_type=1,5'            +#13#10
              'account='+ aBH_LS,
              null) <> 1)
        then begin
          WriteInfo('Не распознан л/с');// для организации-получателя в строках.');
          Result := 15;
          EXIT;
        end;
      //берем идентификатор л/с
//      CopyXmlNodeAttributes( xOrgAccountXml, xDocLine);
      xOrgAccountID := GetNodeAttributeValue( xOrgAccountXml, '@ORGACCOUNT_ID');
      
*)
        { Лицевой счет
          Искать с номером, равным BH.LS, нераспорядительный.
          В строке с типом КБК "Расходы" искать среди счетов
          организаии-оператора бланка расходов с типом 1 (BH.LS в
          карточке л/с) или 5 }
        if (GetOrgAccountGetter_ToXML(
                xOrgAccountXml,            // результат добавляем к строке
                #13#10'account1=' + xRecipientID
               +#13#10'ls_bs='+xLS_UFK  // л/с УФК
               +#13#10'account='+ aBH_LS
               // exchange #2581 - только не закрытые л/с
               +#13#10'closed=is null',
                null) <> 1)
          then begin
            WriteInfo('Не распознан л/с для организации-получателя в строках.');
            Result := 15;
            EXIT;
          end;
        //берем идентификатор л/с
        CopyXmlNodeAttributes( xOrgAccountXml, xDocLine);
        xOrgAccountID := GetNodeAttributeValue( xOrgAccountXml, '@ORGACCOUNT_ID');
  


        { Бланк расходов
          Поиск бланка расходов производится по найденной организации
            Бюджетополучатель и счету. Смотрим бланк расходов с типами
          "Смета", "ПНО" с признаком "Актуальный", если таких несколько,
          то дополнительно искать бланк, в котором указан Лицевой счет,
          равный Счету.
            Если по организации и счету бланков нашлось несколько,
          то делаем выборку всех строк именно для тех бланков расходов,
          которые попали под условие совпадения с Организацией и счетом и
          далее ищем строку среди получившегося списка.
            По пришедшим КБК (20 символов KBK_RCP) ищем строку среди
          отфильтрованного списка строк. Если нашлась одна строка или
          несколько строк, но одного бланка расходов, то именно этот
          бланк расходов и выбираем. (аналогия поиска бланка при
          загрузке файла IK)}
  //logxml('GetEstimateId: ',xDocLine);
        xEstimateID := GetEstimateId( aBudgetID,
                                         xRecipientID,
                                         xOrgAccountID,
                                         xDocLine);
        
        if (xEstimateID = '') then begin
          WriteInfo('Не определен бланк расходов плательщика в строках.');
          Result := 15;
          Exit;
        end;
        xDocLine.setAttribute('ESTIMATE_ID', xEstimateID);

  (*
        { Лицевой счет
          Искать с номером, равным BH.LS, нераспорядительный.
          В строке с типом КБК "Расходы" искать среди счетов
          организаии-оператора бланка расходов с типом 1 (BH.LS в
          карточке л/с) или 5 }
        if (GetOrgAccountGetter_ToXML(
                xOrgAccountXml,            // результат добавляем к строке
                #13#10'account1=' //xRecipientID
                  + QueryField( 'select Org_ID from estimate where ID=?',
                                [ xEstimateID],
                                'ORG_ID')
               +#13#10'ls_bs='+xLS_UFK  // л/с УФК
               +#13#10'account='+ aBH_LS,
                null) <> 1)
          then begin
            WriteInfo('Не распознан л/с для организации-получателя в строках.');
            Result := 15;
            EXIT;
          end;
        //берем идентификатор л/с
        CopyXmlNodeAttributes( xOrgAccountXml, xDocLine);
  //      xOrgAccountID := GetNodeAttributeValue( xOrgAccountXml, '@ORGACCOUNT_ID');
  
  *)
      end;

      // exchange #2581
      // поиск РО (Расходное обязательство) перенесен непосредственно
      // в код формирования строк, поскольку поменялся код АЦК-Ф, при котором,
      // при поиске РО необходим код цели.
      // а для поиска кода цели требуется КБК и много других полей,
      // что в данном месте неизвестно.
      Result := 0;    // операция выполнена успешно
      except
        ExceptionLog( 'Сбой скрипта: "Imp_FK_BH.ImportDocLine10_BH".');
    end;
    finally

  end;
end;

{==============================================================================}
{~ImportDocLine31_BH
  ZR:
    Result := ImportDocLine31_BH( aBudgetID,
                                  xDocLine,
                                  aBH_LS,
                                  xZR_INN_RCP,
                                  xZR_KPP_RCP,
                                  xZR_LS_UBP_RCP);
  PPT:
    Result := ImportDocLine31_BH( aBudgetID,
                                  xDocLine,
                                  aBH_LS,
                                  xPPT_INN_RCP,
                                  xPPT_KPP_RCP,
                                  xPPT_BS_RCP);
  ZV:
    Result := ImportDocLine31_BH( aBudgetID,
                                  xDocLine,
                                  aBH_LS,
                                  xZVDOCPOL_INN_POL,
                                  xZVDOCPOL_KPP_POL,
                                  xZVDOCPOL_LS_POL);
}
function ImportDocLine31_BH( //var aSource: Variant;
                              aBudgetID: string;
                              var xDocLine: Variant;
                              aBH_LS,
                              xINN,
                              xKPP,
                              aINN_UBP,
                              aKPP_UBP,
                              xLS: string): integer;
var
  xXmlOrg: Variant;
  xRecipientID: string;
  xCountreAgentID: string;
  xOrgAccountXml: Variant;
{
  xOrgAccountID: string;
  xEstimateID: string;
  xOrgID: string;
  xOrgReceiver: string;
}
begin
  try
    
    try
      { ФО / Гл.администратор
          Определяется по сочетанию

        ZR:
           ИНН: INN_RCP;
           КПП: KPP_RCP;
           счет типа 7: LS_UBP_RCP;
           счет типа 6 финоргана: LS_UBP_RCP.
        PPT:
           ИНН: PPT.INN_RCP;
           КПП: PPT.KPP_RCP;
           счет типа 7: PPT.BS_RCP;
           счет типа 6 финоргана: PPT.BS_RCP.
        ZV:
           ИНН: ZVDOCPOL.INN_POL;
           КПП: ZVDOCPOL.KPP_POL;
           счет типа 7: ZVDOCPOL.LS_POL;
           счет типа 6 финоргана: ZVDOCPOL.LS_POL.

        контрагента среди актуальных незакрытых организаций для данного бюджета с
        ролью "Администрация/Финорган", "Администратор источников",
        "Гл.администратор источников" и имеющих счет с типом 7
        нераспорядительный с номером, или с типом 6
        нераспорядительный с номером счета финоргана в карточке}
      WriteLog('Поиск ФО / Гл.администратор по ИНН и КПП', True);
      if NOT SearchRecipientID_ToXML(
                aBudgetID,
                xINN,
                xKPP,
                xLS,
                'account2', '11,10,14',
                xRecipientID,
                xXmlOrg)
        then begin
          WriteInfo('Не определен ФО / Гл.администратор для источников.');
          Result := 15;
          Exit;
        end;
      
      // копируем реквизиты организации из xml организации -> в атрибуты строки
      CopyDescriptionRecipientXML( xXmlOrg, xDocLine);

      { Лицевой счет
        Искать с номером, равным BH.LS, нераспорядительный.
        В строке с типом КБК "Источники" среди счетов организации
        ФО / Гл.администратор с типом 6 (BH.LS в карточке л/с)  или 7.
        если счет четко не распознается - отменяем ЭД.}
      WriteLog( 'Описание л/с клиента...', TRUE);
      if (GetOrgAccountGetter_ToXML(
              xOrgAccountXml,            // результат добавляем к строке
              #13#10'account=' + aBH_LS
             +#13#10'ls_bs=' + xLS                 // л/с УФК
             +#13#10'account2=' + xRecipientID
             // exchange #2581 - только не закрытые л/с
             +#13#10'closed=is null',
              null) <> 1)
        then WriteLog('Не распознан л/с для ФО/Гл.администратор.', True);
        CopyXmlNodeAttributes( xOrgAccountXml, xDocLine);
//        xOrgAccountID := GetNodeAttributeValue( xOrgXml, '@ORGACCOUNT_ID');
//      CopyDescriptionRecipientXML( xOrgAccountXml, xDocLine);
      //xDocLine.SetAttribute( 'ORGACCOUNT_ID', xOrgAccountXml.

      { Контрагент:
        Краткое наименование, ИНН, КПП (ZR.INN_UBP, ZR.KPP_UBP)
        организации, найденной по ИНН+КПП среди актуальных незакрытых
        организаций. Если не найдена однозначно, заполнять значением
        Не указанна.}
      
      if SearchRecipientID(
                aBudgetID,
                aINN_UBP,
                aKPP_UBP,
                '',   // л/с не указан
                '',   // параметр л/с не нужен
                '',   // фильтр ролей организации
                xCountreAgentID)
        then xDocLine.setAttribute( 'COUNTERAGENT_ID', xCountreAgentID)
        else xDocLine.setAttribute( 'COUNTERAGENT_ID', '0');

      Result := 0;    // операция выполнена успешно
      except
        ExceptionLog( 'Сбой скрипта: "Imp_FK_BH.ImportLine31_BH".');
    end;
    finally

  end;
end;

{==============================================================================

  ZR:
    Result := ImportDocLine20_BH( aBudgetID,
                                  xDocLine,
                                  aBH_LS,
                                  xZR_BS_RCP,
                                  xZR_INN_RCP,
                                  xZR_KPP_RCP,
                                  xZR_LS_UBP_RCP);
  PPT:
    Result := ImportDocLine20_BH( aBudgetID,
                                  xDocLine,
                                  aBH_LS,
                                  xPPT_BS_PAY,
                                  xPPT_INN_RCP,
                                  xPPT_KPP_RCP,
                                  xPPT_BS_RCP);
  ZV:
    Result := ImportDocLine20_BH( aBudgetID,
                                  xDocLine,
                                  aBH_LS,
                                  xZVDOCPOL_LS_POL,
                                  xZVDOCPOL_INN_POL,
                                  xZVDOCPOL_KPP_POL,
                                  xZVDOCPOL_LS_POL);
}
function ImportDocLine20_BH( //var aSource: Variant;
                              aBudgetID: string;
                              var xDocLine: Variant;
                              aBH_LS,
                              xLS_UFK,    // л/с УФК
                              xINN,
                              xKPP,
                              aINN_UBP,
                              aKPP_UBP,
                              xLS: string): integer;
var
  xXmlOrg: Variant;
  xXmlOrgAcc: Variant;
  xOrgID: string;
  xRecipientID: string;
  xOrgReceiver: string;
  xOrgAccountXml: Variant;
  xOrgAccountID: string;
  xEstimateID: string;
begin
  try
    
    try
      { Блок полей Плательщик - обязателен
        ZR:
          ИНН плательщика: ZR.INN_UBP
          КПП плательщика: ZR.KPP_UBP
        PPT:
          ИНН плательщика: PPT.INN_RCP
          КПП плательщика: PPT.KPP_RCP
        ZV:
          ИНН плательщика: ZVDOCPOL.INN_POL
          КПП плательщика: ZVDOCPOL.KPP_POL

        Краткое наименование, ИНН, КПП организации, найденной по ИНН+КПП
        среди актуальных незакрытых организаций.
        Если не найдена однозначно, заполнять значением Не указанна.
        Территорию заполнять из карточки найденной организации.}
      
      if (SearchOrgRecipient(
                aBudgetID,
                  aINN_UBP,
                  aKPP_UBP,
                '',
                xXmlOrg) = 1)
        then begin
          // копируем атрибуты из xml организации -> в атрибуты строки
          CopyAttrValue( xXmlOrg, '//*/@ID'           , xDocLine, 'COUNTERAGENT_ID');
          CopyAttrValue( xXmlOrg, '//*/@TERRITORY_ID' , xDocLine, 'TERRITORY_ID');
          CopyAttrValue( xXmlOrg, '//*/@ID'           , xDocLine, 'PAYER_ID');
        end else begin
          xDocLine.setAttribute( 'PAYER_ID', '0');
          xDocLine.setAttribute( 'COUNTERAGENT_ID', '0');
          xDocLine.setAttribute( 'TERRITORY_ID', '0');
        end;
      { Блок полей Получатель
        Искать в справочнике Получатели доходов с признаком
        "По умолчанию" с организацией, найденной по сочетанию:

        ZR:
          ИНН плательщика: ZR.INN_UBP
          КПП плательщика: ZR.KPP_UBP
          счет с типом 8, равным: LS_UBP_RCP;
          счет с типом 9, равным: LS_UBP_RCP.
        PPT:
          ИНН плательщика: PPT.INN_RCP
          КПП плательщика: PPT.KPP_RCP
          счет с типом 8, равным: PPT.LS_PAY_RCP;
          счет с типом 9, равным: PPT.LS_PAY_RCP.
        ZV:
          ИНН плательщика: ZVDOCPOL.INN_POL
          КПП плательщика: ZVDOCPOL.KPP_POL

        (INN_RCP, KPP_RCP) контрагента среди актуальных незакрытых
        организаций для данного бюджета с ролью "Администрация/Финорган",
        "Администратор доходов", "Гл.администратор доходов" и имеющих
        счет с типом 8 нераспорядительный с номером, равным PPT.LS_PAY_RCP
        или с типом 9, равным LS_UBP_RCP.
        Счет заполнять найденным счетом.}
      WriteLog('Поиск организации получателя...', True);
      { в начале ищем с учетом справочника Получатели доходов
        с признаком По умолчанию}
      
      if NOT SearchRecipientID_ToXml(
                aBudgetID,
                xINN,
                xKPP,
                xLS,
                'account3', '11,9,13',
                xOrgID,
                xXmlOrg,
                // дополнительное поле получателя
                #13#10'fields=res.ID RECEIVER_ID_'
               +#13#10'receiver=1')
        then begin
          { если таковой не будет - тогда ищем просто организацию по ИНН+КПП}
          
          if NOT SearchRecipientID_ToXml(
                    aBudgetID,
                    xINN,
                    xKPP,
                    xLS,
                    'account3', '11,9,13',
                    xOrgID,
                    xXmlOrg)
            then begin
              WriteInfo('В строках доходов не найден получатель.');
              Result := 15;
              Exit;
            end;
        end;
      
      // копируем реквизиты организации из xml организации -> в атрибуты строки
      CopyDescriptionRecipientXML( xXmlOrg, xDocLine);
      // поле "получатель" берем как организацию из блока "получатель"
      CopyAttrValue( xXmlOrg, '//*/@ID', xDocLine, 'RECEIVER_ID');


      // описываем получателя
      if NOT GetNodeAttribute( xXmlOrg, '//*/@RECEIVER_ID_', xOrgReceiver)
        then WriteLog( 'Получатель доходов не определен.')
        else begin
          
          xDocLine.setAttribute( 'RECEIVER_ID', xOrgReceiver);
        end;
      
      { Лицевой счет
        Искать с номером, равным BH.LS, нераспорядительный.
        В строке с типом КБК "Доходы" выбор из счетов организации блока:

        PPT:
          Получатель с типом 8 или 9: PPT.BS_PAY
        ZR:
          Получатель с типом 8 или 9: ZR.BS_RCP
        ZV:
          Получатель с типом 8 или 9: ZVDOCPOL.LS_POL
        }
      if (GetOrgAccountGetter_ToXML(
              xOrgAccountXml,            // результат добавляем к строке
              #13#10'account=' + aBH_LS
             +#13#10'ls_bs=' + xLS_UFK         // л/с УФК
             +#13#10'account3=' + xOrgID
             // exchange #2581 - только не закрытые л/с
             +#13#10'closed=is null',
              null) <> 1)
        then WriteLog('Не распознан л/с для организации-получателя.', True);
      CopyXmlNodeAttributes( xOrgAccountXml, xDocLine);
//      CopyDescriptionRecipientXML( xOrgAccountXml, xDocLine);

      Result := 0;    // операция выполнена успешно
      except
        ExceptionLog( 'Сбой скрипта: "Imp_FK_BH.ImportLine20_BH".');
    end;
    finally

  end;
end;

{==============================================================================}
procedure InfoDoc215_BH( var aDoc: Variant; aHeader: string);
begin
  WriteLog( FORMAT( '%s ЭД "%s"...',
                    [ aHeader,
                      DefineAZKDocumentNumberAndData(
                          'Справка по внебанковским операциям',
                          aDoc)]),
              TRUE);
end;

{==============================================================================}
procedure InfoDoc193_BH( var aDoc: Variant; aHeader: string);
begin
  WriteLog( FORMAT( '%s ЭД "%s"...',
                    [ aHeader,
                      DefineAZKDocumentNumberAndData(
                          'Распоряжение на зачисление средств на л/с',
                          aDoc)]),
              TRUE);
end;

{==============================================================================
  BuildDoc215_BH
  подпрограмма отправляет на сервер сформированный ЭД "справка по внебанковским
  операциям". при этом формируется такой ЭД в БД.
  помимо этого выполняется логирование XML описания этого ЭД до отправки на
  сервер и после операции - получение ответа.
  
  aValidate - проверка данных без создания ЭД.
    если параметр =true, никаких ЭД не создается, поэтому сразу выходим,
    даже не описывая логов.
  
  после выполнения операции XML xDocXml будет содержать ответ сервера, а не
  исходный документ!}
function BuildDoc215_BH( var xDocXml: Variant;
                          var xDoc: Variant;
                          aValidate: boolean): boolean;
begin

    try
      Result := FALSE;
      if aValidate then EXIT;
      InfoDoc215_BH( xDoc, 'Сохранение сформированного');
      xDoc.setAttribute('action', 'insert');
      xDoc.setAttribute('class', '215');
      // Вставка и обработка.
      // после вставки документ переводится на статус "отложен"
      try

        xDocXml.loadXml( ExecXml( xDocXml.xml));

        Result := TRUE;
        except
          WriteInfo( FORMAT( 'Сбой создания ЭД - %s',
                              [ LastException.Message]));
      end;

      except
        ExceptionLog( 'Сбой BuildDoc215_BH');
    end;

end;
{==============================================================================
  Создавать ЭД "Распоряжение на зачисление средств на л/с", если
  значение поля BH.ROD_DOC равно VI, VS, VJ,  VK.
  
  aType - тип  заявки: ZR/ZV/PPT
  
  ZR:
    Result := UpdateDoc193_BH( aSource,
                               aBudgetID,
                               aBH_KOD_DOC,
                               'ZR',
                               '@DATE_ZR',
                               '@NOM_ZR',
                               '@LS_UBP_PAY',
                               '@LS_UBP_RCP',
                               xDocXml,
                               xDoc,
                               xDocLines,
                               aConfig);

  результат
     0: документ создан;
    10: такой документ уже есть в БД;
    11: нехватает параметров в исходных данных;
    12: не распознана "Заявка БУ/АУ на выплату средств";
    14: в документе ZR нет подразделов ZRST.
    15: невозможно определить бюджетополучателя
    16: если по конфигурации не создается "Распоряжение на зачисление
        средств на л/с".
}
function UpdateDoc193_BH( var aSource: Variant;
                          aBudgetID, aBH_KOD_DOC: string;
                          aType: string;
                          aFieldDate,
                          aFieldNomer,
                          aFieldPAY,
                          aFieldRCP: string;
                          var aUpdateDocXML: Variant;
                          var aUpdateDoc: Variant;
                          var aUpdateDocLines: Variant;
                          var aConfig: TStringList;
                          var xDocRecIDGRBS: string): integer;
var
  Xml: Variant;
  xOrgXml: Variant;
  xDate: string;
  xDate_dt: Variant;
  xNom: string;
  xLS_UBP_PAY: string;
  xLS_UBP_RCP: string;
  xAubucashrequest_ID: string;
  xMoneytransferorder_ID: string;
  xOrgID: string;
  i: integer;
{  xZRSTLines: Variant;
  xZRST: Variant;
  xZRST_KBK: string;}
  xDocXml: Variant;
  xDoc: Variant;
  xDocLines: Variant;
  xDocRecID: string;
//  xDocRecIDGRBS: string;
{  xDocLine: Variant;
  xDocRecID: string;
  xDocRecIDGRBS: string;
  xZR_SumAMount: double;
  xGRANTINVESTMENT: string;}
begin

    try
      // пока прверяем входные данные, результат будет являтся ошибкой
      // как отсутствие параметров.
      Result := 11;



      WriteLog( 'Создается ЭД "Распоряжение на зачисление средств на л/с"...', TRUE);
      WriteLog( 'Поиск ЭД "Заявка БУ/АУ на выплату средств"...', TRUE);
      GetNodeAttribute( aSource, aFieldDate, xDate);
      if (LENGTH(TRIM( xDate)) <= 0) then begin
        WriteInfo( 'Не указана дата платежного поручения.');
        EXIT;
      end;
      GetNodeAttribute( aSource, aFieldNomer, xNom);
      if (LENGTH(TRIM( xNom)) <= 0) then begin
        WriteInfo( 'Не указан номер платежного поручения.');
        EXIT;
      end;
      GetNodeAttribute( aSource, aFieldPAY, xLS_UBP_PAY);
      GetNodeAttribute( aSource, aFieldRCP, xLS_UBP_RCP);
      if ((LENGTH(TRIM( xLS_UBP_PAY)) <= 0) AND
          (LENGTH(TRIM( xLS_UBP_RCP)) <= 0)) then begin
        WriteInfo( 'Не указан л/с ни клиента, ни получателя.');
        EXIT;
      end;
  {    if (LENGTH(TRIM( xLS_PAY_RCP)) <= 0) then begin
        WriteLog( 'Не указан л/с клиента получателя.', TRUE);
        EXIT;
      end;}

      { 3.2.1.1. Сначала производить поиск ЭД "Заявка БУ/АУ на выплату средств"
        со значением поля "Тип платежного поручения в ФК"= "Заявка на кассовый
        расход" на статусе "Готов к исполнению" с Внешним статусом Выгружен по
        следующим параметрам:
        Блок ZR:
          "	Дата документа - ZR.DATE_ZR
          "	Номер документа - ZR.NOM_ZR
          "	Счет плательщика - номер = ZR.LS_UBP_PAY, 5 тип счета
          "	Счет получателя - номер = ZR.LS_UBP_ RCP, 5 тип счета.
        в запросе следует учитывать, если параметр л/с отсутствует, его нужно
        из запроса исключить (тип л/с). }
      xDate_dt := StrToDate( xDate);
      Xml := QueryXml(
  //               FORMAT(
                'select distinct r.id from aubucashrequest r'
               +IfThenElseStr(
                  (LENGTH(TRIM( xLS_UBP_PAY)) > 0),
                  ' join orgaccount oapay on oapay.account_number=r.pay_account'
                 +' and oapay.orgacctype_id=5',
                  '')
               +IfThenElseStr(
                  (LENGTH(TRIM( xLS_UBP_RCP)) > 0),
                  ' join orgaccount oarcp on oarcp.account_number=r.rec_account'
                 +' and oarcp.orgacctype_id=5',
                  '')
               // "Тип платежного поручения в ФК"= "Заявка на кассовый расход"
               +' where r.PAYDOC_CODE = '#39 + aType + #39

               +' and r.dispstatus_id=86'

                  +' and r.extstatus_id='+cnExtStatusID_UnLoaded

               +' and r.documentclass_id=195'
               +' and r.doc_date=? and trim(r.doc_number)=? '
               +IfThenElseStr(
                  (LENGTH(TRIM( xLS_UBP_PAY)) > 0),
                  ' and r.pay_account='#39 + TRIM( xLS_UBP_PAY) + #39,
                  '')
               +IfThenElseStr(
                  (LENGTH(TRIM( xLS_UBP_RCP)) > 0),
                  ' and r.rec_account='#39 + TRIM( xLS_UBP_RCP) + #39,
                  '')
               +' and r.budget_id=?',
               [ xDate_dt, xNom, aBudgetID],
               // здесь нельзя применять кеш, поскольку при одинаковых файлах
               // в результате вернется все тото же ЭД, который обрабатывался
               // в первом файле.
               FALSE);
      if (Xml.documentElement.childNodes.Length <> 1) then begin
        WriteInfo( FORMAT(       'Найдено заявок: %d.'
                          +#13#10'ЭД "Распоряжение на зачисление средств на л/с" не может быть создан.',
                          [ Xml.documentElement.childNodes.Length]));
        Result := 12;
        EXIT;
      end;
      GetNodeAttribute( Xml, '//*/ROW@ID', xAubucashrequest_ID);
      

      WriteLog('Изменение внешнего статуса заявки на "Проверен"...');
      try
  { возможно для этой операции понадобится доработать процессор AUBUCASHREQUEST:
    "serverprocessor.xml". нужно добавить экшен: update_extstatus.
    <SERVERPROCESSOR NAME="AUBUCASHREQUEST" ...
      <SERVERACTION>
        ...
        <SERVERACTION ACTION_NAME="update_extstatus" CAPTION="..." EXTERNAL_FLAG="1" READONLY_FLAG="0" />
      </SERVERACTION>
    </SERVERPROCESSOR>}
        ExecProc( 'DOCUMENT',
                  [ 'action', 'update_extstatus',
                    'class', '195',
                    'ID', xAubucashrequest_ID,
                    'EXTSTATUS_ID', cnExtStatusID_Tested],
                  aBudgetID);
        
        except
          WriteInfo( 'Сбой изменения статуса ЭД "Заявка БУ/АУ на выплату средств".');
          ExceptionLog( 'Сбой выполнения ExecProc: изменение статуса.');
      end;

      { 3.2.1.2. Если не найден, и по настройке ЭД не создается, записывать
        запись в лог и приступать к обработке следующего блока документа BH.}
      if (LowerCase( aConfig.Values[ cnCfgCreateDoc_Topic]) <> cnCfgCreateDoc_193)
        then begin
          // если по конфигурации не создается "Распоряжение на зачисление
          // средств на л/с", то логируем и возвращаем успешное выполнение
          // операции.
          WriteInfo( 'По конфигурации не создается документ "Распоряжение на зачисление средств на л/с".');
          // exchange #3081
          // здесь нужно возвращать значение отличное от 0,
          // иначе будет сбой скрипта в вызывающем коде !
          Result := 16;
          EXIT;
        end;

      WriteLog('Формируется "Распоряжение на зачисление средств на л/с"...');




      try
        ExecProc( 'DOCUMENT',
                  [ 'action', 'spawn_moneytransfer',
                    'class', '195',
                    'ID', xAubucashrequest_ID],
                  aBudgetID);
        WriteLog( 'ЭД "Распоряжение на зачисление средств на л/с" - создан.');
        except
          WriteInfo( 'Сбой создания ЭД "Распоряжение на зачисление средств на л/с".');
          ExceptionLog( 'Сбой выполнения ExecProc: создание ЭД.');
      end;

      // ищем созданный только что документ "Распоряжение на зачисление средств
      // на л/с". его ищем через связку: DOCUMENT.ID=распоряжение,
      // DOCUMENT.PARENT_ID="Заявка БУ/АУ на выплату средств".
      // все должен быть создан один документ!
      WriteLog( 'Поиск созданного ЭД "Распоряжение на зачисление средств на л/с"...');
      Xml := QueryXml(
                ' select m.*'
               +' from moneytransferorder m'
               +' join document dm on dm.id=m.document_id'
               +' join aubucashrequest cr on cr.document_id=dm.parent_id'
               +' where cr.id=? and m.dispstatus_id=1'
               +' and coalesce(m.title_id,m.id)=m.id',
                [ xAubucashrequest_ID],
                // отключаем кеш
                FALSE);
      if (Xml.documentElement.childNodes.Length <> 1) then begin
        WriteInfo( FORMAT(        'Найдено документов: %d.'
                          +#13#10'Сбой создания ЭД "Распоряжение на зачисление средств на л/с".',
                          [ Xml.documentElement.childNodes.Length]));
        Result := 12;
        EXIT;
      end;
      GetNodeAttribute( Xml, '//*/ROW@ID', xMoneytransferorder_ID);


      WriteLog( 'Загружаем ЭД "Распоряжение на зачисление средств на л/с"...');
      xDocXml := CreateOleObject('Microsoft.XmlDom');
      xDoc    := xDocXml.appendChild( xDocXml.createElement('DOCUMENT'));
      xDoc.setAttribute('action', 'read');
      xDoc.setAttribute('class', '193');
      xDoc.setAttribute('ID', xMoneytransferorder_ID);
      { в результате передачи задания, в ответ должны получить ЭД "Распоряжение
        на зачисление средств на л/с" в виде XML вида:
        <DOCUMENT>...</DOCUMENT>.
        нам нужно анализировать параметры корневого узла и добавить в него
        узлы строк PPTS (узел LINES) а затем обновить этот документ, передав
        задание на update.}
      xDocXml.loadXml( ExecXml( xDocXml.xml));
      
      xDoc  := xDocXml.documentElement;

      // анализируем ЭД "Распоряжение на зачисление средств на л/с"
      // если организация в карточке "получатель" не указана или не найдена,
      // в лог ошибку и поле Субсидии и инвестиции не обновляем.
      xDocRecIDGRBS:= '';
      xDocRecID    := TRIM(GetNodeAttributeValue( xDoc, '@REC_ID'));
      if (xDocRecID = '')
        then WriteLog( 'В ЭД "Распоряжение на зачисление средств на л/с" получатель не указан.')
        else begin
          Xml := QueryXml(
                     ' select oa.MANAGER_ID ID from org oa where oa.id=?',
                     [ xDocRecID]);
          if (Xml.documentElement.childNodes.Length = 1)
            then xDocRecIDGRBS := GetNodeAttributeValue( Xml, '//*/ROW@ID');
          if (xDocRecIDGRBS = '')
            then WriteLog( 'В ЭД "Распоряжение на зачисление средств на л/с" не определен "Плательщик"."Код вышестоящего ГРБС".')
        end;
{
      aAccID := GetNodeAttributeValue( xDoc, '//*/ROW@PAY_ACC_ID');
      aAccCode := GetNodeAttributeValue( xDoc, '//*/ROW@PAY_ACCOUNT');
}
      // обновляем ЭД "Распоряжение на зачисление средств на л/с" по BH.ZR
      // меняем только строки по ZRST.
      // поскольку документ создается всегда однострочным, то незачем искать
      // узел LINES.
      WriteLog( 'Обновляем строки ЭД "Распоряжение на зачисление средств на л/с"...', TRUE);
      xDocLines := NULL;
      for i := 0 to xDoc.childNodes.length - 1 do
        if (xDoc.childNodes.item[i].nodeName = 'LINES') then begin
          xDocLines := xDoc.childNodes.item[i];
          BREAK;
        end;
      if VarIsNull( xDocLines)
        then xDocLines := xDoc.appendChild( xDocXml.createElement('LINES'));

      // результат - загруженный документ
      aUpdateDocXML   := xDocXml;
      aUpdateDoc      := xDoc;
      aUpdateDocLines := xDocLines;
      Result          := 0;
      except
        ExceptionProc( 'UpdateDoc193_BH');
    end;

end;
{==============================================================================}
{~FixedUpdateDoc193_BH
  подпрограмма отправляет на сервер обновленный ЭД "Распоряжение на зачисление
  средств на л/с".

  xDocXml - полный XML
  xDoc    - только узел описание документа
  aSumAmount - сумма в строках. записывается вдокумент перед передачей на сервер.
                записывается в поле AMOUNT документа xDoc;
  
  при этом сохраняется этот ЭД в БД.
  помимо этого выполняется логирование XML описания этого ЭД до отправки на
  сервер и после операции - получение ответа.

  после выполнения операции XML xDocXml будет содержать ответ сервера, а не
  исходный документ!}
procedure FixedUpdateDoc193_BH( var xDocXml: Variant;
                                var xDoc: Variant;
                                aSumAmount: double);
begin

    try
      InfoDoc193_BH( xDoc, 'Обновления статуса');
      // exchange #3062
      // исправлена ошибка обновлени узла xDocXml вместо xDoc
      // сохраняем сумму по всем строкам в шапке документа
      xDoc.setAttribute('AMOUNT', FORMAT( '%.2f', [ aSumAmount]));
      xDoc.setAttribute('action', 'update');
      xDoc.setAttribute('class', '193');

      xDocXml.loadXml( ExecXml( xDocXml.xml));

      except
        ExceptionProc( 'FixedUpdateDoc193_BH');
    end;

end;

begin
end.
