Skip to content

Instantly share code, notes, and snippets.

@omerkoseoglu
Last active October 3, 2020 23:33
Show Gist options
  • Save omerkoseoglu/ba37ec9a4a45f6e9606d0085abc4ab2b to your computer and use it in GitHub Desktop.
Save omerkoseoglu/ba37ec9a4a45f6e9606d0085abc4ab2b to your computer and use it in GitHub Desktop.
PostgreSQL Merkez Bankası Döviz Kurları Stored Procedure
-- auto-generated definition
create table exchanges
(
id uuid default uuid_generate_v4() not null
constraint exchanges_pk
primary key,
currency_id uuid
constraint exchanges_currencies_id_fk
references currencies
on delete restrict,
date date not null,
unit integer not null,
forex_buying double precision,
forex_selling double precision,
banknote_buying double precision,
banknot_selling double precision,
reference_id uuid
);
alter table exchanges
owner to postgres;
create unique index exchanges_currency_id_date_uindex
on exchanges (currency_id, date);
create table raw_data
(
id uuid default uuid_generate_v4() not null
constraint raw_data_pk
primary key,
created_date timestamp default now() not null,
data json not null,
exchange_date date not null,
request_date date not null
);
alter table raw_data
owner to postgres;
create or replace procedure get_exchange_rates(request_date date)
language plpgsql
as $$
declare
data jsonb;
err_context text;
exchange_date text;
url varchar;
begin
if date_cmp(request_date, current_date) >= 1 then
RAISE EXCEPTION 'Date cannot be greater than today.';
end if;
if date_cmp(request_date, current_date) = 0 then
url:= 'https://www.tcmb.gov.tr/kurlar/today.xml';
else
url:= 'http://www.tcmb.gov.tr/kurlar/' || date_part('year', request_date) || to_char(request_date, 'mm') || '/' || to_char(request_date, 'dd') || to_char(request_date, 'mm') || date_part('year', request_date) || '.xml';
end if;
data:= get(url);
if data is null then
RAISE EXCEPTION 'Data not found.';
end if;
exchange_date:= data::jsonb->'Tarih_Date'->>'@Tarih';
insert into raw_data (request_date, exchange_date, data) VALUES (request_date, to_date(exchange_date, 'DD.MMM.YYYY'), data->'Tarih_Date'->'Currency');
exception
when others then
GET STACKED DIAGNOSTICS err_context = PG_EXCEPTION_CONTEXT;
RAISE INFO 'Error Name:%',SQLERRM;
RAISE INFO 'Error State:%', SQLSTATE;
RAISE INFO 'Error Context:%', err_context;
end;
$$
create function get(uri character varying) returns json
language plpython3u
as
$$
import json
import urllib3
from xmltodict import parse
http = urllib3.PoolManager()
r = http.request('GET', uri)
try:
return json.dumps(parse(r.data))
except:
return;
$$;
alter function get(varchar) owner to postgres;
create or replace procedure transform_exchange_rate(process_date date)
language plpgsql
as $$
declare
rec record;
err_context text;
begin
SELECT
t.exchange_date,
t.data as data
into rec
FROM (
SELECT
rd.exchange_date,
rd.data
FROM raw_data rd
WHERE rd.exchange_date = process_date LIMIT 1
) t;
IF rec IS NOT NULL THEN
begin
INSERT INTO exchanges (currency_id, date, unit, forex_buying, forex_selling, banknote_buying, banknot_selling)
SELECT
c.id,
rec.exchange_date,
(d#>>'{Unit}')::integer,
(d#>>'{ForexBuying}')::double precision,
(d#>>'{ForexSelling}')::double precision,
(d#>>'{BanknoteBuying}')::double precision,
(d#>>'{BanknoteSelling}')::double precision
FROM currencies c
INNER JOIN LATERAL json_array_elements(rec.data) d ON (d->>'@Kod') = c.code;
exception
when others then
GET STACKED DIAGNOSTICS err_context = PG_EXCEPTION_CONTEXT;
RAISE INFO 'Error Name:%',SQLERRM;
RAISE INFO 'Error State:%', SQLSTATE;
RAISE INFO 'Error Context:%', err_context;
end;
ELSE
INSERT INTO exchanges(currency_id, date, unit, forex_buying, forex_selling, banknote_buying, banknot_selling, reference_id)
SELECT e.currency_id, process_date, e.unit, e.forex_buying, e.forex_selling, e.banknote_buying, e.banknot_selling, e.id
FROM exchanges e
WHERE e.date = (
SELECT max(e.date) max_date
FROM exchanges e
WHERE e.date <= process_date and (process_date - e.date) between 1 and 10 and e.reference_id IS NULL
);
END IF;
end; $$;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment