uses '..\Version\CheckVersion';

var
  Form: TFormCustom;
  ProgressBar: TProgressBar;
  dtDate: TDateTimeEh;
  cmbDocType: TComboBox;
  grbFiltr: TGroupBox;
  edtDir, edtStatus, edtCharacter, edtDocGroup, edtPurpose, edtGuarantee, edtOrg: TEdit;
  btnDir, btnStatus, btnCharacter, btnDocGroup, btnPurpose, btnGuarantee, btnOrg: TSpeedButton;
  FormStatus, FormCharacter, FormDocGroup, FormPurpose, FormGuarantee, FormOrg: TFormCustomList;
  FileLog, FileInfo: String;
  FDebuger, FFormatXML: Boolean;
  FAzkIsLogin: Boolean;
  FOldIndex: Integer;
  timer: TTimer;

const
  FFileVer = '1.0';
  FFileGuid = '{CB979575-D649-45D3-8DB5-7E445A9040CD}';
  // exchange #2754
  // при импорте ценных бумаг гуид не совпадает с договорами и пр.
  // планеры менять не хотят, поэтому подстраиваемся под планеров.
  FFileGuidEx = '{72D46F86-F250-41BC-92BF-BC96D9C05658}';

procedure Main(Xml: Variant);
begin
  CheckWorkAppVersion;
  with Xml.documentElement do
  if getAttribute('TESTED') = 'True' then
  begin
    setAttribute('TESTED', 'False');
    Xml.save('C:\Temp\LoanDocExport.Xml');
    ShowMessage('Тестовый пример приготовлен: C:\Temp\LoanDocExport.Xml');
    Exit;
  end;
  FAzkIsLogin := AzkIsLogin;
  if not AzkIsLogin then
    if not AzkLogin then
      Exit;
  try
    try
      initialization(Xml);
      timer.Enabled := True;
      if FDebuger then
      begin
        Form.Show;
        repeat
          Application.handleMessage;
        until(not Form.Visible);
      end
      else
        Form.ShowModal;
    except
      WriteLog(LastException.Message);
      raise(LastException.Message);
    end;
  finally
    finalization;
    if not FAzkIsLogin then
      AzkLogout;
  end;
end; {End Main}

procedure timerOnTimer(Sender: TObject);
begin
  timer.Enabled := False;
  FOldIndex := cmbDocType.ItemIndex;
  OncmbDocTypeChange(cmbDocType);
end; {End timerOnTimer}

procedure initialization(Xml: Variant);
var
  IniPath: String;
