Konuyu Oyla:
  • Derecelendirme: 5/5 - 1 oy
  • 1
  • 2
  • 3
  • 4
  • 5
Logo Ticari Programa Döviz Kuru Girme Programı (Güncellendi)
#1
İyi günler 
Logo firması 1 ay kadar önce My Logo web sitesinden döviz alma ve logo programına yazma  işlemini kaldırdı.
güncel program kullananlar Program içinden sadece merkez bankasından kur alma işlemi yapabiliyorlar.

Logo Go3 eski versiyonlar veya Go 1.91 versiyona kadar döviz kurunu merkez bankasından alarak 
veri tabanına işleyen program yazdım tamamen geliştirilebir.

Kaynak kodları ve çalışan exe ekledim 
1 adet veritabanı var exe yanında Microsoft Acces 2000 uyumlu  logo bağlantı ayarların tutuyor.

Kod da merkez bankası kur alma kısmı  @mrmarman  beye ait Allah c.c. razı olsun


Ek Dosyalar
.zip   doviz_kurlari.zip (Dosya Boyutu: 79,47 KB / İndirme Sayısı: 44)
.zip   Kur_al_exe.zip (Dosya Boyutu: 3,8 MB / İndirme Sayısı: 44)
"…De ki: "Hiç bilenlerle bilmeyenler bir olur mu? Şüphesiz, temiz akıl sahipleri öğüt alıp-düşünürler" (Zümer Suresi, 9)
Cevapla
#2
Merhaba 
Benzer yöntemle bu işlemi windows servis ile yapmıştım. Normal windowsta sıkıntı olmadan çalışıyor fakat Windows Server yüklü olan bilgisayarda 

DOC  := LoadXMLDocument('https://www.tcmb.gov.tr/kurlar/today.xml');

bölümünde hata veriyor. Muhtemelen Windowsun güvenlik ayarı ile ilgili ama nasıl aşacağımı bulamadım.
Cevapla
#3
@m_ekici

Döviz kurlarını elde etme yöntemi olarak riske girmeden, yani direk load içerisine Merkez Bankası URL'sini yazmak yerine @cinarbil 'in kodundaki şekilde aşağıdaki gibi önce bu XML yapıyı download ettirip bir String değişken içerisine alarak yürürseniz :

    aXML    := aClient.Get( 'https://www.tcmb.gov.tr/kurlar/today.xml' ).ContentAsString;

Bu işlemler elde edilen XML içeriğin yargılamasını yapmak isteyebilirsiniz.

   aXMLDocument := TXMLDocument.Create(nil);
   aXMLDocument.ParseOptions := aXMLDocument.ParseOptions+[poPreserveWhiteSpace];
   aXMLDocument.LoadFromXML(aXML);
   aNode :=  aXMLDocument.DocumentElement.ChildNodes.FindNode('Currency');
   while aNode <> nil do begin
      ...
      ...
      ...
      ...
      aNode := aNode.NextSibling; // ntTEXT
      aNode := aNode.NextSibling; // Currency
    end;

Saygılarımla
Muharrem ARMAN

guplouajuixjzfm15eqb.gif
Cevapla
#4
   try
   aClient := TNetHTTPClient.Create(nil);
   aXML := aClient.Get( AdresEdt.Text ).ContentAsString;
   DOC  := TXMLDocument.Create(nil);
   DOC.ParseOptions := DOC.ParseOptions+[poPreserveWhiteSpace];
   DOC  := LoadXMLDocument(AdresEdt.Text);
   except
     on E: Exception do
           begin
             Memo3.Lines.Add('Hata:'+e.Message);
           end;
   end;

Aynı şekilde denedim. Serverde 

DOC  := LoadXMLDocument(AdresEdt.Text);

bu satırda Hata:Belirtilen kaynağı indirme işlemi başarısız oldu.

mesajı veriyor. Explorer da adres.text teki sayfa açılıyor. Ama exe veya servis bu adresteski XML i indiremiyor. (Merkez bankası ve sayfasını güvenilir sitelere ekledim)
Cevapla
#5
@mrmarman hocam ekte yeni dosyalar var iki tarih arası döviz kurlarını yazan kodlar var.

ilgili tarih de merkez bankasında bilgi yoksa hata veriyor.

