PACKAGE phone IS 



-- Главное меню

PROCEDURE MENU;



-- Список подразделений НГУ, если не определен параметр ID 

-- Список абонентов подразделения НГУ, которое определяет ID

PROCEDURE SUBDIVISIONS(ID VARCHAR2 DEFAULT NULL);



-- Перечень букв алфавита на которые начинаются фамилии абонентов

PROCEDURE NAME;



-- Список абонентов, первая буква фамилии которых равна LETTER

PROCEDURE NAME(LETTER VARCHAR2);



-- Вся информация имеющаяся в БД об абоненте

PROCEDURE PERSON(ID VARCHAR2);



-- Выводит форму для ввода условия поиска

PROCEDURE QUERY;



-- Список абонентов, удовлетворяющий условию поиска по ФИО

PROCEDURE QUERY_NAME(LETTERS VARCHAR2 DEFAULT NULL);



END;

PACKAGE BODY phone IS

 pkg VARCHAR2(100) := 'nsu.phone.'; --имя этого пакета



-- Заголовок HTML - документа 

 PROCEDURE HEADER(TT VARCHAR2) IS

 BEGIN

  htp.p('<HTML>');

  htp.p('<HEAD>');

  htp.p('<TITLE>'||TT||'</TITLE>');

  htp.p('</HEAD>');

  htp.p('<BODY BGCOLOR="#FFFFFF">');

  htp.p('<TABLE WIDTH="100%" BGCOLOR="CCCCCC"><TR><TD ALIGN="CENTER"><B>Телефонный справочник НГУ</B></TABLE>');

  htp.p('<P><P><P>');

 END;



-- Конец HTML - документа 

 PROCEDURE FOOTER IS

 BEGIN

  htp.p('<P><P><P>');

  htp.p('<CENTER>');

  htp.p('<HR>');

  htp.p('<FONT SIZE="-1">');

  htp.p('Информация предоставлена Отделом Средств Связи НГУ.<BR>тел.39-71-00');

  htp.p('<HR>');

  htp.p('<EM>© <A HREF="mailto:zev@nsu.ru">Evgeny Zybarev</A>, 1996</EM>');

  htp.p('</FONT>');

  htp.p('</CENTER>');

  htp.p('</BODY>');

  htp.p('</HTML>');

 END;



-- Вывод сообщения об ошибке

 PROCEDURE sqlerror IS

 BEGIN

  HEADER('Ошибка!');

  htp.p('<B>'||sqlerrm||'</B>');

  FOOTER;

 END;



-- Выводит список абонентов

-- Если PRM2 определено, то выбираются абоненты, работающие в подразделении 

-- "1-го" уровня PRM и подразделении "2-го" уровня PRM2

-- Если PRM2 не определено, то выбираются абоненты,