begin
  IniPath := ExtractFilePath(Xml.documentElement.getAttribute('INI_FILE'));
  FileLog := IniPath + 'System_LoanDocExport.Log';
  FileInfo := IniPath + 'User_LoanDocExport.Log';

  Form := TFormCustom.Create(Application);
  Form.LoadDfm(IniPath + 'Fm_LoanDocExport.dfm');
  Form.Name := 'FmLoanDocExport';
  Form.actExecute.OnExecute := @actExecuteExecute;
  TLabel(Form.FindComponent('lblVersion')).Caption := 'Версия формата: ' + FFileVer;;
  ProgressBar := TProgressBar(Form.FindComponent('ProgressBar'));
  // Отчётная дата
  dtDate := TDateTimeEh(Form.FindComponent('dtDate'));
  dtDate.Date := Work_Date;
  // Каталог экспорта
  edtDir := TEdit(Form.FindComponent('edtDir'));
  btnDir := TSpeedButton(Form.FindComponent('btnDir'));
  btnDir.OnClick := @OnbtnDirClick;
  // Вид договора
  cmbDocType := TComboBox(Form.FindComponent('cmbDocType'));
  cmbDocType.OnChange := @OncmbDocTypeChange;

  grbFiltr := TGroupBox(Form.FindComponent('grbFiltr'));
  // Статус
  FormStatus := TFormCustomList.Create(Form);
  FormStatus.LoadDfm(IniPath + '..\Forms\Fm_DocumentStatus.dfm');
  FormStatus.EditResFieldName := 'Caption';
  edtStatus := TEdit(Form.FindComponent('edtStatus'));
  FormStatus.Edit := edtStatus;
  btnStatus := TSpeedButton(Form.FindComponent('btnStatus'));
  FormStatus.SpeedButton := btnStatus;
  // Признак договора
  FormCharacter := TFormCustomList.Create(Form);
  FormCharacter.LoadDfm(IniPath + '..\Forms\Fm_LnCharacter.dfm');
  FormCharacter.EditResFieldName := 'Caption';
  edtCharacter := TEdit(Form.FindComponent('edtCharacter'));
  FormCharacter.Edit := edtCharacter;
  btnCharacter := TSpeedButton(Form.FindComponent('btnCharacter'));
  FormCharacter.SpeedButton := btnCharacter;
  // Группа договора
  FormDocGroup := TFormCustomList.Create(Form);
  FormDocGroup.LoadDfm(IniPath + '..\Forms\Fm_DocGroup.dfm');
  FormDocGroup.EditResFieldName := 'Caption';
  edtDocGroup := TEdit(Form.FindComponent('edtDocGroup'));
  FormDocGroup.Edit := edtDocGroup;
  btnDocGroup := TSpeedButton(Form.FindComponent('btnDocGroup'));
  FormDocGroup.SpeedButton := btnDocGroup;
  // Целевое назначение
  FormPurpose := TFormCustomList.Create(Form);
  FormPurpose.LoadDfm(IniPath + '..\Forms\Fm_LnPurpose.dfm');
  FormPurpose.EditResFieldName := 'Caption';
  edtPurpose := TEdit(Form.FindComponent('edtPurpose'));
  FormPurpose.Edit := edtPurpose;
  btnPurpose := TSpeedButton(Form.FindComponent('btnPurpose'));
  FormPurpose.SpeedButton := btnPurpose;
  // Способ обеспечения обязательств
  FormGuarantee := TFormCustomList.Create(Form);
  FormGuarantee.LoadDfm(IniPath + '..\Forms\Fm_LnGuarantee.dfm');
  FormGuarantee.SQLText := 'Select g.Id, g.Name as Caption From LN_Guarantee g';
  FormGuarantee.EditResFieldName := 'Caption';
  edtGuarantee := TEdit(Form.FindComponent('edtGuarantee'));
  FormGuarantee.Edit := edtGuarantee;
  btnGuarantee := TSpeedButton(Form.FindComponent('btnGuarantee'));
  FormGuarantee.SpeedButton := btnGuarantee;
  // Кредитор/Заемщик
  FormOrg := TFormCustomList.Create(Form);
  FormOrg.LoadDfm(IniPath + '..\Forms\Fm_Org.dfm');
  FormOrg.SQLText := 'Select o.Id, o.Caption From Org o';
  FormOrg.EditResFieldName := 'Caption';
  edtOrg := TEdit(Form.FindComponent('edtOrg'));
  FormOrg.Edit := edtOrg;
  btnOrg := TSpeedButton(Form.FindComponent('btnOrg'));
  FormOrg.SpeedButton := btnOrg;

  timer := TTimer(form.FindComponent('timer'));
  timer.OnTimer := @timerOnTimer;

  with TStringList.Create do
  try
    CommaText := Xml.documentElement.getAttribute('CONFIG');
    FFormatXML := Trim(Values['Форматировать XML']) = 'Да';
  finally
    Free;
  end;
end; {End initialization}

procedure finalization;
begin
  Form.Free;
end; {End finalization}

procedure OncmbDocTypeChange(Sender: TObject);
  procedure ClearEdit(Sender: TEdit);
  begin
    Sender.Text := '';
    Sender.Hint := '';
  end;

  procedure UpdateQuery(Param: String);
  begin
    FormStatus.SQLText := 'Select distinct ds.dispstatus_id id, ds.Caption From DocStatus ds' +
    ' left join docflowtree dft on dft.id = ds.flow_id and dft.parallel = 0' +
    ' Where ds.dispstatus_id not in (-1, 0) and dft.DocumentClass_Id = ' + Param;
    FormStatus.cdsData.Active := False;
    FormCharacter.SQLText := 'Select c.Id, c.Name as Caption From LN_Character c' +
      ' Where c.DocumentClass_Id = ' + Param;
    FormCharacter.cdsData.Active := False;
    FormDocGroup.SQLText := 'Select dg.Id, dg.Name as Caption From DocGroup dg' +
    ' Where dg.DocumentClass_Id = ' + Param;
    FormDocGroup.cdsData.Active := False;
    FormPurpose.SQLText := 'Select p.Id, p.Name as Caption From LN_Purpose p' +
      ' Where p.DocumentClass_Id = ' + Param;
    FormPurpose.cdsData.Active := False;
  end;
  
var i: Integer;
begin
  if FOldIndex <> cmbDocType.ItemIndex then
  begin
    ClearEdit(edtStatus);
    ClearEdit(edtCharacter);
    ClearEdit(edtPurpose);
    ClearEdit(edtDocGroup);
    ClearEdit(edtGuarantee);
    ClearEdit(edtOrg);
    
    FOldIndex := cmbDocType.ItemIndex;
  end;

  grbFiltr.Enabled := FOldIndex > -1;
  if grbFiltr.Enabled then
    UpdateQuery(GetDocumentClassID);
end;

procedure OnbtnDirClick(Sender: TObject);
begin
  ChooseFolder('Укажите каталог экспорта', edtDir.Text);
end; {End OnbtnDirClick}