15/4/2024 - 19/4/2024 arası kurlar var işliyor
21/4/2024 (pazar günü)  kur yayınlanmadığı için sayfa hata veriyor program bunu önleyebilir miyiz
daha iyisi hata varsa bir gün öncesini okusun.

ilk versiyonda Logo Firma  seçme çalışmıyordu düzeltildi.
Ayrı döviz kurları (Logoda tüm firmalar için ayrı döviz tablosu ayrı firma bazında tutulan tablo ayrı) çalışmıyordu düzeltildi.

iki tarih arası kur alma eklendi ( yukardaki hata hariç Smile   )


Ek Dosyalar Resimler
   

.zip   doviz_kurlari_iki tarih.zip (Dosya Boyutu: 81,11 KB / İndirme Sayısı: 17)
"…De ki: "Hiç bilenlerle bilmeyenler bir olur mu? Şüphesiz, temiz akıl sahipleri öğüt alıp-düşünürler" (Zümer Suresi, 9)
Cevapla
#6
Tarihe odaklı döviz kuru okuma işlemi için basit bir geriye sayım yapabilirsiniz.

Kendi kütüphanemden komple bir fonksiyon paylaşayım. 
Dilersem koda odaklı dilersem tüm veriyi okuyabileceğim bir Type dizisi içerecek şekilde Merkez Bankası döviz kurlarını aşağıdaki şekilde alıp kullanıyorum. 

@cinarbil tahmin ettiğiniz şekilde gün gün geri giderek ulaşabildiğim ilk tarihe odaklıyorum.
Tabi bu sınırsız olamaz deyip, (10) gün ile sınırlandırdım. Olası merkez bankası kaynaklı teknik sorun olursa diye ...

uses  Xml.XMLIntf,  Xml.XMLDoc,
      System.Net.HttpClientComponent,
      System.DateUtils,
      System.UITypes;

{$region ' -- Type Definition Section -- '}

type
  tCurrencyDetail = record
  CurrencyCode,
  Unit_,
  Isim,
  CurrencyName,
  ForexBuying,
  ForexSelling,
  BanknoteBuying,
  BanknoteSelling,
  CrossRateUSD,
  CrossRateOther: string;
  end;
  tCurrencyDetails = array of tCurrencyDetail;

  tCurrencyInfo = record
    Tarih,
    Date,
    Bulten_No : string;

    CurrencyList  : tCurrencyDetails;
    CurrIdx       : Integer;
 // Debug edilmek istenirse kaynak veri
    SourceUrl     : string;
    SourceXML     : string;
  end;

{$endregion ' -- Type Definition Section -- '}

function MerkezBankasi_KurVerisi( aCurrencyCode: string; aDate: TDateTime ): tCurrencyInfo;
// https://www.tcmb.gov.tr/kurlar/202401/05012024.xml
  var
    LCurrInfo : tCurrencyInfo;
    LCurrList : tCurrencyDetails;