-- чьи ФИО соответствую шаблону PRM

 PROCEDURE PHONE_LIST(PRM VARCHAR2 DEFAULT '%', PRM2 VARCHAR2 DEFAULT NULL) IS

  Cursor frm1 is

    select Должность f1, ФИО f2, "Сл# телефон" f3, Место f4, ROWID

    from TEL_SPIS

    where upper(ПОДР) like upper(PRM) and

          upper(ПОДРАЗДЕЛЕНИЕ) like upper(PRM2)

    order by Должность;

  Cursor frm2 is

    select ФИО f2, "Сл# телефон" f3, Место f4, "Дом# телефон" f5, ROWID

    from TEL_SPIS

    where upper(ФИО) like upper(PRM)||'%'

    order by ФИО;

  ff VARCHAR2(100) := 'dummy';

  FRM Number(1) := 1;

 BEGIN

  If PRM2 is not NULL Then FRM := 1; Else FRM := 2; End If;

  htp.p('<TABLE WIDTH="100%" COLS="4" BORDERCOLOR="#CCCCCC">');

  htp.p('<TR BGCOLOR="#CCCCCC">');

  If FRM=1 Then htp.p('<TH>Должность или<BR>подразделение'); End If;

  htp.p('<TH>Фамилия, имя, отчество');

  htp.p('<TH>Телефон');

  If FRM=2 Then htp.p('<TH>Домашний<BR>телефон'); End If;

  htp.p('<TH>Номер комнаты<BR>и корпус');

  If FRM=1 Then

   For rec in frm1 Loop

    htp.p('<TR ALIGN="LEFT">');

    If ff!=rec.f1||rec.f2 Then

     ff:=rec.f1||rec.f2;

     htp.p('<TD>'||rec.f1);

     htp.p('<TD><A HREF="'||pkg||'person?ID='||rec.ROWID||'">'||rec.f2||'</A>');

    Else

     htp.p('<TD><TD>');

    End If;

    htp.p('<TD ALIGN="CENTER">'||rec.f3);

    htp.p('<TD ALIGN="CENTER">'||rec.f4);

   End Loop;

  ElsIf FRM=2 Then

   For rec in frm2 Loop

    htp.p('<TR ALIGN="LEFT">');

    htp.p('<TD>');

    If ff!=rec.f2 Then

     ff:=rec.f2;

     htp.p('<A HREF="'||pkg||'person?ID='||rec.ROWID||'">'||rec.f2||'</A>');

    End If;

    htp.p('<TD ALIGN="CENTER">'||rec.f3);

    htp.p('<TD ALIGN="CENTER">'||rec.f5);

    htp.p('<TD ALIGN="CENTER">'||rec.f4);

   End Loop;

  End If;

  htp.p('</TABLE>');

 END;



-- Главное меню

 PROCEDURE MENU IS

 BEGIN

  HEADER('Телефонный справочник НГУ');

  htp.p('<CENTER>');

  htp.p('<TABLE BGCOLOR="#FFFFCC" WIDTH="50%" BORDER="1">');

  htp.p('<TR ALIGN="CENTER">');

  htp.p('<TD>');

  htp.p('<A HREF="'||pkg||'subdivisions"><FONT SIZE="+2">Подразделения НГУ</FONT></A>');

  htp.p('</TD>');

  htp.p('</TR>');

  htp.p('<TR ALIGN="CENTER">');

  htp.p('<TD>');

  htp.p('<A HREF="'||pkg||'name"><FONT SIZE="+2">Именной указатель</FONT></A>');

  htp.p('</TD>');

  htp.p('<TR ALIGN="CENTER">');

  htp.p('<TD>');

  htp.p('<A HREF="'||pkg||'query"><FONT SIZE="+2">Поиск по ФИО</FONT></A>');

  htp.p('</TD>');

  htp.p('</TR>');

  htp.p('</TABLE>');

  htp.p('</CENTER>');

  FOOTER;

 EXCEPTION WHEN OTHERS THEN sqlerror;

 END;



-- Список подразделений НГУ, если не определен параметр ID 

-- Список абонентов подразделения НГУ, которое определяет ID

 PROCEDURE SUBDIVISIONS(ID VARCHAR2 DEFAULT NULL) IS

  cursor sd is

    select ПОДРАЗДЕЛЕНИЕ f1, max(ROWID) f2 from TEL_SPIS

    group by ПОДРАЗДЕЛЕНИЕ order by 1;

 BEGIN

  HEADER('Телефонный справочник НГУ. Подразделения.');

  If ID is NULL Then

  htp.p('<CENTER><FONT SIZE="+1">Подразделения</FONT></CENTER>');

  htp.p('<HR>');

   htp.p('<UL>');

   For rec in sd Loop

    htp.p('<LI><A HREF="'||pkg||'subdivisions?ID='||rec.f2||'">'||rec.f1||'</A>');

   End Loop;

   htp.p('</UL>');

  Else

   Declare

    pdr VarChar2(100);

   Begin

    For rec in (select ПОДРАЗДЕЛЕНИЕ f1 from TEL_SPIS where ROWID=ID) Loop

     htp.p('<CENTER><FONT SIZE="+2"><B>'||rec.f1||'</B></FONT></CENTER>');

     htp.p('<HR>');

     pdr := rec.f1;

    End Loop;

    For rec in (select DISTINCT ПОДР f1 from TEL_SPIS

                where ПОДРАЗДЕЛЕНИЕ=pdr and ПОДР=pdr order by 1)

    Loop

     PHONE_LIST(rec.f1,pdr);

    End Loop;

    For rec in (select DISTINCT ПОДР f1 from TEL_SPIS

                where ПОДРАЗДЕЛЕНИЕ=pdr and ПОДР!=pdr order by 1)

    Loop

     htp.p('<HR>');

     htp.p('<CENTER><FONT SIZE="+2">'||rec.f1||'</FONT></CENTER>');

     htp.p('<HR>');

     PHONE_LIST(rec.f1,pdr);

    End Loop;

   End;

  End If;

  FOOTER;

 EXCEPTION WHEN OTHERS THEN sqlerror;

 END;