procedure OnKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  if Key = VK_DELETE then
  begin
    TEdit(Sender).Hint := '';
    TEdit(Sender).Text := '';
  end;
end; {End OnKeyDown}

procedure WriteLog(Message: String);
begin
  if FileLog <> '' then
    WriteLogFile(FileLog, Message);
end; {End WriteLog}

procedure WriteInfo(Message: String);
begin
  WriteLogFile(FileInfo, Message);
  WriteLogFile(FileLog, Message);
end; {End WriteInfo}

function GetDocumentClassID: String;
begin
  case cmbDocType.ItemIndex of
    0: Result := '44';
    1: Result := '45';
    // exchange #2756 - добавлен договор гарантии
    2: Result := '57';
    // exchange #2754 - Выпуск ценных бумаг
    3: Result := '152';
  end;
end;

procedure CopyElementAttributes(SourceElement, TargetElement: Variant);
var
  I: Integer;
begin
  for I := 0 to SourceElement.attributes.length - 1 do
    TargetElement.setAttribute(SourceElement.attributes[I].nodeName,
      Trim(SourceElement.attributes[I].nodeValue));
end;

{~CopyElementAttribute
  копирование атрибута aAttributeName из узла aSourceElement
  в узел aTargetElement.
  если в узле aSourceElement не будет нужного атрибута, в конечном
  узеле aTargetElement будет создан атрибут с пустой строкой.}
procedure CopyElementAttribute( aSourceElement, aTargetElement: Variant;
                                aAttributeName: string);
begin
  aTargetElement.SetAttribute(
              aAttributeName,
              Trim( VarToStr( aSourceElement.GetAttribute( aAttributeName))));
end;

procedure actExecuteExecute(Sender: TObject);
var
  i, j, i2, i3: Integer;
  FileXml, Sql, AmountSql: String;
  MainSqlXml, MainSqlXmlInteres, Xml, XmlEl, Node, XmlDoc, Row,
  XmlDocInteres, XmlDocInteresLine, MainSqlXmlLine,
  XmlDocLine, XmlDocLine_Line: Variant;
  xSql2756_1: string;
  xSql2756_2: string;
  xID: integer;
  xDoc152Server_XML: Variant;
  xDoc152Node: Variant;
  xDoc152Node_Line: Variant;
  xXmlDocNode: Variant;
  xXmlDocNode_Line: Variant;