{$region ' -- Currency Parse Section -- '}
  procedure ParseCurrCodes(aContent:String);
    function ParseSubValue( aCurrencyContent:string ): tCurrencyDetail;
    var
      LSubXMLDocument  : IXMLDocument;
      LSubRootNode     : IXMLNode;
      LSubNode         : IXMLNode;
    begin
      result := default(tCurrencyDetail);

      LSubXMLDocument := TXMLDocument.Create(nil);
      try
        LSubXMLDocument.ParseOptions := LSubXMLDocument.ParseOptions+[poPreserveWhiteSpace];
        LSubXMLDocument.XML.Clear;
        LSubXMLDocument.XML.Text     := aCurrencyContent;
        LSubXMLDocument.Active       := TRUE;

        if  ( LSubXMLDocument <> nil )
        and ( LSubXMLDocument.ChildNodes.Count > 0 )
          then
            LSubRootNode := LSubXMLDocument.ChildNodes.First;

        if  ( LSubRootNode <> nil )
        and ( LSubRootNode.HasChildNodes )
          then
            LSubNode := LSubRootNode.ChildNodes.First;

        while (LSubNode <> nil)
          and (LSubNode.NodeType = ntText)
            do
              LSubNode := LSubNode.NextSibling;

        if LSubNode <> nil then
        begin
          while (LSubNode <> nil)  do
          begin
            if  ( LSubNode.NodeType <> ntText )
            and ( NOT VarIsNull( LSubNode.NodeValue ) )
            then
            begin
              if LSubNode.NodeName = 'Unit'            then result.Unit_           := LSubNode.NodeValue;
              if LSubNode.NodeName = 'Isim'            then result.Isim            := LSubNode.NodeValue;
              if LSubNode.NodeName = 'CurrencyName'    then result.CurrencyName    := LSubNode.NodeValue;
              if LSubNode.NodeName = 'ForexBuying'     then result.ForexBuying     := LSubNode.NodeValue;
              if LSubNode.NodeName = 'ForexSelling'    then result.ForexSelling    := LSubNode.NodeValue;
              if LSubNode.NodeName = 'BanknoteBuying'  then result.BanknoteBuying  := LSubNode.NodeValue;
              if LSubNode.NodeName = 'BanknoteSelling' then result.BanknoteSelling := LSubNode.NodeValue;
              if LSubNode.NodeName = 'CrossRateUSD'    then result.CrossRateUSD    := LSubNode.NodeValue;
              if LSubNode.NodeName = 'CrossRateOther'  then result.CrossRateOther  := LSubNode.NodeValue;
            end;
            LSubNode := LSubNode.NextSibling;
          end;
        end;


      except
        on E: Exception do
          raise Exception.Create( E.ClassName + ':' + E.Message );
      end;

    end;
  var
    LXMLDocument  : IXMLDocument;
    LRootNode     : IXMLNode;
    LNode         : IXMLNode;
    LCurrencyCode : IXMLNode;
  begin
    Finalize(LCurrList);

    LXMLDocument := TXMLDocument.Create(nil);
    try
      LXMLDocument.ParseOptions := LXMLDocument.ParseOptions+[poPreserveWhiteSpace];
      LXMLDocument.XML.Clear;
      LXMLDocument.XML.Text     := aContent;
      LXMLDocument.Active       := TRUE;

      if  ( LXMLDocument <> nil )
      and ( LXMLDocument.ChildNodes.Count > 0 )
        then
          LRootNode := LXMLDocument.ChildNodes.First;

      while ( LRootNode <> nil )
      and   ( LRootNode.NodeName <> 'Tarih_Date' )
        do
          LRootNode := LRootNode.NextSibling;

      if  ( LRootNode <> nil )
      and ( LRootNode.HasChildNodes ) then
      begin
        LCurrInfo := default( tCurrencyInfo );
        LCurrInfo.CurrIdx := -1; // not assigned

        if LRootNode.AttributeNodes.FindNode('Tarih') <> nil
          then LCurrInfo.Tarih := LRootNode.AttributeNodes.FindNode('Tarih').NodeValue;
        if LRootNode.AttributeNodes.FindNode('Date') <> nil
          then LCurrInfo.Date := LRootNode.AttributeNodes.FindNode('Date').NodeValue;
        if LRootNode.AttributeNodes.FindNode('Bulten_No') <> nil
          then LCurrInfo.Bulten_No := LRootNode.AttributeNodes.FindNode('Bulten_No').NodeValue;

        LNode := LRootNode.ChildNodes.First;
      end;

      while (LNode <> nil)
        and (LNode.NodeType = ntText)
          do
            LNode := LNode.NextSibling;

      if LNode <> nil then
      begin
        while (LNode <> nil)  do
        begin
          if ('Currency' = LNode.NodeName )
          then
          begin

            LCurrencyCode := LNode.AttributeNodes.FindNode('CurrencyCode');

            if  ( LCurrencyCode <> nil )
            and ( LCurrencyCode.NodeType = ntAttribute )
            then begin
              SetLength(LCurrList, length(LCurrList)+1);
              LCurrList[high(LCurrList)]  := ParseSubValue( LNode.XML );
              LCurrList[high(LCurrList)].CurrencyCode := LCurrencyCode.NodeValue;
            end;
          end;
          LNode := LNode.NextSibling;
        end;
      end;
    except
      on E: Exception do
        raise Exception.Create( E.ClassName + ':' + E.Message );
    end;

  end;
{$endregion ' -- Currency Parse Section -- '}