-- Перечень букв алфавита на которые начинаются фамилии абонентов

 PROCEDURE NAME IS

  Cursor alf is select DISTINCT upper(substr(ФИО,1,1)) f1

                from TEL_SPIS

                where ФИО is not NULL

                order by 1;

  i Number := 0;

  n Number := 10;

 BEGIN

  HEADER('Телефонный справочник НГУ. Именной указатель.');

  htp.p('<CENTER>');

  htp.p('<TABLE BORDER="1" CELLSPACING="3" CELLPADDING="3">');

  htp.p('<CAPTION>');

  htp.p('<HR WIDTH="300">');

  htp.p('<FONT SIZE="+2">Именной указатель</FONT>');

  htp.p('<HR WIDTH="300">');

  htp.p('</CAPTION>');

  htp.p('<TR BGCOLOR="#CCCCCC" ALIGN="CENTER">');

  For rec in alf Loop

   If i=n Then

     htp.p('<TR BGCOLOR="#CCCCCC" ALIGN="CENTER">');

     i:=0;

   End If;

   i := i+1;

   htp.p('<TD>');

   htp.p('<FONT SIZE="+2">');

   htp.p('<A HREF="'||pkg||'name?LETTER='||to_char(ascii(rec.f1))||'">'||rec.f1||'</A>');

   htp.p('</FONT>');

  End Loop;

  For j in i+1..n Loop

   htp.p('<TD> ');

  End Loop;

  htp.p('</TABLE>');

  htp.p('</CENTER>');

  FOOTER;

 EXCEPTION WHEN OTHERS THEN sqlerror;

 END;



-- Список абонентов, первая буква фамилии которых равна LETTER

 PROCEDURE NAME(LETTER VARCHAR2) IS

  ff VARCHAR2(100):='dummy';

 BEGIN

  HEADER('Телефонный справочник НГУ. Именной указатель. '||LETTER);

  htp.p('<CENTER>');

  htp.p('<FONT SIZE="+1">Именной указатель</FONT>');

  htp.p('<BR><FONT SIZE="+5">= '||chr(LETTER)||' =</FONT>');

  htp.p('</CENTER>');

  PHONE_LIST(chr(LETTER));

  FOOTER;

 EXCEPTION WHEN OTHERS THEN sqlerror;

 END;



 -- Вся информация имеющаяся в БД об абоненте