begin
  if Trim(edtDir.Text) = '' then
  begin
    MessageDlg('Не указан каталог выгрузки', mtError, mbOk, 0);
    Exit;
  end;
  FileXml := StringReplace(edtDir.Text + '\', '\\', '\');
  if not DirectoryExists(FileXml) then
    raise('Отсутствует каталог: ' + FileXml);
  if cmbDocType.ItemIndex = -1 then
    raise('Выберите Вид договора');

  FileXml := GetUniqueFileName(FileXml + 'LoanDocExport_' +
    DateTimeToStr(Date) + '_DocClass-' + GetDocumentClassID + '_.xml');
  setAppDisable;
  try
    // Теперь создаем Xml которая будет хранить в себе результаты главной выборки
    // exchange #2756 - добавлен договор гарантии
    // в результате требуется возвращать дополнительные поля
    xSql2756_1 := '';
    xSql2756_2 := '';
    case GetDocumentClassID of
      '57': begin
          xSql2756_1 := ' d.GARANT_ID as GARANT_ID, g2.caption as GARANT_NAME,'
                       +' d.GARANTER_ID as GARANTER_ID, g3.caption as GARANTER_NAME,'
                       +' d.bank_ID as BANK_ID, g4.caption as BANK_NAME,'
                       +' d.OBL_NUMBER as OBL_NUMBER,'
                       +' d.OBL_DATE as OBL_DATE,'
                       +' d.OBL_FINISH_DATE as OBL_FINISH_DATE,'
                       +' d.OBL_AMOUNT as OBL_AMOUNT,'
                       +' d.OBL_DESCRIPTION as OBL_DESCRIPTION, '
                       +' d.OBL_PURPOSE_ID as OBL_PURPOSE_ID,'
                       // exchange #2789 - добавлены поля:
                       // INI_IN_AMOUNT – "Начально получено"
                       // INI_OUT_AMOUNT – "Начально погашено"
                       +' d.INI_IN_AMOUNT, d.INI_OUT_AMOUNT,'
                       +' obl_p.NAME as OBL_PURPOSE_NAME,';
          xSql2756_2 := ' left join org g2 on g2.id= d.GARANT_ID'
                       +' left join org g3 on g3.id= d.GARANTER_ID'
                       +' left join org g4 on g4.id= d.bank_ID'
                       +' left join LN_PURPOSE obl_p on obl_p.id = d.OBL_PURPOSE_ID';
        end;
    end;//case//

    MainSqlXml := CreateOleObject('Microsoft.XmlDom');
    Sql :=
      ' select d.doc_number as DOC_NUMBER, d.doc_date as DOC_DATE, d.reg_date as REG_DATE,' +
      ' d.AMOUNT as AMOUNT, d.DESCRIPTION as DESCRIPTION, d.DIRECTION_ID as DIRECTION_ID,' +
      ' d.DOCGROUP_ID as DOCGROUP_ID, dg.NAME as DOCGROUP_NAME,' +
      ' d.ORG_ID as ORG_ID, o.CAPTION as ORG_NAME,' +
      ' d.ORGACCOUNT_ID as ORGACCOUNT_ID, oa.ACCOUNT_NUMBER,' +
      ' d.START_DATE as START_DATE, d.FINISH_DATE as FINISH_DATE,' +
      ' d.GUARANTEE_ID as GUARANTEE_ID, g.NAME as GUARANTEE_NAME,' +
      ' d.CHARACTER_ID as CHARACTER_ID, c.NAME as CHARACTER_NAME,'
     +xSql2756_1
     +' d.PURPOSE_ID as PURPOSE_ID, p.NAME as PURPOSE_NAME,' +
      ' d.INI_IN_AMOUNT as INI_IN_AMOUNT, d.INI_OUT_AMOUNT as INI_OUT_AMOUNT,' +
      ' d.ID as ID, d.FOREIGN_KEY as FOREIGN_KEY' +
      ' from LOANDOC d' +
      ' left join docgroup dg on (d.DOCGROUP_ID = dg.ID)' +
      ' left join org o on (d.ORG_ID = o.ID)' +
      ' left join ORGACCOUNT oa on (oa.id = d.ORGACCOUNT_ID)' +
      ' left join LN_GUARANTEE g on (d.GUARANTEE_ID = g.ID)' +
      ' left join LN_CHARACTER c on (d.CHARACTER_ID = c.ID)' +
      ' left join LN_PURPOSE p on (d.PURPOSE_ID = p.ID)'   // поправлена ошибка в запросе
     +xSql2756_2
     +' where (not d.dispstatus_id in (-1, 0)) ' +
      ' and d.documentclass_id = ?' +
      ' and (d.doc_date >= ? and d.doc_date <= ?)' +
      ' and d.budget_id=?';
      
    if edtStatus.Hint <> '' then
      Sql := Sql + ' and d.dispstatus_id in (' + edtStatus.Hint + ')';
    if edtCharacter.Hint <> '' then
      Sql := Sql + ' and d.CHARACTER_ID in (' + edtCharacter.Hint + ')';
    if edtDocGroup.Hint <> '' then
      Sql := Sql + ' and d.DOCGROUP_ID in (' + edtDocGroup.Hint + ')';
    if edtPurpose.Hint <> '' then
      Sql := Sql + ' and d.PURPOSE_ID in (' + edtPurpose.Hint + ')';
    if edtGuarantee.Hint <> '' then
      Sql := Sql + ' and d.GUARANTEE_ID in (' + edtGuarantee.Hint + ')';
    if edtOrg.Hint <> '' then
      Sql := Sql + ' and d.ORG_ID in (' + edtOrg.Hint + ')';

    Query.addLong(GetDocumentClassID);
    Query.addDate(EncodeDate(YearOf(dtDate.Date),1,1));
    Query.addDate(dtDate.Date);
    Query.addStr(Budget_Id);

    Form.SimpleText := 'Запрос к серверу приложений ...';
    MainSqlXml.LoadXml(Query.Run(Sql));
    MainSqlXml := MainSqlXml.documentElement.childNodes;
    if MainSqlXml.length = 0 then
    begin
      MessageDlg('Нет данных по условиям', mtInformation, mbOK, 0);
      WriteLog('Нет данных по условиям ...');
      Exit;
    end;
    ProgressBar.Max := MainSqlXml.Length;

    Form.SimpleText := 'Формирование файла экспорта ...';
    // Создаем главную XML
    Xml := CreateOleObject('Microsoft.XmlDom');
    // создаем её наполнение
    XmlEl := Xml.createElement('LOANDOCEXPORT');
    Xml.DocumentElement := XmlEl;
    XmlEl.setAttribute('FINYEAR', FormatDateTime('yyyy', dtDate.Date));
    XmlEl.setAttribute('FILEDATE', FormatDateTime('yyyy-mm-dd', dtDate.Date));
    XmlEl.setAttribute('FILEVER', FFileVer);

    // exchange #2754
    // при выгрузке ценных бумаг. гуид должен быть другим
    case GetDocumentClassID of
      '152': XmlEl.setAttribute('FILEGUID', FFileGuidEx);
      else   XmlEl.setAttribute('FILEGUID', FFileGuid);
    end;//case//

    XmlEl.setAttribute('DOCUMENTCLASS', GetDocumentClassID);

    for I := 0 to MainSqlXml.Length - 1 do
    begin
      // Проходим по каждой строке полученного набора данных
      Row := MainSqlXml.Items[i];

      // формируем новый документ (на базе Row)
      XmlDoc := Xml.createElement('ROW');

      if (GetDocumentClassID = '152') then begin
        // ЭД "Выпуск ценных бумаг" берем не из бд, а через процессор
        // 152 класса ЭД (читаем ЭД из АЦК-Ф по ID)
        // тем самым при изменении полей в АЦК-Ф он будет взят так, как
        // реализовано в АЦК-Ф.
        // но тут есть проблема: некоторые поля придется догружать,
        // поскольку помимо Id требуются названия полей.
        xDoc152Server_XML := CreateOleObject('Microsoft.XmlDom');
        xDoc152Server_XML.LoadXML(
            ExecProc( 'DOCUMENT',
                      [ 'action', 'read',
                        'class', '152',
                        'ID', Row.GetAttribute( 'ID')],
                      Budget_Id));
        xDoc152Server_XML := xDoc152Server_XML.documentElement;

        // копируем описание ЭД в узел XmlDoc
        CopyElementAttributes( xDoc152Server_XML, XmlDoc);
        // часть полей будем копировать из БД
        CopyElementAttribute( Row, XmlDoc, 'DOCGROUP_NAME');
        CopyElementAttribute( Row, XmlDoc, 'PURPOSE_NAME');
        CopyElementAttribute( Row, XmlDoc, 'FOREIGN_KEY');
        CopyElementAttribute( Row, XmlDoc, 'GUARANTEE_NAME');
        CopyElementAttribute( Row, XmlDoc, 'CHARACTER_NAME');

        // копируем списковые значения как есть, а не как по заданию.
        // согласовано с ОР планирования.
        for i2 := 0 to xDoc152Server_XML.childNodes.Length - 1 do begin
          xDoc152Node      := xDoc152Server_XML.childNodes.Items[ i2];
          // создаем описание узла
          xXmlDocNode := Xml.createElement( xDoc152Node.NodeName);
          XmlDoc.appendChild( xXmlDocNode);
          // копируем все кложенные подузлы (только один уровень вложенности)
          for i3 := 0 to xDoc152Node.childNodes.Length - 1 do begin
            xDoc152Node_Line := xDoc152Node.childNodes.Items[ i3];
            // создаем и копируем строку списка
            xXmlDocNode_Line := Xml.createElement( xDoc152Node_Line.NodeName);
            xXmlDocNode.appendChild( xXmlDocNode_Line);
            // копируются все параметры в строке
            CopyElementAttributes( xDoc152Node_Line, xXmlDocNode_Line);
          end;//for//
        end;//for//
      end else begin
        // для прочих ЭД копируем все поля из запроса к БД
        CopyElementAttributes(Row, XmlDoc);

        XmlDocInteres := Xml.createElement('LN_INTEREST');
        XmlDoc.appendChild(XmlDocInteres);
      
        MainSqlXmlInteres := CreateOleObject('Microsoft.XmlDom');
        Sql :=
          ' select d.LINE_NUMBER as LINE_NUMBER, d.PAYTYPE_ID as PAYTYPE_ID, pt.name as PAYTYPE_NAME,' +
          ' d.START_DATE as START_DATE, d.FINISH_DATE as FINISH_DATE,' +
          ' d.CALCMETHOD_ID as CALCMETHOD_ID, cm.name as CALCMETHOD_NAME,' +
          ' d.PARAMS as PARAMS, d.PERIOD as PERIOD, d.PAY_DAY as PAY_DAY,' +
          ' d.DISPINDATE as DISPINDATE, d.DISPOUTDATE as DISPOUTDATE,' +
          ' d.DESCRIPTION as DESCRIPTION, d.ESTIMATE_ID as ESTIMATE_ID,' +
          ' e.caption as ESTIMATE_NAME, d.RECIPIENT_ID as RECIPIENT_ID,' +
          ' r.caption as RECIPIENT_NAME, d.KFSR_CODE as KFSR_CODE,' +
          ' d.KCSR_CODE as KCSR_CODE, d.KVR_CODE as KVR_CODE,' +
          ' d.KDF_CODE as KDF_CODE, d.KDE_CODE as KDE_CODE, d.KDR_CODE as KDR_CODE,' +
          ' d.KADMR_CODE as KADMR_CODE, d.KESR_CODE as KESR_CODE, d.FSR_ID as FSR_ID,' +
          ' d.PAYER_ID as PAYER_ID, p.caption as PAYER_NAME,' +
          ' d.RECEIVER_ID as RECEIVER_ID, org_rec.caption as RECEIVER_NAME,' +
          ' d.TERRITORY_ID as TERRITORY_ID, t.caption as TERRITORY_NAME,' +
          ' d.KD_CODE as KD_CODE, d.KDD_CODE as KDD_CODE, d.KDT_CODE as KDT_CODE,' +
          ' d.KADMD_CODE as KADMD_CODE, d.KESD_CODE as KESD_CODE,' +
          ' d.FSD_ID as FSD_ID, d.KI_CODE as KI_CODE, d.KDI_CODE as KDI_CODE,' +
          ' d.COUNTERAGENT_ID as COUNTERAGENT_ID, ca.caption as COUNTERAGENT_NAME,' +
          ' d.KADMI_CODE as KADMI_CODE, d.KESI_CODE as KESI_CODE, d.FSI_ID as FSI_ID'
         // exchange #2465 - добавление кода цели
         +' ,d.PURPOSEFULGRANTD_ID'
         +' ,d.PURPOSEFULGRANTI_ID'
         +' ,d.PURPOSEFULGRANT_ID'
         +' from LN_INTEREST d' +
          ' left join LN_PAYTYPE pt on (d.PAYTYPE_ID = pt.ID)' +
          ' left join LN_CALCMETHOD cm on (d.CALCMETHOD_ID = cm.ID)' +
          ' left join Estimate e on (d.ESTIMATE_ID = e.id)' +
          ' left join org r on (d.RECIPIENT_ID = r.ID)' +
          ' left join org p on (d.PAYER_ID = p.ID)' +
          ' left join RECEIVER rec on (d.RECEIVER_ID = rec.ID)' +
          ' left join org org_rec on (rec.ORG_ID = org_rec.ID)' +
          ' left join territory t on (d.TERRITORY_ID = t.ID)' +
          ' left join org ca on (d.COUNTERAGENT_ID = ca.ID)' +
         // параметризация запроса
          ' where d.LOANDOC_ID=?';
        Query.AddStr( VarToStr(XmlDoc.getAttribute('ID')));

        Form.SimpleText := 'Получение видов выплат для документа с ID=' + VarToStr(XmlDoc.getAttribute('ID'));
        MainSqlXmlInteres.LoadXml(Query.Run(Sql));
        MainSqlXmlInteres := MainSqlXmlInteres.documentElement.childNodes;
        if MainSqlXmlInteres.length = 0 then
          Form.SimpleText := 'У документа с ID=' + VarToStr(XmlDoc.getAttribute('ID')) +
            ' отсутствуют виды выплат!'
        else
        for J := 0 to MainSqlXmlInteres.Length - 1 do
        begin
          // Проходим по каждой строке полученного набора данных
          Row := MainSqlXmlInteres.Items[j];
          // формируем новый документ (на базе Row)
          XmlDocInteresLine := Xml.createElement('LN_INTEREST');
          CopyElementAttributes(Row, XmlDocInteresLine);
          XmlDocInteres.appendChild(XmlDocInteresLine);
        end;
      end;

      // закладка "операции"
      // их нет в серверной xml
      XmlDocLine := Xml.createElement('LINE');
      XmlDoc.appendChild(XmlDocLine);

      MainSqlXmlLine := CreateOleObject('Microsoft.XmlDom');
    
      // exchange #2756 - добавлен договор гарантии (класс 57)
      case GetDocumentClassID of
       '44':
        AmountSql := ' case when d.DOCUMENTCLASS_ID = 50 ' +
                     '   then case when ' +
                     '               exists(select null from LN_PAYTYPE pt' +
                                     '      where (pt.NAME = ''Основная сумма(погашение)'' or ' +
                                     '             pt.NAME = ''Основная сумма(списание)'' or ' +
                                     '             pt.NAME = ''Проценты'' or ' +
                                     '             pt.NAME = ''Штрафы'') and pt.DOCUMENTCLASS_ID=44' +
                                     '             and pt.id = d.PAYTYPE_ID)' +
                     '          then -d.AMOUNT ' +
                     '          else  d.AMOUNT ' +
                     '        end ' +
                     '   else case when d.DOCUMENTCLASS_ID = 52 ' +
                     '          then case when ' +
                     '                 exists(select null from LN_PAYTYPE pt' +
                                       '      where (pt.NAME = ''Основная сумма(получение)'')' +
                                       '      and pt.DOCUMENTCLASS_ID=44 and pt.id = d.PAYTYPE_ID)' +
                     '                 then -d.AMOUNT ' +
                     '                 else  d.AMOUNT ' +
                     '               end ' +
                     '          else d.AMOUNT ' +
                     '        end ' +
                     ' end as AMOUNT';

       '45':
        AmountSql := ' case when d.DOCUMENTCLASS_ID = 56 ' +
                     '   then case when ' +
                     '               exists(select null from LN_PAYTYPE pt' +
                                     '      where (pt.NAME = ''Основная сумма(погашение)'' or ' +
                                     '             pt.NAME = ''Штрафы(просроч. проценты)'' or ' +
                                     '             pt.NAME = ''Проценты'' or ' +
                                     '             pt.NAME = ''Штрафы'') and pt.DOCUMENTCLASS_ID=45 ' +
                                     '             and pt.id = d.PAYTYPE_ID)' +
                     '          then -d.AMOUNT ' +
                     '          else  d.AMOUNT ' +
                     '        end ' +
                     '   else case when d.DOCUMENTCLASS_ID = 54 ' +
                     '          then case when ' +
                     '                 exists(select null from LN_PAYTYPE pt' +
                                       '      where (pt.NAME = ''Основная сумма(выдача)'')' +
                                       '      and pt.DOCUMENTCLASS_ID=45 and pt.id = d.PAYTYPE_ID)' +
                     '                 then -d.AMOUNT ' +
                     '                 else d.AMOUNT ' +
                     '               end ' +
                     '          else d.AMOUNT ' +
                     '        end ' +
                     ' end as AMOUNT';

       else
        AmountSql := ' d.AMOUNT as AMOUNT';
      end;//case//

      Sql :=
        ' select d.doc_number as DOC_NUMBER, d.doc_date as DOC_DATE, '

        // exchange #2713
        // Для ЭД класса 50 и 52 выгружается значение поля
        // «Дата исполнения» (CARRY_DATE).
        // Для ЭД класса 51 выгружается значение поля «Дата выплаты» (PAY_DATE).
        // Для ЭД класса 49 не выгружается.
        // для прочих ЭД выгружается как раньше: d.pay_date.
        // exchange #2756
        // для ЭД договора гарантии по вложенных эд на закладке "операции"
        // поле дата исполнения находится в CARRY_DATE, и ее нужно выгружать
        // в поле  PAY_DATE.
        // exchange #2754
        // при выгрузке ценных бумаг дата исполнения находится в CARRY_DATE
        // в ЭД 154, 155 и 156 классов, и ее нужно выгружать в поле  PAY_DATE.
        // в принципе в 155м необязательно, поскольку планирование этот ЭД
        // не загружают, но по заданию указано.
        // exchange #2794
        // для ЭД "Договор размещения средств" по вложенных эд на закладке
        // "операции" поле дата исполнения находится в CARRY_DATE,
        // и ее нужно выгружать в поле  PAY_DATE.
        // кроме эд 55го класса. в нем дата исполнения находится в pay_date
       +' (case '
       +'    when d.DOCUMENTCLASS_ID in (50, 52, 53, 56, 54, 91, 92, 93, 94, 156, 155, 154) then d.CARRY_DATE'
       +'    when d.DOCUMENTCLASS_ID in (49) then null'
       +'    else d.pay_date'
       +'  end) as PAY_DATE,'

       +' d.OPERTYPE_ID as OPERTYPE_ID, ot.caption as OPERTYPE_NAME,' +
        ' d.DESCRIPTION as DESCRIPTION, d.REMARK as REMARK,' +
        ' d.PAYTYPE_ID as PAYTYPE_ID, pt.name as PAYTYPE_NAME,' +
        ' d.ESTIMATE_ID as ESTIMATE_ID, e.caption as ESTIMATE_NAME,' +
        ' d.RECIPIENT_ID as RECIPIENT_ID, r.caption as RECIPIENT_NAME, '+
        ' d.KFSR_CODE as KFSR_CODE, d.KCSR_CODE as KCSR_CODE, d.KVR_CODE as KVR_CODE,' +
        ' d.KDF_CODE as KDF_CODE, d.KDE_CODE as KDE_CODE, d.KDR_CODE as KDR_CODE,' +
        ' d.KADMR_CODE as KADMR_CODE, d.KESR_CODE as KESR_CODE, d.FSR_ID as FSR_ID,' +
        ' d.PAYER_ID as PAYER_ID, p.caption as PAYER_NAME,' +
        ' d.RECEIVER_ID as RECEIVER_ID, org_rec.caption as RECEIVER_NAME,' +
        ' d.TERRITORY_ID as TERRITORY_ID, t.caption as TERRITORY_NAME,' +
        ' d.KD_CODE as KD_CODE, d.KDD_CODE as KDD_CODE, d.KDT_CODE as KDT_CODE,' +
        ' d.KADMD_CODE as KADMD_CODE, d.KESD_CODE as KESD_CODE,' +
        ' d.FSD_ID as FSD_ID, d.KI_CODE as KI_CODE, d.KDI_CODE as KDI_CODE,' +
        ' d.COUNTERAGENT_ID as COUNTERAGENT_ID, ca.caption as COUNTERAGENT_NAME,' +
        ' d.KADMI_CODE as KADMI_CODE, d.KESI_CODE as KESI_CODE, d.FSI_ID as FSI_ID,' +
        ' d.DOCUMENTCLASS_ID as DOCUMENTCLASS, d.ID as ID, d.FOREIGN_KEY as FOREIGN_KEY, '
       + AmountSql
       // exchange #2465 - добавление кода цели
       +' ,d.PURPOSEFULGRANTD_ID'
       +' ,d.PURPOSEFULGRANTI_ID'
       +' ,d.PURPOSEFULGRANT_ID'
       +' from LN_PAYDOC d' +
        ' left join OperType ot on (d.OPERTYPE_ID = ot.id)' +
        ' left join LN_PAYTYPE pt on (d.PAYTYPE_ID = pt.ID)' +
        ' left join Estimate e on (d.ESTIMATE_ID = e.id)' +
        ' left join org r on (d.RECIPIENT_ID = r.ID)' +
        ' left join org p on (d.PAYER_ID = p.ID)' +
        ' left join RECEIVER rec on (d.RECEIVER_ID = rec.ID)' +
        ' left join org org_rec on (rec.ORG_ID = org_rec.ID)' +
        ' left join territory t on (d.TERRITORY_ID = t.ID)' +
        ' left join org ca on (d.COUNTERAGENT_ID = ca.ID)' +
//       +' left join PURPOSEFULGRANT pg on (pg.id=d.PURPOSEFULGRANT_ID)'+
      // параметризация запроса
        ' where d.dispstatus_id=10 and d.LOANDOC_ID=?';
      Query.AddStr( VarToStr(XmlDoc.getAttribute('ID')));

      // exchange #2756 - добавлен договор гарантии (класс 57)
      // выгружаются только классы 91, 92, 93, 94 на 10м статусе.
      // класс 115 не выгружается.
      // exchange #2754 - добавлена выгрузка эд ценных бумаг
      case GetDocumentClassID of
        '44': Sql := Sql + ' and d.DOCUMENTCLASS_ID in (49, 50, 51, 52)';
        '45': Sql := Sql + ' and d.DOCUMENTCLASS_ID in (55, 53, 56, 54)';
        '57': Sql := Sql + ' and d.DOCUMENTCLASS_ID in (91, 92, 93, 94)';
       '152': Sql := Sql + ' and d.DOCUMENTCLASS_ID in (154, 155, 156)';
      end;//case//

      Form.SimpleText := 'Получение операций для документа с ID=' + VarToStr(XmlDoc.getAttribute('ID'));
      MainSqlXmlLine.LoadXml(Query.Run(Sql));
      MainSqlXmlLine := MainSqlXmlLine.documentElement.childNodes;
      if MainSqlXmlLine.length = 0 then
        Form.SimpleText := 'У документа с ID=' + VarToStr(XmlDoc.getAttribute('ID')) +
          ' отсутствуют виды выплат!'
      else
      for J := 0 to MainSqlXmlLine.Length - 1 do
      begin
        // Проходим по каждой строке полученного набора данных
        Row := MainSqlXmlLine.Items[j];
        // формируем новый документ (на базе Row)
        XmlDocLine_Line := Xml.createElement('LINE');
        CopyElementAttributes(Row, XmlDocLine_Line);
        XmlDocLine.appendChild(XmlDocLine_Line);
      end;

      XmlEl.appendChild(XmlDoc);
      // Для каждого сформированного документа выполняем дополнительный запрос
      // с целью получения строк этого документа
      ProgressBar.Position := i + 1;
    end;

    Form.SimpleText := 'Сохранение файла экспорта ...';
    if FFormatXML then
      Xml.loadXml('<?xml version="1.0" encoding="Windows-1251"?>' + FormatXmlData(Xml.xml));
    Xml.save(FileXml);
    MessageDlg('Файл экспорта: ' + FileXml, mtInformation, mbOK, 0);
  finally
    Form.SimpleText := '';
    ProgressBar.Position := 0;
    SetAppEnable;
  end;
end; {End actExecuteExecute}

var
  Xml: Variant;

begin
  FAzkIsLogin := AzkIsLogin;
  FDebuger := True;
  Xml := CreateOleObject('Microsoft.XmlDom');
  if not FileExists('C:\Temp\LoanDocExport.Xml') then
  begin
    ShowMessage('Не найден тестовый пример: C:\Temp\LoanDocExport.Xml');
    Exit;
  end;
  if not Xml.Load('C:\Temp\LoanDocExport.Xml') then
  begin
    ShowMessage('Ошибка при загрузке: C:\Temp\LoanDocExport.Xml');
    Exit;
  end;
  if not AzkIsLogin then
    if not AzkLogin then
      Exit;
  try
    Main(Xml);
  finally
    if not FAzkIsLogin then
      AzkLogout;
  end;
end. {End Start}