const
  LBaseUrl = 'https://www.tcmb.gov.tr/kurlar';

var
  LClient   : System.Net.HttpClientComponent.TNetHTTPClient;
  LUrl      : string;
  LResponse : TStringStream;
  LDate     : TDateTime;

  LTrial,
  LStatus   : Integer;

  i         : Integer;

  LProc     : String;
begin
  LProc := '[MerkezBankasi_CrossRateUSD] ';

  LResponse := TStringStream.Create;
  LClient   := TNetHTTPClient.Create(nil);
  try
    LClient.UserAgent := 'Mozilla/5.0';
    try
      LTrial  := 0;
      LStatus := 0;
      LDate   := aDate;

      while ( LStatus <> 200 ) and ( LTrial < 10 ) do
      begin
        inc(LTrial); // max 10 gün önceye kadar tekrarla..
        LUrl  := Format( '%s/%s.xml', [LBaseUrl, FormatDateTime('YYYYMM"/"DDMMYYYY', LDate) ] );

        LStatus := LClient.Get( LUrl, LResponse ).StatusCode;
        if LStatus = 200 then
        begin
        //Parse to LCurrList
          ParseCurrCodes(LResponse.DataString);
          LCurrInfo.CurrencyList := LCurrList;

          Result := LCurrInfo;
          // Debug edilmek istenirse kaynak veri...
          Result.SourceUrl    := LUrl;
          Result.SourceXML    := LResponse.DataString;

          for i := Low(LCurrList) to High(LCurrList) do
          begin
            if LCurrList[i].CurrencyCode = aCurrencyCode then
            begin
              Result.CurrIdx      := i;

              break;
            end;
          end;

        end else
        begin
          LDate   := IncDay( LDate, -1 ); // Haftasonu veya bayram olabilir
                                          // bir gün öncesi ile yeniden...
          Result          := default(tCurrencyInfo);
          Result.CurrIdx  := -1; // not assigned
        end;
      end;
    except on E: Exception do
      begin
        // Burada VCL ise mesaj verdirebilir, service ise Debug Dump yapabilirsiniz.

        MessageDlg( format('%s'+sLineBreak+'%s', [
          'Döviz kuru için Merkez Bankası bağlantısı sağlanamadı...', E.Message ])
          , TMsgDlgType.mtError, [mbCancel], 0 );

        Result          := default(tCurrencyInfo);
        Result.CurrIdx  := -1; // not assigned
      end;
    end;

  finally
    FreeAndNil(LClient);
    FreeAndNil(LResponse);
  end;
end;



Kullanımı :

procedure TForm1.BitBtn1Click(Sender: TObject);
var
 KurBilgisi : tCurrencyInfo;
begin

 KurBilgisi := MerkezBankasi_KurVerisi( 'USD', now);
 if KurBilgisi.CurrIdx > -1 then
 begin
   ShowmessageFmt( '%s %s : %s'+sLineBreak+'%s' + sLineBreak + 'Döv.Al: %s Döv.Sat: %s',
     [
       KurBilgisi.Tarih,
       KurBilgisi.Bulten_No,
       KurBilgisi.CurrencyList[KurBilgisi.CurrIdx].CurrencyName,
       KurBilgisi.CurrencyList[KurBilgisi.CurrIdx].CurrencyCode,
       KurBilgisi.CurrencyList[KurBilgisi.CurrIdx].ForexBuying,
       KurBilgisi.CurrencyList[KurBilgisi.CurrIdx].ForexSelling
     ] );
 end;
end;


x1pf9hvbrh09tx2ls7x3.gif
Saygılarımla
Muharrem ARMAN

guplouajuixjzfm15eqb.gif
Cevapla
#7
(23-04-2024, Saat: 16:41)cinarbil Adlı Kullanıcıdan Alıntı: @mrmarman hocam ekte yeni dosyalar var iki tarih arası döviz kurlarını yazan kodlar var.

ilgili tarih de merkez bankasında bilgi yoksa hata veriyor.

15/4/2024 - 19/4/2024 arası kurlar var işliyor
21/4/2024 (pazar günü)  kur yayınlanmadığı için sayfa hata veriyor program bunu önleyebilir miyiz
daha iyisi hata varsa bir gün öncesini okusun.