PROCEDURE PERSON(ID VARCHAR2) IS

  cursor fio is select ФИО f1 from TEL_SPIS where ROWID=ID;

  cursor prs(fio VARCHAR2) is

   select ПОДРАЗДЕЛЕНИЕ f1, ПОДР f2, ДОЛЖНОСТЬ f3, МЕСТО f4, "Сл# телефон" f5

   from TEL_SPIS where ФИО=fio order by 1,2;

  cursor zv(fio VARCHAR2) is

    select distinct ЗВАНИЕ f1 from TEL_SPIS where ФИО=fio;

  cursor dt(fio VARCHAR2) is

    select distinct "Дом# телефон" f1 from TEL_SPIS

      where ФИО=fio and "Дом# телефон" is not NULL;

  ff VARCHAR2(100);

  f1 VARCHAR2(100) := 'dummy';

  f2 VARCHAR2(100) := 'dummy';

  f3 VARCHAR2(100) := 'dummy';

  f4 VARCHAR2(100) := 'dummy';

 BEGIN

  open fio; fetch fio into ff; close fio;

  HEADER('Телефонный справочник НГУ. '||ff);

  htp.p('<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0">');

  htp.p('<TR><TD ALIGN="CENTER"><FONT SIZE="+3">'||ff||'</FONT>');

  htp.p('<TR><TD ALIGN="CENTER">');

  For rec in zv(ff) Loop

   If zv%ROWCOUNT>1 Then htp.p(', '); End If;

   htp.p(rec.f1);

  End Loop;

  htp.p('</TABLE>');

  htp.p('<CENTER>');

  For rec in prs(ff) Loop

   If f1!=rec.f1 Then

     htp.p('<HR>');

     f1:=rec.f1;

     htp.p('<FONT SIZE="+2"><B>'||rec.f1||'</B></FONT>');

   End If;

   If f2!=rec.f2 and rec.f2!=rec.f1 Then

     f2:=rec.f2;

     htp.p('<BR><FONT SIZE="+1">'||rec.f2||'</FONT>');

   End If;

   If f3!=rec.f3 Then f3:=rec.f3; htp.p('<BR>'||rec.f3); End If;

   If f4!=rec.f4 Then

     f4:=rec.f4;

     htp.p('<BR>'||rec.f4||'<BR>');

   Else

     htp.p('<BR>');

   End If;

   htp.p('<FONT SIZE="+2">'||rec.f5||'</FONT>');

  End Loop;

  For rec in dt(ff) Loop

   If dt%ROWCOUNT=1 Then

     htp.p('<HR>Дом.тел.: ');

   Else

     htp.p(', ');

   End If;

   htp.p(rec.f1);

  End Loop;

  htp.p('</CENTER>');

  FOOTER;

 EXCEPTION WHEN OTHERS THEN sqlerror;

 END;



-- Выводит форму для ввода условия поиска

 PROCEDURE QUERY IS

 BEGIN

  HEADER('Телефонный справочник НГУ. Поиск.');

  htp.p('<CENTER>');

  htp.p('<FONT SIZE="+2">Поиск</FONT>');

  htp.p('<HR>');

  htp.p('<FORM ACTION="'||pkg||'query_name" METHOD="POST">');

  htp.p('ФИО : <INPUT TYPE="TEXT" NAME="LETTERS" SIZE="30">');

  htp.p('<INPUT TYPE="SUBMIT" VALUE="Выполнить">');

  htp.p('<FORM>');

  htp.p('</CENTER>');

  htp.p('<HR>');

  htp.p('<BR>В качестве условия запроса можно задать первые буквы фамилии или шаблон :');

  htp.p('<DL>');

  htp.p('<DD> _ (подчерк) - заменяет любой символ');

  htp.p('<DD> % (процент) - заменяет произвольную последовательность символов');

  htp.p('</DL>');

  htp.p('<BR><B>Например:</B> "% Сергей С_востьянович"');

  FOOTER;

 EXCEPTION WHEN OTHERS THEN sqlerror;

 END;



-- Список абонентов, удовлетворяющий условию поиска по ФИО

 PROCEDURE QUERY_NAME(LETTERS VARCHAR2 DEFAULT NULL) IS

 BEGIN

  HEADER('Телефонный справочник НГУ. Поиск по ФИО. '||LETTERS);

  htp.p('<CENTER>');

  htp.p('<FONT SIZE="+2">Результат поиска по ФИО</FONT><BR>');

  htp.p('<FONT SIZE="+1">("'||LETTERS||'")</FONT>');

  htp.p('</CENTER>');

  If LETTERS is NULL Then

    htp.p('<H1>Не задано условие для запроса!</H1>');

  Else

    PHONE_LIST(LETTERS);

  End If;

  FOOTER;

 EXCEPTION WHEN OTHERS THEN sqlerror;

 END;



END;