Загрузка курсов валют прямо с сайта cbr.ru
На страницу 1, 2 След.
|
Предыдущая тема :: Следующая тема |
Автор |
Сообщение |
prog Эксперт
Вступление в Клуб: 03.03.2008
|
Ср Сен 30, 2009 16:55  Загрузка курсов валют прямо с сайта cbr.ru |
|
Полезность: 6
|
Операция устанавливает актуальные курсы валют ЦБ.
Легко может быть использована в назначенных заданиях.
GetRecontCurs в переменную l_table3 out recont_table складывает список валют курс которых изменился.
Последний раз редактировалось: prog (Ср Сен 30, 2009 17:04), всего редактировалось 1 раз |
|
 |
prog Эксперт
Вступление в Клуб: 03.03.2008
|
Ср Сен 30, 2009 16:56   |
|
Полезность: Нет оценки
|
Глобальные описания:
Код: |
proxy varchar2;
username varchar2;
password varchar2;
url varchar2 := 'http://www.cbr.ru/scripts/xml_daily.asp?date_req=';
type recont_table is table of [RECONT_CUR_LIST];
--Функция определяет курсы валют подлежащих переоценке
--ErrorInfo = 0 - не было ошибок
--ErrorInfo = 1 - проблемы со связью
--ErrorInfo = 2 - не курсов на сайте
procedure GetRecontCurs(op_date date, l_table3 out recont_table, ErrorInfo in out number);
PRAGMA INCLUDE([DEBUG_TRIGGER]::[MACRO_LIB]);
|
|
|
 |
prog Эксперт
Вступление в Клуб: 03.03.2008
|
Ср Сен 30, 2009 16:57   |
|
Полезность: Нет оценки
|
Локальные описания:
Код: |
pragma macro (xml, '[RUNTIME]::[XML_DOM]');
pragma macro (debug_, '&debug('' ''|| [1] ||'' = ''||&xml.getNodeName([2])||'' = ''||&xml.getNodeValue([2]),2)'
, substitute);
pragma macro(num_form, ', ''99D9999'', '' NLS_NUMERIC_CHARACTERS = '''', ''''''');
pragma macro(exp, 'exception when OTHERS then
&debug('' [1] ERROR! ''||sqlerrm||''
''||utils.call_stack,0)', substitute);
type rec is record
(
NumCode varchar2(6),
CharCode varchar2(50),
Nominal varchar2(5),
Name varchar2(50),
Value varchar2(50)
);
type table_type is table of rec;
procedure cbr_curs(p_date date default sysdate, l_table in out table_type, ErrorInfo in out number) is
l_clob clob;
l_parser &xml.parser;
l_doc &xml.domdocument;
l_nodelist &xml.DOMNamedNodeMap;
l_node &xml.domnode;
l_child &xml.domnode;
l_child2 &xml.domnode;
NodeName varchar2;
req utl_http.req;
resp utl_http.resp;
idx number := 1;
begin
&debug(' -> cbr_curs : proxy '||proxy||' ['||username||':'||password||'] date='||to_char(p_date),1)
begin
if proxy is not null then
utl_http.set_proxy(proxy);
end if;
req := utl_http.begin_request(url||to_char(p_date, 'dd.mm.yyyy'));
if proxy is not null and username is not null then
utl_http.set_authentication(req, username, password, 'Basic', true);
end if;
utl_http.set_body_charset('windows-1251');
utl_http.set_header(req, 'User-Agent', 'Mozilla/4.0');
resp := utl_http.get_response(req);
utl_http.read_text(resp, l_clob);
utl_http.end_response(resp);
EXCEPTION
WHEN utl_http.end_of_body THEN
utl_http.end_response(resp);
END;
&debug(l_clob, 2)
--Меняем кодировку на ту которая в БД
l_clob := convert(l_clob,'CL8MSWIN1251', 'CL8ISO8859P5');
l_parser := &xml.newparser;
&xml.parseClob(l_parser, l_clob);
dbms_lob.freetemporary(l_clob);
l_doc := &xml.getdocument(l_parser);
if &xml.IsNull(l_doc) then
pragma error('Ошибка в структуре XML-документа');
end if;
--Читаем корневой узел
l_node := &xml.getFirstChild(&xml.makenode(l_doc));
&debug_('Node1', l_node)
l_nodelist := &xml.getAttributes(l_node);
for i in 0 .. &xml.getLength(l_nodelist)-1 loop
l_child := &xml.item(l_nodelist, i);
NodeName := &xml.getNodeName(l_child);
&debug_('Attr', l_child)
end loop; --ValCurse
l_node := &xml.getFirstChild(l_node);
while not &xml.isNull(l_node) loop --Valute
&debug_('Node2', l_node)
case &xml.getNodeName(l_node) of
:'#text':
--Читаем значание узла
null;
else
l_nodelist := &xml.getAttributes(l_node);
if not &xml.isNull(l_nodelist) then
for i in 0 .. &xml.getLength(l_nodelist)-1 loop
l_child := &xml.item(l_nodelist, i);
NodeName := &xml.getNodeName(l_child);
&debug_('Attr', l_child)
end loop;
end if;
l_child := &xml.getFirstChild(l_node);
while not &xml.isNull(l_child) loop --NumCode, CharCode, Nominal,
NodeName := &xml.getNodeName(l_child);
&debug_('Node3', l_child)
case &xml.getNodeName(l_child) of
:'#text':
--Читаем значание узла
null;
else
--Читаем строковое значение параметра
if &xml.hasChildNodes(l_child) then
l_child2 := &xml.getFirstChild(l_child);
&debug_('Node4', l_child2)
case NodeName of
:'NumCode':l_table(idx).NumCode := trim(&xml.getNodeValue(l_child2));
:'CharCode':l_table(idx).CharCode := trim(&xml.getNodeValue(l_child2));
:'Nominal':l_table(idx).Nominal := trim(&xml.getNodeValue(l_child2));
:'Name':l_table(idx).Name := trim(&xml.getNodeValue(l_child2));
:'Value':l_table(idx).Value := trim(&xml.getNodeValue(l_child2));
:'#text':null;
else
null;
end;
end if;
end;
l_child := &xml.getNextSibling(l_child);
end loop;
end;
idx := nvl(l_table.last, 0)+1;
l_node := &xml.getNextSibling(l_node);
end loop;
&xml.freeparser(l_parser);
if l_table.count <> 0 then
for i in l_table.first.. l_table.last loop
&debug(' CharCode='||l_table(i).CharCode||', NumCode='||l_table(i).NumCode||', Nominal='||l_table(i).Nominal||', Name='||l_table(i).Name||', Value='||l_table(i).Value, 1)
end loop;
&debug(' return '||l_table.count||' record',1)
end if;
&exp(cbr_curs)
ErrorInfo := 1;
end;
procedure GetRecontCurs(op_date date, l_table3 out recont_table, ErrorInfo in out number)
is
l_table1 table_type; --курс на текущую дату
l_table2 table_type; --курс на прошлую дату
br ref [BRANCH];
NOW_Date date;
NEXT_Date date;
ft_m ref [FT_MONEY];
rc ref [RECONT_CUR_LIST];
begin
-- определим филиал, где хранится список переоценки
br := ::[RECONT_ACCOUNT].[DO_RECONT].get_recont_branch;
--его дату
NOW_Date := nvl(OP_DATE, ::[BRANCH].[SLIB].opdate_filial( br ));
--если текущий день суббота, то передвинем его на предыдущий
if to_number(to_char(NOW_Date, 'D')) = 6 then
NOW_Date := [RUNTIME]::[CALENDAR].next_date('HOLIDAYS',0, NOW_Date-1, -1);
end if;
--курсы за текущий день
cbr_curs(NOW_Date, l_table2, ErrorInfo);
--курсы за следующий день
NEXT_DATE := [RUNTIME]::[CALENDAR].next_date('HOLIDAYS',0, NOW_Date+1, +1);
cbr_curs(NEXT_DATE, l_table1, ErrorInfo);
if nvl(l_table1.count, 0) = 0 or nvl(l_table2.count, 0) = 0 then
return;
end if;
for i in l_table1.first..l_table1.last loop
ft_m := ::[FT_MONEY].[LIB].Get_money(l_table1(i).CharCode);
if ft_m is null then
&debug(' Валюты '||l_table1(i).CharCode||' не найдено в справочнике FT_MONEY',1)
elsif l_table1(i).NumCode is null or
l_table1(i).CharCode is null or
l_table1(i).Nominal is null or
l_table1(i).Name is null or
l_table1(i).Value is null
then
&debug(' Не все поля строки '||i||' с курсами на '||to_char(Next_Date)||' заполнены',1)
else
begin
locate rc in ::[RECONT_CUR_LIST] where rc.[CURRENCY] = ft_m;
--если не было исключения то считаем что все проверки запись прошла
for j in l_table2.first..l_table2.last loop
if l_table2(j).CharCode = l_table1(i).CharCode then
if l_table2(i).NumCode is null or
l_table2(i).CharCode is null or
l_table2(i).Nominal is null or
l_table2(i).Name is null or
l_table2(i).Value is null
then
&debug(' Не все поля строки '||i||' с курсами на '||to_char(Now_DATE)||' заполнены',0)
ErrorInfo := 2;
else
if TO_NUMBER(l_table1(i).Value &num_form) = TO_NUMBER(l_table2(j).Value &num_form) then
&debug(' Курс валюты '||l_table1(i).CharCode||' на '||to_char(Next_Date)||' и на '||to_char(Now_DATE)||' совпадает.',0)
ErrorInfo := 2;
else
&debug(' Определен курс валюты '||ft_m.[CUR_SHORT]||' на '||to_char(Next_Date)||' ('||TO_NUMBER(l_table1(i).Value &num_form)||')',0)
ErrorInfo := 0;
--добавим данные в итоговую таблицу
l_table3(nvl(l_table3.last,0)+1).[DATE_BEGIN] := Next_Date;
l_table3(l_table3.last).[CURRENCY] := ft_m;
l_table3(l_table3.last).[UNIT_NEW] := TO_NUMBER(l_table1(i).Nominal);
l_table3(l_table3.last).[RATE_NEW] := TO_NUMBER(l_table1(i).Value &num_form);
end if;
end if;
end if;
end loop;
exception when NO_DATA_FOUND then
&debug(' Валюта '||l_table1(i).CharCode||' не найдена в справочнике RECONT_CUR_LIST',1)
end;
end if;
end loop;
&exp(main)
end;
|
|
|
 |
prog Эксперт
Вступление в Клуб: 03.03.2008
|
Ср Сен 30, 2009 17:00   |
|
Полезность: Нет оценки
|
Пример использования
Тело операции
Код: |
rc ref [RECONT_CUR_LIST];
begin
proxy := P_PROXY;
username := P_USER;
password := P_PASSWORD;
V_RECONT.delete;
GetRecontCurs(P_OP_DATE, V_RECONT, V_ERRORINFO);
--Пишем курсы
for i in V_RECONT.first..V_RECONT.last loop
locate rc in ::[RECONT_CUR_LIST] where rc.[CURRENCY] = V_RECONT(i).[CURRENCY];
rc := V_RECONT(i);
end loop;
&exp(execute)
end;
|
|
|
 |
BoBr Участник со стажем
Вступление в Клуб: 30.01.2013
|
Чт Мар 28, 2013 10:02   |
|
Полезность: Нет оценки
|
Добрый День! Извиняюсь, пока еще новичек в ЦФТ, при попытке сохранения операции множественные ошибки (во вложении), дял этого нужно создавать какую-то отдельную таблицу?? |
|
 |
prog Эксперт
Вступление в Клуб: 03.03.2008
|
Чт Мар 28, 2013 10:26   |
|
Полезность: Нет оценки
|
в данном примере v_recont - это массив [RECONT_CUR_LIST], располагается на форме, туда выводятся загруженные курсы
P_OP_DATE - дата установки курсов
V_ERRORINFO - переменная куда код ошибки складывается |
|
 |
Alkov Профи
Вступление в Клуб: 23.09.2010
|
Чт Мар 28, 2013 10:32   |
|
Полезность: Нет оценки
|
Вообще тут разные ошибки, но вот например не может найти операцию UTL_HTTP поищите её на схеме и замените вызов на [ТБП-тип где лежит данная операция].[UTL_HTTP] |
|
 |
prog Эксперт
Вступление в Клуб: 03.03.2008
|
Чт Мар 28, 2013 10:34   |
|
Полезность: Нет оценки
|
вот секция проверки кстати Надо же, за несколько лет ни у кого даже вопросов не возникло...
Код: | begin
if P_MESSAGE = 'DEFAULT' then
--Читаем настройки
P_PROXY := nvl(::[DEFVALS].[SLIB].RestoreStr(::[SYSTEM], &METHOD$CLASS, &METHOD$SNAME, 'P_PROXY_'||stdlib.userid), '10.10.10.3:8080');
P_USER := nvl(::[DEFVALS].[SLIB].RestoreStr(::[SYSTEM], &METHOD$CLASS, &METHOD$SNAME, 'P_USER_'||stdlib.userid),'');
P_PASSWORD := nvl(::[DEFVALS].[SLIB].RestoreStr(::[SYSTEM], &METHOD$CLASS, &METHOD$SNAME, 'P_PASSWORD_'||stdlib.userid),'');
proxy := P_PROXY;
username := P_USER;
password := P_PASSWORD;
V_RECONT.delete;
GetRecontCurs(P_OP_DATE, V_RECONT, V_ERRORINFO);
end if;
&exp(validate)
end; |
|
|
 |
prog Эксперт
Вступление в Клуб: 03.03.2008
|
Чт Мар 28, 2013 10:35   |
|
Полезность: Нет оценки
|
Alkov пишет: | Вообще тут разные ошибки, но вот например не может найти операцию UTL_HTTP поищите её на схеме и замените вызов на [ТБП-тип где лежит данная операция].[UTL_HTTP] |
не.. это просто надо флаг расширенный синтаксис поставить в настройках компиляции |
|
 |
Random Эксперт
Вступление в Клуб: 27.06.2011
|
Чт Мар 28, 2013 10:48   |
|
Полезность: Нет оценки
|
Alkov пишет: | Вообще тут разные ошибки, но вот например не может найти операцию UTL_HTTP поищите её на схеме и замените вызов на [ТБП-тип где лежит данная операция].[UTL_HTTP] |
UTL_HTTP - это системный пакет Oracle, его нет в "ТБП-типах".
Расширенный синтаксис на операции надо установить, только и всего. |
|
 |
BoBr Участник со стажем
Вступление в Клуб: 30.01.2013
|
Пт Мар 29, 2013 10:57   |
|
Полезность: Нет оценки
|
Так и не получается настроить . Вывожу операцию в монитор и там вижу такую ошибку:
11:50:52 [END_OD_OPERATION]::[PVB_DOWNLOAD_CUR]<?xml version="1.0" encoding="windows-1251" ?>
<ValCurs Date="29/03/13">
</ValCurs>
[END_OD_OPERATION]::[PVB_DOWNLOAD_CUR] Node1 = ValCurs =
[END_OD_OPERATION]::[PVB_DOWNLOAD_CUR] Attr = Date = 29/03/13
[END_OD_OPERATION]::[PVB_DOWNLOAD_CUR] Node2 = #text =
[END_OD_OPERATION]::[PVB_DOWNLOAD_CUR] -> cbr_curs : proxy [:] date=01/04/13
11:50:52 [END_OD_OPERATION]::[PVB_DOWNLOAD_CUR]<?xml version="1.0" encoding="windows-1251" ?>
<ValCurs Date="01/04/13">
</ValCurs>
[END_OD_OPERATION]::[PVB_DOWNLOAD_CUR] Node1 = ValCurs =
[END_OD_OPERATION]::[PVB_DOWNLOAD_CUR] Attr = Date = 01/04/13
[END_OD_OPERATION]::[PVB_DOWNLOAD_CUR] Node2 = #text =
[END_OD_OPERATION]::[PVB_DOWNLOAD_CUR] EXECUTE ERROR! ORA-06502: PL/SQL: ошибка числа или значения
----- PL/SQL Call Stack -----
object line object
handle number name
387319100 136 package body IBS.UTILS
3c5d5bb60 347 package body IBS.Z$END_OD_OPERATION_P2483159187
387282540 78 package body IBS.Z$U$2483159187
3c5627db8 1 anonymous block |
|
 |
prog Эксперт
Вступление в Клуб: 03.03.2008
|
|
 |
BoBr Участник со стажем
Вступление в Клуб: 30.01.2013
|
Пт Мар 29, 2013 13:21   |
|
Полезность: Нет оценки
|
Да у меня видимо год проставляется 13 вместо 2013, а как это можно поправить ? |
|
 |
yaffil Профи
Вступление в Клуб: 18.08.2011
|
Пт Мар 29, 2013 13:33   |
|
Полезность: Нет оценки
|
BoBr пишет: | Да у меня видимо год проставляется 13 вместо 2013, а как это можно поправить ? |
Так вы и передавайте вместо:
<ValCurs Date="01/04/13">
Это:
<ValCurs Date="01/04/2013">, лучше прям формат прописать to_date('01/04/2013','DD/MM/YYYY'), мало ли как у вас оракла настроена. |
|
 |
prog Эксперт
Вступление в Клуб: 03.03.2008
|
Пт Мар 29, 2013 13:45   |
|
Полезность: Нет оценки
|
вот кусок кода где формируется ссылка. Если ничего не меняли то и так должно работать
Код: | req := utl_http.begin_request(url||to_char(p_date, 'dd.mm.yyyy')); |
|
|
 |
|
|
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете голосовать в опросах
|
|