ilk versiyonda Logo Firma  seçme çalışmıyordu düzeltildi.
Ayrı döviz kurları (Logoda tüm firmalar için ayrı döviz tablosu ayrı firma bazında tutulan tablo ayrı) çalışmıyordu düzeltildi.

iki tarih arası kur alma eklendi ( yukardaki hata hariç Smile   )

Daha önce paylaşmış olduğum TCMB Döviz Kur Bileşen (ArsDöviz) paketinde şu mantıkla çalışıyor.

Öncelikle kur talep edilen tarihin hafta sonu mu olduğuna bakılıyor. 
Hafta sonu ise haftanın ilk gününe +4 gün ekleyerek Cuma günü bulunuyor. Kur olarak Cuma gününün kuru döndürülüyor. 
    if TArsDate.IsWeekEnd(FKurTarihi) then
      FKurTarihi := FirstDayOfWeek(FKurTarihi) + 4;

TDay ve TDays tipleri:
  TDay = (Pazartesi, Sali, Carsamba, Persembe, Cuma, Cumartesi, Pazar);
 TDays = set of TDay;

IsWeekEnd fonksiyonu (System.DateUtils kullanıyor):

class function IsWeekEnd(const ADate: TDateTime; AWorkDays: TDays = [Pazartesi .. Cuma]): Boolean; static;

class function TArsDate.IsWeekEnd(const ADate: TDateTime; AWorkDays: TDays): Boolean;
begin
 Result := not(TDay(Ord(DayOfTheWeek(ADate))) in AWorkDays);
end;
Begin : = end / 2;
Cevapla
#8
@RAD Coder

Güzel düşünmüşsünüz elinize sağlık.
Resmi tatil günlerine denk gelince nasıl bir sonuç veriyor diye kodları görmek için linke tıkladım ancak açık kaynak değil sanırım.
Saygılarımla
Muharrem ARMAN

guplouajuixjzfm15eqb.gif
Cevapla
#9
(24-04-2024, Saat: 09:47)mrmarman Adlı Kullanıcıdan Alıntı: @RAD Coder  

Güzel düşünmüşsünüz elinize sağlık.
Resmi tatil günlerine denk gelince nasıl bir sonuç veriyor diye kodları görmek için linke tıkladım ancak açık kaynak değil sanırım.

Demo uygulamada bu sonucu görebilirsiniz.
Uygulamanın kaynak kodunu paylaşayı düşünmüyorum.
Begin : = end / 2;
Cevapla
#10
@mrmarman, @RAD Coder  ve diger yardımcı olanlara teşekkür ederim Allah c.c razı olsun

Programın son halini paylaşıyorum devamı olmayacak.

Son güncellemede iki tarih arasında döviz kurlarını alırken resmi , dini tatil zamanlarında veri olmadığında hata veriyordu

verilen örneklerden faydalanarak güncelledim şu an hatasın çalışıyor.


Ek Dosyalar
.zip   doviz_kurlari_iki_tarih_arasi.zip (Dosya Boyutu: 83,13 KB / İndirme Sayısı: 36)
"…De ki: "Hiç bilenlerle bilmeyenler bir olur mu? Şüphesiz, temiz akıl sahipleri öğüt alıp-düşünürler" (Zümer Suresi, 9)
Cevapla


Konu ile Alakalı Benzer Konular
Konular Yazar Yorumlar Okunma Son Yorum
  TCMB Döviz Kur Bileşeni (ArsDöviz) v1.2.0 RAD Coder 28 7.941 13-01-2026, Saat: 09:48
Son Yorum: frmman
  TCMB Döviz Kur Kütüphanesi (Kurulumsuz) Mr.X 0 170 13-01-2026, Saat: 00:04
Son Yorum: Mr.X
  Teknk Servis Programı (Güncellendi) ercanskose 21 9.966 03-09-2024, Saat: 11:01
Son Yorum: ercanskose
  MSSQL Yedekleme Programı ercanskose 11 12.189 14-02-2023, Saat: 15:38
Son Yorum: TheEAK
Wink Spor Toto Tahmin-Takip Programı narkotik 1 2.190 20-12-2020, Saat: 03:37
Son Yorum: mcuyan



Konuyu Okuyanlar: 1 Ziyaretçi