CftClub.ru
Клуб специалистов ЦФТ-Банк

Загрузка курсов валют прямо с сайта cbr.ru
На страницу 1, 2  След.
 
Ответить на тему    Клуб специалистов ЦФТ-Банк (IBSO) -> Справочник PL/PLUS: Функции, примеры, приёмы
Предыдущая тема :: Следующая тема  
Автор Сообщение
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    Ответить с цитатой
Полезность: Нет оценки
вот секция проверки кстати Smile Надо же, за несколько лет ни у кого даже вопросов не возникло...

Код:
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    Ответить с цитатой
Полезность: Нет оценки
Так и не получается настроить Sad. Вывожу операцию в монитор и там вижу такую ошибку:

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
СообщениеПт Мар 29, 2013 11:04    Ответить с цитатой
Полезность: Нет оценки
вот сравните то что должно получиться по сылке http://www.cbr.ru/scripts/xml_daily.asp?date_req=01.04.2013 с тем что получилось у вас
Цитата:
<?xml version="1.0" encoding="windows-1251" ?>

<ValCurs Date="01/04/13">

</ValCurs>


проверьте ссылку. У вас скорее всего что-то типа http://www.cbr.ru/scripts/xml_daily.asp?date_req=01.04.13
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'));
Показать сообщения:   
Ответить на тему    Клуб специалистов ЦФТ-Банк (IBSO) -> Справочник PL/PLUS: Функции, примеры, приёмы Часовой пояс: GMT + 3
На страницу 1, 2  След.
Страница 1 из 2

 
Перейти:  
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Рейтинг@Mail.ru