You are on page 1of 132

UNIVERSITATEA DIN CRAIOVA

FACULTATEA DE AUTOMATIC, CALCULATOARE I ELECTRONIC

Secia Calculatoare Romn

Proiect de Licen
Aplicaie medical pentru gestionarea activitii medicilor de familie

Coordonator tiinific: Prof. Liana Stnescu

Absolvent: M a n d a M i h a e l a- A d i n a

Craiova Iunie 2009

Cuprins

INTRODUCERE ................................................................... 3 1.1 Obiective ................................................................... 3 1.2 Contribuiile tezei ....................................................... 4

FUNDAMENTE TEORETICE ............................................... 6 2.1 SQL Server 2005 i JDBC ........................................... 6 date ...................................................................... 6 2.1.2 SQL Server 2005 .................................................. 10 2.1.2.1 Caracteristici evolutive fa de versiunea 2000 ........................................................ 10 2.1.2.2 SQL Server 2005 Express Edition ............... 13 2.1.2.3 SQL Server Reporting Services .................. 14 2.2 Programarea concurent n JAVA .................................. 18 2.2.1 Crearea firelor de execuie implementnd interfaa Runnable ............................................................. 18 2.1.1 JDBC accesul din platforma JAVA la bazele de date

3 ARHITECTURA I FUNCIONALITATEA SISTEMULUI .... 22 4 DESCRIEREA APLICAIEI ................................................. 23 4.1 Structura bazei de date ................................................ 23 4.2 Drepturi de utilizator ................................................... 35 4.3 Interfee grafice .......................................................... 37 4.3.1 Interfaa grafic pentru medic ........................... 37 4.3.2 Interfaa grafic pentru pacient ......................... 64 4.4 Operaii efectuate asupra bazei de date .......................... 66 4.4.1 Conectarea la baza de date ................................ 66 4.4.2 Operaii de manipulare a datelor: SELECT, INSERT, UPDATE, DELETE ............ 67

4.4.3 Rapoarte ......................................................... 72 5 6 7 CONCLUZII ........................................................................ 79 BIBLIOGRAFIE .................................................................. 80 ANEXE ................................................................................ 8 1

1 INTRODUCERE

1.1

Obiective

Lucrarea

de

fa

urmrete

prezentarea

unei

aplicaii

informatice avnd caracter medical i care se adreseaz medicilor de familie din Romnia, cu scopul de a ine o eviden clar i concis a activitii lunare medicale i a altor date legate de administrarea unei uniti sanitare din acest sector medical. n plus, aplicaia ofer posibilitatea pacientul de a-i vizualiza nregistrrile sale n baza de date medical, prezentate sub forma unei fie medicale/foi de

observaie. Realizat n mediul de dezvoltare Eclipse, aplicaia folosete o baz de date stocat pe un SGBD SQL Server 2005. Aplicaia este uor de utilizat de ctre orice cadrul medical, avnd o interfa intuitiv i prietenoas prin intermediul creia se asigur managementul ntregii activiti din cabinetul medicului de familie. Pe lng programul ncrcat de lucru att pe teren, ct i n cabinet, medicul are sarcina de a prelucra integral datele privind activitatea desfaurat zilnic. n acest scop, aplicaia de fa ncearc s elimine rutina i timpul pierdut n completarea formularelor i a rapoartelor. Introducerea datelor n baza de date se face rapid, n general prin simpla selectare din tabele, majoritarea cmpurilor completnduse automat pentru a reduce ansele de a tasta date eronate.

Sistemul ine evidena serviciilor medicale oferite pe categorii de pacieni i a documentelor medicale specifice: reete, bilete de trimitere, certificate medicale. Prin ncheierea de contracte i

convenii cu instituii superioare ale sistemului romnesc de santate, Casele Judeene de Asigurri de Sntate (CJAS), medicii de familie se fac obligai de a efectua rapoarte periodice ctre acestea i ctre Casa Naional de Asigurri de Sntate (CNAS). Formatul raportului creat pentru medic cuprinde informaiile privind activitile lunare: lista serviciilor medicale pe pachete de servicii - pentru asigurai i pentru neasigurai, lista pacienilor noi intrai i a celor ieii din eviden, un centralizator cu punctajele obinute pentru fiecare categorie de servicii, precum i diagrame relevante.

1.2

Contribuiile tezei

Aplicaia are misiunea de a simplifica i de a reduce eforturile necesare desfurarii activitii medicilor de familie. Alegerea serverului de baze de date este justificat n

urmtoarele rnduri. Pe piaa global, SQL Server trebuie s fac fa unei competiii serioase: Oracle i Sysbase. Oracle este vzut probabil ca lider de pia n comunitatea bazelor de date, avnd un numar important de utilizatori. Nu exist dubiu c este un produs foarte bun, care se potrivete n special companiilor mari ce necesit soluii pe masur. Este un instrument puternic ce ofer scalabilitate i performan; este flexibil permind adugarea de noi instrumente dup nevoi, fcndu-l astfel s fie mai adaptabil dect SQL Server. De exemplu, SQL Server 2005 impune instalarea platformei .NET Framework, fie c se vor folosi funcionalitile acesteia, fie c nu. i totui, Oracle nu este att de prietenos din punctul de vedere al dezvoltatorului de aplicaii n ceea ce privete instrumentul pentru interogri ad-hoc sau cele pentru tehnologiile Web i XML,

precum i din maniera n care poi construi o soluie complet a bazei de date pentru un sistem. Alte inconveninte se refer la costurile i complexitatea funcionaliti, instalrii SQL i utilizarea 2005 poate eficient. face fa Cu cu noile succes

Server

competitorului su principal. Deci SQL Server pare a fi cea mai bun soluie de pe piaa de profil, i n multe scenarii chiar este. Poate fi alegerea potrivit pentru un grup mic de utilizatori, aa cum este cazul aplicaiei noastre, precum i la fel de potrivit n marile corporaii. Nu implic mari costuri de ntreinere i este uor de instalat, cci vine ntr-un pachet complet pentru majoritatea funcionalitilor necesare, cu o simpl instalare ulterioar a altor instrumente, dup cerine. n plus, SQL Server vine cu o soluie util pentru creare de rapoarte, soluie care rezolv problema raportrii medicului de familie ctre instituiile superioare. Datorit procesului rapid de creare,

oricnd pot fi adugate noi rapoarte n funcie de necesiti. n sistemul actual al sntii, referitor la seciunea medicinei de familie, achiziia i transformarea datelor n format electronic se face cu ajutorul unei aplicaii informatice ce folosete baze de date, instalate pe un computer local, prezent n fiecare unitate medical. SGDB-ul folosit este unul de tip desktop: MS Access, un sistem de administrare a bazelor de date i aministreaz eficient un numr redus de nregistrri: n jur de 20000-30000 nregistrri, folosit n general n activitatea de management n companiile mici. Un astfel de SGBD de tip desktop nu poate accepta solicitri de la ali clieni, cu alte

cuvinte nu acioneaz ca un server SQL. n contrast, un SGBD de tip SQL cum este MS SQL 2005 acioneaz drept parte a unei configuraii de reea de tip client/server, iar regulile care descriu modul n care se transmit solicitrile i rspunsurile sunt grupate sub forma

protocoalelor SGBD, ca ODBC i JDBC. Pentru a evita limitrile SGBD-ului de tip desktop, pentru dezvoltarea aplicaiei n cauz am ales, dintre cele cteva produse renumite pe piaa serverelor de baze de date, serverul firmei

Microsoft, datorit evoluiei rapide i performanelor prin care s-a

remarcat. Acest produs a eliminat categoric necesitatea unor unelte exterioare pentru a realiza rapoarte. Aplicaia respect modelul arhitectural al unei aplicaii

client/server pe un singur nivel (engl. one-tier architecture), acela n care datele sunt stocate pe acelai computer cu partea de interfa pentru utilizatorul care le exploateaz. Exist i dezavantaje, exist

i avantaje ce motiveaz modelul adoptat, printre care faptul c este o tehnologie uor de implementat i cu costuri modeste de dezvoltare i ntreinere.

2 FUNDAMENTE TEORETICE

2.1

SQL Server 2005 i JDBC

2.1.1

J D B C - a c c e s u l di n p l a t f o r m a J A V A l a bazele de date

Java Database Connectivity (JDBC) este un produs tip API JAVA pentru accesul la orice tip de tabel, asigurnd ptrunderea aplicaiei JAVA la orice surs de date, independent de baza de date, cu condiia s fie disponibile drivere JDBC corespunztoare, care s ndeplineasc urmtoarele funcii: stabilirea conexiunii la baza de date; transmiterea interogrilor SQL i a instruciunilor de

actualizare la sursa de date;

posibilitatea procesrii rezultatelor.

Tehnologia JDBC este realizat prin utilizarea unei biblioteci de clase (java.sql) care permite executarea unei cereri de tip SQL pentru baze de date relaionale, din aplicaii scrise n JAVA. Avantajul utilizrii acestui pachet este c aplicaiile JAVA sunt aceleai,

indiferent de baza de date. JDBC-ul are o construcie asemntoare cu a ODBC-ului, fiind practic varianta ODBC pe obiecte, pentru JAVA, ambele pornind de la specificaiile X/Open SQL Call Level Interface. Accesul la o anumit baza de date din Java via JDBC se face pe baza unui driver specific tipului bazei de date pe care dorim s-o utilizm, fie via ODBC, folosind un bridge JDBC-ODBC. n acest caz, apelurile JDBC sunt transformate n apeluri ODBC. JDBC-ul este o interfa low-level, fiind folosit pentru

execuia direct a comenzilor SQL i care are implementate dou APIuri mai importante: - un preprocesor SQL ncapsulat pentru JAVA, care permite folosirea secvenelor mixte SQL direct din JAVA ; - o mapare direct a tabelelor bazei de date relaionale n JAVA, prin care fiecare articol al bazei de date devine o instan a unei clase, i fiecare cmp corespunde unui atribut al instanei respective. Firma disponibile: * driver-ele de tipul 1 reprezint singura punte JDBC-ODBC; * driver-ele de tipul 2 nvelesc codul nativ, adic driverele exis- tente, n JAVA; * driver-ele de tipul 3 sunt scrise complet n JAVA i utilizeaz o component pe server i un protocol de reea pentru comunicare; * driver-ele de tipul 4, scrise complet n JAVA, folosesc un protocol specific bazei de date. n figura de mai jos prezentat n lucrarea [2.4] se pot observa Sun a stabilit o clasificare a tipurilor de drivere

diferenele dintre cele patru tipuri de driver-e JDBC:

Fig 1. Tipuri de driver-e JDBC

Execuia

unei

comenzi

SQL

din

interiorul

aplicaiei

JAVA

folosind API-ul JDBC, presupune parcurgerea urmtoarelor etape: - ncrcarea driver-ului JDBC, - realizarea conexiunii la baza de date prin intermediul driverului: Connection c = DriverManagement.getConnection(); - construcia comenzii: Statement s = c.createStatemant(); - execuia comenzii i returnarea rezultatului: ResultSet r = s.executeQuery(). Pentru realizarea acestor funcii avem la dispoziie o serie de clase i interfee din biblioteca java.sql: - DriverManager - folosit pentru a facilita utilizarea mai multor drivere de baze de date ntr-o singur aplicaie, fiecare dintre drivere putnd fi utilizat pentru conectarea la o surs diferit de date; ncarc un driver JDBC i gestioneaz conexiunea la baza de date; - Connection - obiect care specific cu ce baz de date se face comunicaia;

Statement, PreparedStatement, CallableStatement - gestio-

neaz o conexiune SQL; - ResultSet - asigur accesul la rezultatele obinute n urma execuiei unei instruciuni SQL; ResultSetMetaData despre tipurile i interfa folosit pentru a obine dintr-un

informaii ResultSet.

proprietile

coloanelor

Dup ncrcarea driver-ului, se poate stabili o conexiune JDBC cu baza de date, conexiune indentificat printr-un URL specific.

Sintaxa standard este: jdbc:<subprotocol>:<nume> Sintaxa particular pentru a oferi aplicaiei JAVA acces la o baz de date gestionate de SGBD-ul SQL Server 2005 are mai multe forme; n cazul aplicaiei de fa s-a utilizat urmtoarea form: jdbc:sqlserver://localhost:1433;databaseName:medicina_familie; integratedSecurity:true; Conexiunea se realizeaz folosind modul de autentificare

Windows, pentru a beneficia de modelul de securitate Windows i a politicilor de securitate configurate pe domeniu. Avantajele utilizrii JDBC fa de ODBC, n condiiile n care ODBC este cea mai folosit interfa pentru accesul la aproape orice tip de baze de date relaionale. De exemplu, ODBC nu este potrivit pentru a fi utilizat direct din JAVA pentru c folosete interfa C, iar apelurile JAVA ctre C pot provoca probleme, legate de portabilitate i securitate. n plus, ODBC-ul este mai greu de nvaat, avnd opiuni complexe chiar i pentru interogri simple. De cealalt parte, JDBC-ul este o soluie pur JAVA, putnd fi deci portabil i securizat pe toate platformele, de la NC (Network Computer) la mainframe-uri. Driver-e JDBC pentru SQL Server 2005

Microsoft pune la dispoziie utilizatorilor de SQL Server cteva versiuni de drivere JDBC ce pot fi folosite pentru interconectivitatea cu un server de SQL 2000, 2005 i 2008. Cea mai recent versiune, driver-ul JDBC 2.0 aduce multiple mbuntiri fa de predecesorii si, versiunile 1.1 i 1.2. Driver-ul JDBC 2.0 este un driver de tip 4 i poate accesa multe din caracteristicile actuale ale SQL Server 2005, incluznd <<database mirroring>> i tranzaciile <<snapshot>>; ofer suport pentru tipurile de date SQLXML, metode noi de tipul get, set i update pentru tipurile de date national character: nchar, nvarchar, longnvarchar, nclob. Suport interfaa java.sql.Wrapper care ofer un mecanism de acces la extensiile ale API-lui SQL Server printr-o JDBC care sunt specifice driverului proxy. mbuntete clasa

interfa

SQLServerConnection prin adugarea de metode noi pentru crearea obiectelor de tip blob, clob i nclob, precum i alte noi metode specifice altor clase.

Server JDBC Driver URL

MS SQL Server 2005 com.microsoft.sqlserver.jdbc.SQLServerDriver jdbc:sqlserver://

2.1.2 SQL Server 2005

Una

dintre

tendinele

contemporane

reprezint

creterea

nevoii de disponibilitate, a cererii pentru sisteme scalabile care s poat corespunde unor eventuale modificri ulterioare, ce pot fi realizate chiar de ctre utilizator. Aceste nevoi se fac simite nu doar la nivelul marilor corporaii, ci i la nivelul consumatorilor

individuali sau al micilor ntreprinztori. n acest context, Microsoft a ncercat s se adreseze acestor noi necesiti ale consumatorilor prin pachetul SQL Server 2005, care

10

poate

rula

la

fel

de

bine

medii

de

orice

dimensiune,

prin

intermediul urmtoarelor versiuni: SQL Server Standard Edition, SQL Server 2005 Express Edition, SQL Server 2005 Mobile Edition. Familia de ediii SQL Server include toate funcionalitile de care este nevoie ntr-o platform complet de stocare preconfigurat a datelor, management i analiz, cu condiii de liceniere flexibile care permit alegerea soluiei ce corespunde cel mai bine necesitilor. Pe site-ul oficial al companiei Microsoft, ntr-o scurta

prezentare se precizeaz: Conceput pentru a realiza o scalare de la cele mai mari ntreprinderi pn la cele mai mici, SQL Server 2005 ofer aceeai performan, securitate, fiabilitate i valoare de business tuturor clienilor. [2.1]

2.1.2.1 Caracteristici evolutive fa de versiunea 2000

Dintre

cele

mai

importante

schimbri

domeniul

disponibilitii i scalabilitii introduse de SQL Server 2005 fa de versiunea 2000 sunt important de reinut urmtoarele: Database mirroring: are rolul de a crete disponibilitatea datelor i de a permite recuperarea de pe urma erorilor, n cazul n care serverul pe care se afl baza de date devine nedisponibil. Ceea ce apare nou fa de SQL Server 2000 este prezena unui al treilea server, care are rolul de a monitoriza operaiile dintre cele dou servere, obiectivul din principal partea cele fiind detecia cderilor Att prin timp lipsa ct

rspunsului sincronizarea

server-ului dou

principal. este

dintre

servere

meninut,

server-ul

oglind poate prelua cererile clientului, fr ntrziere prea mare (cteva secunde) i fr nici o pierdere de date. Dei mecanismul de oglindire a bazei de date implic trei servere distincte, fiecare

11

dintre ei poate juca roluri diferite n sesiuni de database mirroring diferite. restore online: ofer posibilitatea de a restaura datele fr a nchide n prealabil baza de date, cum era cazul versiunilor precedente de SQL Server. Utilizatorii sunt prevenii doar la accesarea datelor care au fost restaurate; suport att pentru Windows-ul pe 32 ct i pentru cel pe 64 de bii; partiionarea tabelelor: ofer posibilitatea partiionrii tabelelor ntre grupele de fiiere din baza de date, ceea ce optimizeaz operaiile pe tabele de dimensiuni mari; instantaneu al bazei de date (engl. database snapshot) snapshot-urile genereaz o vedere read-only a bezei de date n cauz, care poate fi folosit, de exemplu, pentru a recupera rapid datele dup o modificare eronat. Snapshot-urile (instantanee-le) difer de copiere deoarece ocup doar spaiul necesar pentru a conine schimbrile aplicate bazei de date dup ce aceasta a fost creat. Izolarea snapshoturilor ofer acces paralel la ultima nregistrare pe care s-a produs un commit n baza de date i care poate fi folosit pentru a elimina problemele de blocaj care pot aprea atunci cnd mai muli utilizatori opereaz simultan asupra aceluiai set de date; replicarea implementarea SQL Server 2000 a fost mbuntit prin introducerea unei noi topologii peer-to-peer, a

abilitii de a replica date prin HTTP sau HTTPS i de replicare din bazele de date Oracle; SQL Service Broker ofer funcionalitatea rutrii mesajelor asincrone i garanteaz livrarea pentru scenarii care implic task-uri de procesare a datelor complexe, simultane, distribuite i

interdependente (folosite n special n aplicaiile e-commerce); referitor la problemele de securitate, SQL Server 2005

implementeaz urmtoarele modificri: setri secure by default, noi politici de logare SQL Server privitoare la parole, criptarea nativ a datelor i protejarea acestora prin parole sau certificate, motenirea autorizrilor;

12

SQL Server Integration Services conin faciliti noi care simplific extragerea datelor din diferite surse i le prelucreaz pentru a le utiliza n aplicaii analitice sau de Data Warehouse; introduce un nou tip de date varchar(MAX), mpreun cu nvarchar(MAX) i varbinary(MAX) care au proprietatea de a stoca pn la 2GB de date, incluznd date de tip text, ntext i image; Sistemul de Management SQL Server mbuntit; Reporting Services ofer posibilitatea de a crea i vizualiza rapoarte. Prin integrarea lui n SQL Server 2005 se elimin

necesitatea unor instrumente externe, cum ar fi Crystal Reports.

n tabelul urmtor, sunt sintetizate principalele mbuntiri aduse versiunii 2005, fa de cea precedent [2.2]:
Componente Extragere, transformare i ncrcare Baz de date relaional Baz de date multidimensional Data mining Gestiunea rapoartelor Analize i interogri ad-hoc SQL Server 2000 Data Transformation Services (DTS) Baz de date relaional SQL Server 2000 SQL Server 2000 Analysis Services SQL Server 2000 Analysis Services SQL Server 2000 Reporting Services Produsele Microsoft Office (Excel, componentele Office Web, Data Analyzer-ul, Instrumente pentru dezvoltarea aplicaiilor de baze de date i BI Sharepoint SQL Server 2005 SQL Server Integration Services (Nou!) Baz de date relaional SQL Server 2005 SQL Server 2005 Analysis Services SQL Server 2005 Analysis Services SQL Server 2005 Reporting Services Produsele Microsoft Office (Excel, componentele Office Web, Data Analyzer-ul, Sharepoint Portal) SQL Server 2005 Business Intelligence

Portal) SQL Server 2000 Enterprise Manager, Analysis Manager, Query Analyzer i multe altele

Development Studio (Nou!)

13

Instrumente pentru managementul baze de date

Enterprise

Manager,

SQL Server 2005 Management Studio (Nou!)

Analysis Manager

n concluzie, Microsoft propune o gam complet de soluii de Business Intelligence. Astfel, SQL Server 2005 integreaz servicii avansate de analiz a datelor i business intelligence. Versiunea de SQL Server 2005 Express Edition with Advances Series folosit de ctre aplicaie se poate descrca gratuit de pe siteul: http://www.microsoft.com/downloads/details.aspx?

familyid=4C6BA9FD-319A-4887-BC753B02B5E48A40&displaylang=en. Driver-ul cu versiunea 2.0 folosit pentru interconectivitatea JAVA-SQL Server funcioneaz cu succes.

2.1.2.2 SQL Server 2005 Express Edition

Sistemul SQL Server 2005 a evoluat rapid de la un mic desktop SGBD la un sistem puternic orientat pe performan i scalabilitate. n prezent, mai mult ca niciodat, dezvoltatorii extind bazele de date relaionale pentru a oferi o experien mbuntit utilizatorilor. Protejarea i managementul informaiilor n cadrul acestor aplicaii sunt critice. SQL Server Express ajut dezvoltatorii s genereze aplicaii fiabile oferind o baz de date disponibil, uor de utilizat i robust. Adesea, sistemele de baze de date sunt mult prea complexe pentru generarea de aplicaii simple. Microsoft Visual Studio 2005 i SQL Server Express reduc aceast complexitate, oferind un mediu de

dezvoltare simplu, dar puternic pentru generarea de aplicaii de date. Dezvoltatorii pot concepe scheme, aduga date i interoga baze de date locale n mediul Visual Studio 2005. Versiunea Express este o versiune uor de administrat. Este uor de instalat, cci interfaa cu utilizatorul pentru configurare este simplificat. Este uor de utilizat, punnd la dispoziie un instrument

14

nou de management i de editare a interogrilor, un optimizator avansat care optimizeaz automat interogrile, ofer securitate robust - trei nivele de securitate cu acces pe baz de cod: sigur, nesigur i acces extern (verificabil). Ofer suport pentru XML: tipul de date XML nativ, suport pentruy XQuery, pentru scheme XML. Pe scurt, SQL Server Express ofer funcionalitate complet pentru baze de date: Proceduri stocate Vizualizri Declanatoare Cursoare Indeci extini Nivel de izolare snapshot Optimizator avansat al interogrilor Suport pentru Transact-SQL Dac pe viitor se dovedesc a fi necesare caracteristici mai avansate pentru bazele de date, se poate realiza upgrade facil de la SQL Server Express la versiunile mai sofisticate ale SQL Server.

2.1.2.3 SQL Server Reporting Services

SQL Server Reporting Services (SSRS) este o soluie complet de tip server pentru crearea, administrarea i furnizarea att a

rapoartelor tradiionale pe hrtie, ct i a celor n format Web, interactiv. Reporting Services ntregete facilitile existente de business intelligence i data warehousing din Microsoft Office i Microsoft SQL Server. [2.2] Are ca scop mbuntirea productivitii organizaiilor oferind un mediu de raportare performant i uor de administrat. SSRS este astzi o parte esenial din SQL Server 2005 i este disponibil n multe ediii, de la Express la Enterprise. Deoarece este

15

o soluie de raportare de tip Web, un raport este accesibil oricrui tip de client, de la browser pn la uzualele formulare Windows Form. De asemenea, pentru ca rapoartele sunt accesibile via Hypertext Transfer Protocol (HTTP) sau HTTP Secure (HTTPS), ele se pot vizualiza de

ctre orice client care are acces la serverul Web SSRS, fr a fi nevoie ca rapoartele s fie stocate local cu aplicaiile client robuste.

Figura urmtoare descrie arhitectura SSRS:

F i g 1. Arhi t ect ura S erverul ui de R apoart e

Reporting instrumente i

Services medii de

suport editare

integrarea ca

cu

varietate mai

de

pentru

utilizatorii

puin

experimentai s poat s creeze i s-i personalizeze rapoartele far a scrie cod. Report Wizard este un vrjitor care ndrum utilizatorii, pas cu pas, n realizarea operaiunilor de creare i personalizare a

rapoartelor. Query Builder este instrumentul care permite realizarea vizual a interogrilor care vor sta la baza rapoartelor, chiar fr a fi necesar cunoaterea limbajului SQL pentru filtrarea datelor. Report Designer, instrumentul pentru crearea de rapoarte inclus n Reporting Services, folosete mediul de dezvoltare integrat (IDE) Microsoft Visual Studio.NET pentru a accesa toate facilitaile de proiectare a rapoartelor. Cu Report Designer, administratorii pot defini surse de date i pot realiza interogri, pot aduga regiuni de date i cmpuri, pot defini formatul i pot stabili faciliti interactive pentru rapoarte.

16

Report Manager este o aplicaie Web care administreaz toate aspectele legate de raportare, incluznd: surse de date, execuia rapoartelor i planificarea lor, istoria rapoartelor, securitate, abonarea la rapoarte periodice, furnizarea rapoartelor i administrarea

serverului de raportare. Elemente defintorii privind Reporting Services Beneficiind de formate flexibile de realizare a rapoartelor, SSRS poate, de asemenea, furniza rapoarte ctre o varietate de

dispozitive. Aceste faciliti includ: generarea rapoartelor la cerere sau bazat pe evenimente Reporting Services suport att furnizarea de rapoarte la cerere, atunci cnd utilizatorii cer un raport n mod dinamic de la serverul de raportare, ct i raportare planificat sau bazat pe evenimente, n situaiile n care abonaii obin rapoarte automat, imediat ce datele unui raport au fost actualizate sau conform unei planificri orare. abonamente Aceast facilitate definete utilizatorii care doresc s obin un raport, dar i formatul i preferinele legate de acest raport. De exemplu, un utilizator doreste o versiune HTML a raportului, n timp ce un altul prefer un fiier Microsoft Excel ataat la un e-mail. Utilizatorii pot crea abonamente personale, definind preferinele

legate de obinerea de rapoarte, precum i care sunt rapoartele pe care doresc s le obin. Exist dou tipuri de abonamente: abonamentele condiionate de modelul de securitate i abonamentele condiionate de date. opiuni de afiare pentru rapoarte Pentru c aceasta operaiune este separat de procesarea iniial a datelor pentru raportare, acelai raport poate fi furnizat n formate diferite pentru o varietate mare de utilizatori. Arhitectura orientat pe servicii Web Aa cum am menionat, Reporting Services include un server de raportare bazat pe Web i o aplicaie de management al rapoartelor.

17

Folosind

serviciile

Web,

Reporting

Services

poate

lucra

cu

varietatea mare de platforme. Aceasta arhitectur prezint urmtoarele trasturi fundamentale: este scalabil i extensibil prin proiectare, oferind

conectivitate i fiabilitate nalt; - reduce costurile de infrastructur i implementare; - faciliteaz accesul uor i rapid la date, mbuntind productivitatea afacerii i oferind o conectivitate superioar ntre oameni i informaie; - folosete Report Definition Language (RDL), un standard bazat pe XML pentru a defini rapoarte. Extensii, API-uri i interfee Designul Interface) modular i API-ul (Application i Programming s

extensibil

permite

dezvoltatorilor

organizaiilor

foloseasc serviciile de raportare din SQL Server cu sisteme mai vechi i aplicaii tere. De exemplu, dezvoltatorii pot utiliza interfee

deschise i interfee pentru a: - realiza aplicaii care sa administreze serverul de raportare folosind o interfa Simple Object Access Protocol (SOAP); dezvolta aplicaii sau a utiliza un browser Web pentru

manipularea aspectului rapoartelor; crea extensii adiionale pentru rendering, furnizare i

procesare de date folosind Microsoft .NET Framework.

Deoarece,

calitate

de furnizor

de servicii

medicale,

medicul de familie face lunar raportarea activitii sale medicale ctre CJAS, Reporting Services a fost alegerea potrivit pentru crearea de rapoarte. SSRS este astfel o tehnologie care ofer medicului posibilitatea s transmit simplu informaii corecte personalului calificat, i pacientului s-i vizualizeze propria fi medical.

18

2.2

Programarea concurent n JAVA

2.2.1

Crearea firelor de execuie implementnd interfaa Runnable

n JAVA, programarea cu fire de execuie (engl. multithread) este un aspect important. Ca sinonime, n literatura de specialitate de menioneaz paralelismul prin i concurena. disponibile Limbajul ntr-unul JAVA dintre suport pachetele

multithearding

clasele

fundamentale, java.lang. Multithearding se refer la capacitatea unui program de a

executa mai multe secvene de cod n acelai timp, secvene care se numesc fire de execuie (engl. thread). Thread-urile fac trecerea de la programarea secvenial la cea paralel. Ca definiie, putem spune c un fir de execuie este o

succesiune secvenial de instruciuni care se execut n cadrul unui proces, aa cum este schiat n figur: [1.5]

Un program JAVA i poate defini nu doar un fir de execuie ci oricte, ceea ce nseamn c n cadrul unui proces se pot executa

19

simultan mai multe fire de execuie, permind efectuarea concurent a sarcinilor independente ale acelui program. Un fir de execuie poate fi asemnat cu o versiune redus a unui proces, ambele rulnd de simultan i independent lor. De pe o structur execuia

secvenial

format

instruciunile

asemenea,

simultan a firelor n cadrul unui proces este similar cu execuia concurent a proceselor: sistemul de operare va aloca procesorul dup o anumit strategie fiecrui fir de execuie pn la terminarea lor. Din acest motiv firele de execuie mai sunt numite i procese uoare. Exist o deosebirea major ntre un proces i un fir de execuie care const n faptul c firele de execuie nu pot rula dect n cadrul unui proces. O alt deosebire rezult din faptul c fiecare proces are propria sa memorie (propriul su spaiu de adrese), iar la crearea unui nou proces (fork) este realizat o copie exact a procesului printe: cod i date, n timp ce la crearea unui fir nu este copiat dect codul procesului printe, toate firele de execuie avnd acces la aceleai date, datele procesului original. Aadar, un fir mai poate fi privit i ca un context de execuie n cadrul unui proces. Firele de execuie sunt utile n multe privine, ns uzual ele sunt folosite pentru executarea unor operaii

consumatoare de timp fr a bloca procesul principal. Un fir de execuie este, ca orice obiect JAVA, o instan a unei clase. Firele definite de o clas vor avea acelai cod, deci aceeai secven de instruciuni. Crearea unei clase care s defineasc fire de execuie poate fi facut n dou moduri:

prin motenirea clasei Thread; prin implementarea interfeei Runnable.

Orice clas ale crei instane vor fi executate separat ntr-un fir propriu trebuie declarat ca fiind de tip Runnable. Aceasta este o interfa care conine o singur metod, i anume metoda run(). Aadar, orice clas ce descrie fire de execuie va suprascrie aceast metoda implementnd codul ce va fi rulat. Interfaa Runnable este

20

conceput ca fiind un protocol comun pentru obiectele care doresc s execute un anumit cod pe durata existenei lor. Cea mai important clas care implementeaz interfaa Runnable este chiar clasa Thread, iar folosirea celei de-a doua metode de creare a firelor de execuie ar permite motenirea cpabilitilor unei alte clase, dat fiind faptul c motenirea multipl nu este permis. Operaiile de creare a unui thread folosind interfaa Runnable sunt:

crearea clasei care s implementeze interfaa Runnable; implementarea metodei run() din interfaa Runnable; instanierea unui obiect al clasei utiliznd operatorul new crearea unui obiect din clasa Thread folosind un

constructor care primete ca parametru un obiect de tip Runnable;

pornirea firului de execuie folosind metoda start().

Spre deosebire de modalitatea anterioar, simpla instaniere a clasei care implementeaz o astfel de interfa nu creeaz niciun fir de execuie, crearea lor trebuie fcut explicit. Utilizarea firelor de execuie n aplicaia de fa se face pentru mbuntirea timpului de lucru prin mprirea task-urilor care

implic lucrul cu baza de date. Astfel, clasa care stabilete conexiunea cu baza de date

gestionat de SQL Server se numete ConectareServerBD. Clasa care implementeaz interfaa Runnable este clasa InterogareBaz i fiecare instan a sa va executa n metoda run() o anumit operaie asupra bazei de date, fie SELECT, UPDATE, sau DELETE. Aadar, aceste operaii se realizeaz n fire de execuie separate fa de firul

principal (engl. main thread). n programarea concurenial rezultatele pot fi uneori

imprevizibile n cazul n care nu se implementeaz o metod de sincronizare. Atunci cnd este nevoie ca firul principal s culeag

21

rezultatele obinute de un alt fir de execuie, se atept terminarea execuiei firului respectiv prin metoda join(). Crearea unui obiect InterogareBaz se face folosind un

constructor cu parametri care specific apelul metodei propriu-zise ce se va executa concurenial, i sintaxa interogrii care se trimite ctre SGBD:
[..] public Thread fir; //pentru interogari simple public InterogareBaza(String comanda, String sql) { this.comanda = comanda; //metoda care se va apela this.sql = sql; //interogarea care se trimite this.fir = new Thread(this); this.fir.start(); //se porneste firul } //pentru apelul procedurii stocate cu 4 parametri public InterogareBaza(String comanda, String sql, String p1, int p2, int p3, int p4) { this.comanda = comanda; this.sql = sql; this.p1 = p1; this.p2=p2; this.p3=p3; this.p4=p4; this.fir = new Thread(this); this.fir.start(); //se porneste firul } [..]

Codul metodei run() se poate analiza mai jos:


[..] public void run() { if (this.comanda.equals("adauga")) rezultat = adauga(this.sql); else if (this.comanda.equals("modifica")) rezultat = modifica(this.sql); else if (this.comanda.equals("stergere")) rezultat = stergere(this.sql); else if (this.comanda.equals("adauga_reteta")) adauga_reteta(this.sql,this.p1,this.p2,this.p3,this.p4); else if (this.comanda.equals("creeazaModel")) vector_rezultat = creeazaModel(this.sql); else if (this.comanda.equals("citire")) vector_rezultat2 = citire(this.sql); System.out.println("Firul a terminat!"); } [..]

22

Metodele apelate se vor vizualiza n capitolul final, Anexe. Acestea realizeaz, dup stabilirea conexiunii cu baza de date i crearea unui obiect Statement sau CallableStatement, trimiterea

interogrii i culegerea rezultatelor, atunci cnd este cazul. Firele de execuie vor mpri aceeai conexiune.

3 ARHITECTURA SISTEMULUI

n lucrarea de fa se prezint o aplicaie desktop multithreading care folosete o baz de date medical stocat pe server-ul SQL Server. Arhitectura impus sistemului este o arhitectur pe un singur nivel, acest lucru semnificnd c att aplicaia-client, care emite cereri, ct i serverul de baze de date care gestioneaz baza de date i vehiculeaz computer. n timp ce SQL Server a fost proiectat s lucreze n mod eficient ca i server, poate fi folosit i n aplicaii ce au nevoie de baze de date stand-alone, stocate local cu aplicaia-client. Conectarea la baze de date SQL Server locale se face n mod asemntor cazului n care s-ar 23 date nspre/dinspre client, sunt stocate pe acelai

conecta prin intermediul reelei la un SGBD ce ruleaz pe un server la distan. Figura urmtoare reprezint schematic modul n care lucreaz aplicaia:

4 DESCRIEREA APLICAIEI

4.1

Structura bazei de date

Aplicaia are n spate o baz de date numit medicina_familie i stocat, aa cum am menionat, pe serverul de baze de date SQL Server 2005. Un SGBD de tip SQL Server acioneaz drept parte de server a unei configuraii de reea de tip client/server: stocheaz baze de date i rspunde la solicitrile SQL efectuate de mai muli clieni. Tabelul este obiectul bazei de date care stocheaz datele despre un anumit tip de entitate (clasa de obiecte). Modelul relaional

furnizeaz mecanismul numit cheie extern pentru a face posibil asocierea a dou tabele.

24

Diagrama celor douzeci i trei de tabele de mai jos afieaz i legturile dintre acestea:

25

26

Prezentm

continuare

cele

mai

importante

tabele

ale

utilizatorului din structura bazei de date: tabela tblUnitateMedical memoreaz datele despre unitatea

sanitar. Coloanele sale sunt:

Id_unitate (cheie primar) - cu proprietatea Identity(1); Denumire_unitate cmp de tip varchar(50) ce reprezint

denumirea unitii medicale; CUI cmp de tip numeric reprezentnd codul unic de

nregistrare a unitii; Nr_registru_comer Reprezentant_legal reprezentantului legal; cmp pentru numele i prenumele

Jude, Localitate i Adres - cmpuri pentru adresa unitii, ultimul acceptnd i NULL-uri.

tabela tblAngajai conine datele despre angajaii unei uniti sanitare fie medici, fie personal asistent - memorate n urmtoarele coloane:

Id_angajat (cheia primar) cu proprietatea Identity(1); Nume_prenume cmp varchar pentru numele i prenumele angajatului unitaii; CNP cmp de tip varchar(13) pentru codul numeric personal al angjatului; Medic cmp de tip bit ce codific faptul c angajatul este medic (1), sau nu (0); am ales acest tip de date deoarece SGBDul SQL Server 2005 nu dispune de tip Boolean;

Paraf reprezint cmpul de tip varchat(15) pentru parafa unui medic; poate accepta i NULL-uri pentru cazul n care

27

cmpul anterior este 0; este o cheie UNIQUE pentru c parafa unui medic este unic;

Id_unitate este cheia extern peste cheia primar Id_unitate din tabela tblUnitateMedical; astfel, se face legtura ntre un angajat i unitatea medical la care lucreaz, legatur de tip 1:1;

Valid_de_la

cmp

ce

memoreaz

date

de

tip

datetime,

reprezentnd data de start a contractului de munc a unui angajat;

Utilizator i Parol cmpuri de tip varchar(20) memornd datele contului de utilizator ce permit logarea la aplicaia de fa; permit i NULL-uri, n ideea c ulterior dup nregistrarea n baza se pot actualiza aceste date printr-o instruciune Update;

tabela tblContracte, respectiv tblConvenii conin datele despre contractele, respectiv conveniile ncheiate cu CJAS. Pentru prima tabela, coloanele din structura sa sunt:

Nr_contract (cheia primar) reprezint numrul contractului ncheiat; exist o constrngere pentru acest cmp de tip int: valoarea Default s fie 200;

Casa_de_asigurri cmp de tip char(10), reprezint codul pentru CJAS de care aparine unitatea; Data_contract, Valabil_de_la ,Valabil_pana_la -cmpuri

datetime ce rein: data ncheierii, data de nceput i data de sfrit a contractului. Analog pentru tabela tblConvenii avnd cheia primar numrul conveniei memorat n campul Nr_convenie. tabela tblUnitateContractConvenii este tabela n care se fac

legturile dintre o unitate medical,

i contractele i conveniile

stocate n cele dou tabele prezentate anterior. O unitate medical se poate s fii ncheiat mai multe contracte i convenii, iar acestea nu pot aparine i unei alte uniti, deci este vorba de o legatur 1:M. n structura tabelei intr urmtoarele coloane:

28

Id (cheia primar) cmp cu proprietatea Identity(1); Id_unitate cheia extern peste cheia primar a tabelei

tblUnitateMedical; Nr_contract tblContracte; Nr_convenie cheia extern peste cheia primar a tabelei tblConvenii; tabela tblPacieni este tabela cu datele despre pacienii nscrii la medici de familie. Fiecare nregistrare are: cheia extern peste cheia primar a tabelei

Id_pacient (cheia primar) cmp de tip int cu proprietatea Identity(1); CNP cmp de tip varchar(13), NOT NULL, ce reine codul numeric personal al pacientului. Deoarece n realitate CNP-ul unei persoane este unic, am declarat o cheie UNIQUE peste aceast coloan. n general, cheia UNIQUE creeaz un index non-clustered peste coloana peste care este definit.

Nume

Prenume

cmpuri

varchar(50)

pentru

numele

prenumele pacientului; Sex este un cmp calculat n funcie de cmpul CNP, urmtoarea formul: (case substring([CNP],(1),(1)) when cu '1'

then 'M' when '5' then 'M' else 'F' end); pentru c acest cmp s nu fie recalculat de fiecare dat cnd este cerut, ci va fi stocat fizic, am ales proprietatea Is persisted;

Data_naterii de asemenea este un cmp calculat n funcie tot de CNP cu formula: (CONVERT([datetime],(((substring([CNP],(6),(2))+'/') +substring([CNP],(4),(2)))+'/')+substring([CNP],(2),(2)),(3)));

Data_intrarii este cmpul de tip datetime pentru data la care s-a nscris pacientul pe lista unui medic, identificat n acest tabel prin paraf;

Data_ieirii reprezint data de ieire a pacientul de pe lista unui medic; poate fi i NULL-a;

29

Cod_categorie

cmp

int,

cheie

externa

peste

tabela

tblCategorii, destinat pentru a reine categoria din care face parte pacientul;

Motiv_intrare cmp varchar(20) pentru a memora motivul de intrare. Valoarea DEFAULT este Existent, iar n cazul n care se adaug noi pacieni pe lista medicului motivul este n

urmtoarea lista: Asigurat nou, Transfer la medic. Acest lucru se face pentru a putea deosebi pacienii deja existeni n baza ntr-o anumit luna, i cei noi intrai n respectiva luna;

Motiv_ieire

cmp

varchar(20)

ce

poate

lua

valori

din

urmatoarea list: Deces, Transfer de la medic. Jude, Localitate, Adres cmpuri pentru memorarea datelor despre domiciliul pacientului; doar ultimul permite i NULLuri;

Asigurat cmp calculat astfel: (case [Cod_categorie] when (21) then 'NU' else 'DA' end) , deoarece codul 21 din tabela tblCategorii este pentru neasigurai;

Valid cmp de tip bit ce codific faptul c un pacient este deja existent sau este nou intrat pe lista medicului valoarea 1, i faptul c a fost scos de pe lista medicului valoarea 0. Dup ce un pacient a fost nevalidat (0) nu i vor mai putea aduga servicii sau documente medicale. El va rmne totui memorat n baza pentru a putea aprea la raportare n seciunea

pacienilor ieii, iar datele deja introduse acestuia nu se vor terge;

Paraf cheia extern peste cheia primar Id_angajat din tabela tblAngajai, face astfel legtura ntre un pacient i medicul su de familie;

Id_act cheia extern peste tabela tblActJustificator cu datele despre actul justificator pentru categoria de pacient; poate fi NULL deoarece calitatea de neasigurat nu necesit datele unui asemenea act.

30

tblCategorie

este

tabela

ce

conine

codurile

denumirile

categoriilor de pacieni: coduri de asigurat i codul de neasigurat. n tabela tblCategoriiServicii sunt stocate codurile i denumirile categoriile de servicii care fac parte din pachetele de servicii

memorate n tabela anterioar. Conine coloanele:

Id_cat_serviciu (cheia primar) cmp de tip int cu valoarea DEFAULT (10); Denumire_cat_serviciu cmp varchar(MAX) pentru memorarea descrierii categoriei de serviciu; Cod_pachet cheie extern peste cheia primar a tabelei

tblPachetServicii, pentru a face legatura ntre categoria de servicii i pachetul din care face parte;

Punctaj cmp de tip numeric(5,2) ce reine punctajul pentru o categorie de servicii.

tblSubserviciu este tabela care conine id-urile i denumirile

pentru fiecare serviciu care face parte dintr-o anumit categorie de servicii stocat n tabela anterioara. Cuprinde coloanele:

Id_subserviciu (cheia primar) memozeaz id-ul serviciului; Denumire cmp varchar(max) pentru descrierea serviciului; Id_cat_serviciu cheia extern peste cheia primar

Id_cat_serviciu din tabela anterioar, fcndu-se astfel legtura de 1:1 ntre un serviciu i categoria din care face parte. tabela tblServiciiPacient conine nregistrrile serviciilor oferite

pacienilor. Pentru serviciile de urgen, codurile i denumirile lor se gsesc memorate n tabela tblDiagnosticeServiciiUrgen. Revenind la tabela cu servicii, aceasta cuprinde urmtoarele coloane:

Id_serviciu_pacient (cheia primar) Id_pacient cheia extern peste cheia primar a tabelei

tblPacieni; dei cheia extern accept i NULL-uri, n cazul de fa nu ar putea fi NULL, specificarea pacientului care a

beneficiat e un serviciu este obligatorie;

31

Data_efecturii cmp datetime specificnd data la care s-a efectuat serviciul; Id_subserviciu cheia extern peste cheia primar a tabelei tblSubserviciu; Nr_registru cmp de tip int pentru numrul din registrul de consultaii; Cod_diagnostic cheie extern peste cheia primar a tabelei cu diagnostice pentru situaiile de urgen; poate fi i NULL, n cazul serviciilor de alt tip dect cele de urgen.

tabela tblMedicament stocheaz datele despre medicamentele ce se pot prescrie pe o reet. Structural, este format din urmtoarele coloane:

Id_medicament Identity(1);

(cheia

primara)

cmp

cu

proprietatea

Cod_medicament cmp varchar(20) peste care s-a definit o cheie UNIQUE i care stocheaz codul medicamentului; Denumire_medicament cmp varchar(50) memornd denumirea medicamentului; Lista_componente, Forma_farmaceutic, Substan_activ, Concentraie i Procent_compensat, Pre_maxim cmpuri

pentru stocarea altor date relevante legate de un medicament. tabela tblReetPacient conine nregistrrile despre reetele

prescrise pacienilor. Coloanele tabelei sunt urmtoarele:

Serie_reet i Nr_reet formeaz cheia primar compus a tabelei; primul cmp este de tip varchar(10) i reine seria reetei, iar cel de-al doilea este de tip numeric(10,0) i

stocheaz numrul reetei;

Id_pacient tblPacieni;

cheia

extern

peste

cheia

primar

tabelei

Data_nregistrare cmp datetime pentru data la care s-a eliberat reeta;

32

Nr_registru

cmp

int

pentru

numrul

din

registrul

de

consultaii la care exist nregistrarea reetei; Tip_reet cmp varchar(50) ce ia valori n urmtoarea list: Reet unic, Reet stupefiante; Diagnostic cmpul opional pentru memorarea diagnosticelor, observaiilor etc. tabela tblReet este tabela reetelor mpreun cu medicamentele prescrise pe acestea. Deoarece un medicament se poate regsi pe mai multe reete i o reet poate avea mai multe medicamente, legtura dintre tabele tblMedicament i tblRetetaPacient este de M:M. Acest lucru se realizeaz prin introducerea tabelei n cauz, ce conine coloanele:

Id_reet (cheia primar) cmp int cu proprietatea Identity(1); Serie_reet i Nr_reet cheia extern compus peste cheia primar compus a tabelei tblReetPacient; Id_medicament cheia extern peste cheia primar a tabelei tblMedicament; Cantitate cantitatea prescris pentru un medicament.

tabela tblBiletTrimitere conine nregistrrile despre biletele de trimitere eliberate pentru pacieni. Codurile de diagnostic prezumtiv se gsesc n tabela specialitatea ctre tblDiagnosticPrezumtivBilete, iar cele pentru care se face trimiterea se gsesc n tabela

tblSpecialitiBilete. Coloanele tabelei sunt aadar:

Serie_bilet si Nr_bilet cheia primar compus format din seria i numrul biletului; Id_pacient cheia extern peste cheia primar a tabelei cu pacieni, tblPacieni; Data_eliberrii cmp datetime pentru data la care s-a eliberat biletul de trimitere;

33

Tip_investigaie

cmp

varchar(50)

pentru

tipul

biletului:

pentru specialist i n vederea internrii (investigaie clinic), sau de laborator;

Cod_diagnostic_prezumtiv cheie extern peste cheia primar a tabelei tblDiagnisticPrezumtivBilete, pentru codul de diagnostic ipotetic trimitere; al pacientului pentru care s-a eliberat biletul de

Cod_specialitate tblSpecialitiBilete,

cheie memornd

extern de exemplu

peste codul

tabela pentru

specialitatea laboratorului (analize medicale, imagistic);

Nr_registru cmpul int pentru numrul de registru; Observaii cmpul varchar(MAX) pentru observaiile

medicului sau alte diagnostice secundare; tabela tblCertificateMedicale stocheaz datele despre certificatele eliberate pacienilor. Codurile de indemnizaie pentru

medicale

certificate sunt stocate n tabela tblIndemnizaii, cele pentru bolile infecto-contagioase (atunci cnd este iar cazul) cele se gsesc situaiile n de

tblBoliInfectoContagioaseCertificate,

pentru

urgen n tabela tblServiciiUrgen. Revenind la tabela cu certificate medicale, coloanele acesteia sunt:

Serie_certificat

Nr_certificat

cheia

primar

compus

reprezentnd seria i numrul certificatului medical; Id_pacient cheia extern peste cheia primar a tabelei cu pacieni, reprezentnd id-ul pacientului pentru care s-a acordat certificatul medical;

Cod_indemnizaie cheia extern peste cheia primara a tabelei cu indemnizaii, reprezentnd codul de indemnizaie trecut pe certificat;

Cod_urgen cheia extern peste cheia primar a tabelei tblDiagnosticServiciiUrgen; n cazul n care codul de

indemnizaie nu se refer la urgene medico-chirurgicale, acest

34

cmp poate fi NULL, n caz contrar va trebui completat cu un cod din tabela la care face referire.

Cod_boal_contagioas cheia extern peste cheia primara a tabelei care memoreaz codurile de boli din categoria bolilor infecto-contagioase;

Tip_diagnostic cmp varchar(50) pentru tipul de diagnostic: acut,cronic sau subacut; Cod_diagnostic cheie extern peste cheia primar a tabelei cu coduri de diagnostic prezumtiv; Tip_certificat cmp de tip bit prin care se codific faptul c certificatul este unul inial, prin valoarea 1, i c este n continuarea altui certificat existent n baza de date, prin

valoarea 0. n ultimul caz, este normal s se completeze seria i numrul certificatului iniial;

Serie_certif_anterior si Nr_certif_anterior pentru seria i numrul certifcatului iniial, atunci cnd este vorba de un certificat medical n continuare;

Data_acordrii, Valabil_de_la i Valabil_pn_la cmpuri de tip datetime pentru a memora data la care s-a acordat

certificatul medical, data de nceput i data de sfrit;

Nr_registru cmp de tip int pentru numrul de registru; Nr_zile cmp calculat pentru stocarea numrului de zile de concediu, urmtoarea: +(1))). Pe lng tabele, baza de date conine vederi utilizate n special trecut pe certfificatul medical; formula este

(datediff(day,[Valabil_de_la],[Valabil_pana_la]

la crearea seturilor de date pentru realizarea celor dou rapoarte: raportul pentru medic i raportul pentru pacient. Sau uneori sunt utilizate n aplicaie pentru afiarea n tabele a informaiilor care intereseaz. O vedere este o instruciune SELECT memorat, care returneaz un tabel ce conine date obinute dintr-unul sau mai multe tabele, numite tabele componente. Aceasta se materializeaz n mod dinamic

35

sub forma unui tabel fizic atunci cnd este referit prin nume ntr- o instruciune instruciunii. Vederile ascund complexitatea datelor i simplific SQL, tabel care exist numai pe durata execuiei

instruciunile, astfel nct utilizatorii pot efectua operaii asupra vederilor mult mai uor. Cnd este actualizat un tabel de baz, modificrile se propag automat n toate vederile care fac referire la tabelul respectiv. Una din utilizrile cele mai ntalnite ale vederilor este reprezentat de ascunderea datelor prin filtrarea datelor coninute n tabelele componente. Tabelele de baz permit o vizualizare real a datelor din baza de date, dar uneori se dorete o vizualizare virtual a bazei de date, specific aplicaiei, vizualizare ce permite ascunderea unor pri din baza de date tabele ntregi sau doar coloane din tabele - care nu sunt relevante. Deoarece vederile nu stocheaz date, SGBD-urile trebuie s le execute de fiecare dat cnd se face referire la ele. Vederile

complexe, n special cele imbricate, pot nrutai ns performanele. Cteva dintre cele mai importante vederi declarate n baza noastr de date sunt:

View_BileteTrimitere care afieaz rezultatul unor compuneri de tip INNER JOIN ntre tabela cu pacieni, tabela cu biletele acordate i tabela cu diagnostice;

View_CertificateMedicale informatiilor legate de

utilizat i

pentru

regsirea medicale

pacieni

certificatele

eliberate pe numele lor;

View_arbore_servicii este apelat n aplicaie la realizarea coninutului componentei JTree care prezint categoriile de servicii dintr-un anumit pachet - vzut ca rdacina a arborelui, i serviciile din fiecare categorie existent n respectivul

pachet.

n plus, aplicaia de fa apeleaz proceduri stocate n baza de date. Procedurile stocate din SQL Server sunt similare procedurilor stocate n alte limbaje de programare, n sensul c accept parametri

36

de intrare i returneaz valori prin parametri de ieire ctre un program apelant. Tot ca asemnare, aceste obiecte conin instruciuni de programare care efectueaz operaii n baza de date i pot apela la rndul lor, alte proceduri stocate. De asemenea, returneaz ctre apelant o valoare care indic succesul sau eecul, i eventual cauza eecului. Utilizarea procedurilor stocate prezint mai multe avantaje fa de varianta programelor stocate la nivelul aplicaiilor utilizator. Una dintre acestea este programarea modular: o procedur stocat poate fi creat o singur dat i apelat de mai multe ori din mai multe aplicaii. De asemenea, aceasta prezint performan mbuntit, pentru c n cazul programelor cu volum mare de cod sau a celor executate n mod repetat, procedurile stocate sunt mai eficiente deoarece

compilarea i optimizarea lor se face o singur dat la crearea procedurii i sunt memorate ntr-o form direct executabil; se evit astfel repetarea fazelor de compilare i optimizare la fiecare apel al procedurii. n plus, utilizarea lor reduce traficul de reea: o prelucrare care presupune execuia a sute de linii de cod poate fi realizat printr-o singur linie de comand care apeleaz procedura stocat prin care este implementat acea prelucrare. Se evit astfel transmiterea prin reea a codului respectiv la fiecare executare a acelei prelucrri. n baza noastr de date exist urmtoarele proceduri: proc_adaug_reet procedura stocat cu parametri de

intrare care conine o instruciune INSERT pentru tabela tblReet; - proc_servicii_pacient procedura stocat cu un parametru de intrare (@cnp), dup execuia creia se obin serviciile introduse n baza de date pentru pacientul cu CNP-ul transmis ca parametru; - proc_reete_pacient, proc_certificate_pacient, proc_bilete_ pacient pentru vizualizarea reetelor, certificatelor, respectiv a biletelor pentru un pacient.

37

4.2

Drepturi de Utilizator

Aplicaia este una multiutilizator. Exist dou categorii de utilizatori: angajaii unitii, pe care-i numim utilizatori de nivel 1, i pacienii, vzui ca utilizatori de nivel 2. Utilizatorul administratorul cu drepturi depline asupra cu bazei de date este in

SGBD-ului

responsabil

adugarea

medicilor

sistem i actualizarea nomenclatoarelor cu diagnostice, cu categorii de pacieni, de servicii etc. Acesta este utilizatorul de nivel 0, care ns nu are cont de utilizare a aplicaiei. El ar putea spre exemplu, actualiza listele de medicamente astfel nct medicul s elibereze reete conform legislaiei n vigoare. De asemenea, poate aduga noi rapoarte sistemului, astfel nct s ofere posibilitatea medicului de a centraliza datele pe trimestre, nu doar lunar. Pentru asigurarea securitii datelor, dreptul de a accesa i utiliza aplicaia se obine dup autentificarea folosind datele de identificare: username i parol. Metodele care se apeleaz pentru tratarea evenimentelor

butoanelor de logare de pe fereastra principal, verific existena utilizatorilor n baza de date i ntoarc o valoare de tip Boolean:
[..] //autentificare pentru pacient public Boolean autentificare_pacient(String user, String parola) { String sql = "SELECT CNP FROM tblUtilizatoriPacienti where (Utilizator ='"+ user +"' and Parola = '"+ parola+"')"; InterogareBaza conectare = new InterogareBaza("citire",sql); //asteapta sa termine firul try {

38

conectare.fir.join(); } catch (InterruptedException e) {e.printStackTrace();} //retinem rezultatul v_pacient = conectare.getVectorRezultat(); return (v_pacient.isEmpty()); //daca este da, pacientul nu exista } //autentificare pentru medic public Boolean autentificare_medic(String user, String parola) { String sql = "SELECT CNP FROM tblAngajati where (Utilizator ='"+ user +"' and Parola = '"+ parola+"')"; InterogareBaza conectare = new InterogareBaza("citire", sql); try { conectare.fir.join(); } catch (InterruptedException e) {e.printStackTrace();} v_medic = conectare.getVectorRezultat(); return (v_medic.isEmpty()); }[..]

n plus, metoda pentru autentificarea pacientului va scrie, n cazul n care exist, rezultatul interogrii valoarea cmpului CNP din tabela tblPacieni ntr-un vector, valoare ce va fi trimis ca parametru ferestrei MenuPacient unde va fi folosit pentru citirea i afiarea informaiilor de un anumit tip despre respectivul pacient. n asistent, calitate de angajat de al unitii, 1 are fie medic, fie personal asupra

utilizatorul

nivel

drepturi

depline

informaiilor legate de activitatea sa medical din unitatea sanitar la care este angajat. Are rolul de a ine evidena serviciilor medicale i a documentelor medicale, putnd efectua orice fel de operaii asupra datelor la care are acces, existente n baza de date. Poate actualiza datele privind partea de administrare a unitii, spre exemplu poate nregistra n baza faptelor reale, noi contracte i convenii ncheiate cu CJAS din judeul de care aparine. Poate aduga sau terge angajai i pacieni. Odat logat, poate aduga i alte conturi de utilizator pentru un angajat existent al unitii, precum i poate i modifica propriile date de identificare. De cealalt parte, utilizatorii de nivel 2 au acces restricionat doar pentru vizualizare a informaiilor. Pacienii nu vor putea efectua schimbri n baza de date, putnd vizualiza doar datele referitoare la persoana sa date personale i servicii/documente primite-

39

nregistrate n baza de date, informaii sintetizate sub forma unei fie medicale, ce poate fi n plus, descarcat i eventual printat pe hrtie.

4.3

Interfee grafice Interfaa grafic pentru medic


afieaz un formular de logare pentru

4.3.1

Fereastr

principal

cadrul medical i unul pentru pacient, ca n imaginea de mai jos:

40

Dup autentificarea medicului se deschide urmtoarea fereastr ce conine o bar de meniu i o bar de unelte. Bara de unelte (engl. toolbar) situat sub bara de meniu reprezint o colecie de pictograme ce sunt acceleratori pentru opiunea Servicii i documente din meniul de baz. Pe bara de meniu se afl grupate urmtoarele elemente JMenu: *1. Administrare *2. Pacieni *3. Servicii i documente *4. Raportri *5. Ajutor

1. Meniul Administare
Aplicaia de fa permite medicului acces la partea de adminis-

41

trare a unitii sanitare la care este angajat. Astfel, din meniul Administrare putem accesa opiunea Unitate medical care afieaz datele despre unitatea medical la care este ncadrat medicul. Date afiate se regsesc n tabelele unitii medicale i a angajailor. Tabelul adugat pe container-ul ferestrei principale este o instan a componentei grafice JTable i are la baz un model

AbstractTableModel, clas care ofer libertate n alegerea structurii de date ce st la baza modelului. Rezultatele se pot vedea n imagine:

Detaliile unitii sunt disponibile doar pentru vizualizare. n tabelul de angajai din seciunea Detalii angajai se pot aduga, modifica sau terge angajai; exemplu de adugare (urmat de

updatarea tabelei de angajai):

42

Adugarea Salveaz.

unui

angajat

se

face din

prin partea

accesarea acestei

butonului

Tratarea

evenimentelor

componente

grafice se face n metoda actionPerformed(). O parte din codul inserat aici se poate analiza mai jos:
[..] //din panoul pt adaugare else if (e.getSource() == salveaza1) { if (! nume_prenume1.getText().isEmpty() & !cnp1.getText().isEmpty() & !de_la1.getDataString().isEmpty() ) { String sql ="INSERT INTO medicina_familie].[dbo].[tblAngajati]" + "([Nume_prenume],[CNP],[Parafa],[Medic],[Id_unitate], "+ " [Valid_de_la]) VALUES ('" + nume_prenume1.getText() + "','" + cnp1.getText() +"','"+ parafa1.getText() +"','"+ check1.isSelected() +"',"+ id_unitate_medicala +",'"+ de_la1.getDateSQL() + "')"; InterogareBaza conect = new InterogareBaza("adauga", sql); try { conect.fir.join(); } catch (InterruptedException e1) {e1.printStackTrace();} if(conect.getRezultat()==1) { Vector<Object> temp_vect = new Vector<Object>(); temp_vect.addElement(nume_prenume1.getText()); temp_vect.addElement(cnp1.getText()); temp_vect.addElement(parafa1.getText());

43

temp_vect.addElement(check1.isSelected()); temp_vect.addElement(de_la1.getDataString()); JOptionPane.showMessageDialog(null, "Salvare cu succes!","Mesaj" ,JOptionPane.INFORMATION_MESSAGE); tabela_unitate.addRow(temp_vect);//adauaga in tabela de pe panoul anterior this.dispose(); } [..]

Metoda addRow() din clasa definit pentru crearea unui panou JPanel pe care este adugat o component JTable este prezentat mai jos:
[..] public void addRow(Vector<Object> v) { int r = aModel.getRowCount(); rowNo = r+1; //creste nr de linii Object[][] temp_vector = data; data = new Object[rowNo][colNo]; //copiaza data in alt vector for (int R=0;R< rowNo-1 ;R++) for(int C=0; C<colNo;C++) data[R][C]= temp_vector[R][C]; for(int C=0; C<colNo; C++) //adauga vectorul v data[rowNo-1][C] = v.elementAt(C); //notifica toti ascultatorii ca a fost inserata o linie aModel.fireTableRowsInserted(r,r); } [..]

Opiunea Contracte i Convenii permite adugarea, modificarea i tergerea unui nou contract cu CJAS a judeului n care i

desfaoar activitatea, n baza cruia se face raportarea de servicii i a unei noi convenii, necesar pentru raportarea certificatelor medicale (concediile). Modificarea unui contract se realizeaz astfel:

44

Seciunea de cod care realizeaz apelul metodei ce va face modificare unui contract n baza de date, este prezentat mai jos:
[..] //din panoul pt modificare else if (e.getSource() == salveaza2) { //update if (clasa.equals("contract")) //pentru obiectul contract { String sql = "UPDATE [medicina_familie].[dbo].[tblContracte]"+ "SET [Nr_contract] ="+ nr2.getText()+", [Casa_de_asigurari] = '"+ casa2.getSelectedItem().toString()+"'"+ ",[Data_contract] = '" + data2.getDateSQL() +" '"+ ",[Valabil_de_la] = '" + de_la2.getDateSQL()+"'"+ ",[Valabil_pana_la] = '"+ pana_la2.getDateSQL()+"'"+ "WHERE [Nr_contract]="+ data_rand_selectat_contracte.elementAt(0); InterogareBaza conect = new InterogareBaza("modifica",sql); try { conect.fir.join(); }catch (InterruptedException e1) {e1.printStackTrace();} if (conect.rezultat==1){ Vector<Object> v = new Vector<Object>(); v.addElement(Integer.parseInt(nr2.getText())); //scriem ca int [..]

45

if (rand_selectat_contracte!=-1)//updateaza tabela din panou tabela_contracte.updateRow(rand_selectat_contracte, v); } //a aparut o eroare else JOptionPane.showMessageDialog(null, "Modificare e\u015fuat\u0103!","Eroare" ,JOptionPane.ERROR_MESSAGE); } [..]

n fiecare caz, tabela din panoul precedent cu nregistrrile existente se updateaz corespunztor. Dup selectarea unei linii din tabel, aceasta se poate modifica sau terge. tergerea unui contract se face simplu, prin selectarea liniei de ters i apoi acionarea butonului terge. Operaiile ce se pot efectua asupra tabelei de convenii i interfeele grafice prin care se permit aceste operaii, sunt

asemntoare celor prezentate anterior. Erori sau atenionri ce pot aprea sunt semnalate prin apariia ferestrelor de dialog JOptionPane cu mesaje sugestive, indicnd faptul c datele introduse nu sunt valide. De exemplu, cazul n care nu s-a selectat din tabela nicio linie pentru a fi modificat/tears, un MessageBox cere selectarea unei linii; la fel, suntem avertizai n cazurile n care operaiile de actualizare cu baza de date nu s-au ncheiat cu succes. Opiunea utilizator Utilizatori permite adugarea unui nou cont de

i parola sa, pentru

a putea utiliza aplicaia. Acest lucru

este posibil doar pentru angajaii deja existeni ai unitii medicale:

46

Funcia care realizeaz adugarea unui utilizator n sistem face de fapt o operaie de Update a nregistrrii din baza de date pentru un angajat, identificat prin CNP. Erori pot aprea n cteva cazuri: n cazul n care textul introdus n cmpul Parola difer de cel din cmpul n care trebuie retastat parola pentru confirmare, n cazul n care unul dintre

cmpuri este necompletat sau atunci cnd CNP-ul introdus nu se regsete printre CNP-urile din tabelul angajailor, i operaia nu s-a realizat. Acestea ne sunt aduse n vedere cu ajutorul ferestrelor de dialog.

2. Meniul Pacieni
Din meniul Pacieni opiunea List pacieni se poate vizualiza situaia pacienilor nscrii pe lista medicului de familie. Panoul central este o component JTabbedPane, care reprezint o stiv de componente de tip JPanel, aezate pe mai multe straturi

47

suprapuse, unul dintre ele putnd fi selectat la un moment dat, determinnd componenta coninut s devin vizibil. Astfel, panoul cu pacieni conine un panoul care conine la rndul su tabela de pacieni nscrii la medic, unul pentru tabela de pacieni noi intrai i unul pentru tabela cu cei ieii din eviden:

Tabela de pacieni stocat n baza de date memoreaz att pacienii deja existeni pe lista medicului, ct i pacieni noi intrai sau ieii. Micarea pacienilor se gsete n coninutul raportului creat pentru cadrul medical, de aceea ieirea unui pacient nu

semnific tergerea propiu-zis din baza de date, ci doar modificarea unui cmp care s indice starea actual. Accesnd tab-ul Intrai se pot aduga noi pacieni, modifica sau terge pacieni. Dac se dorete modificarea lunii pentru vizualizarea pacienilor intrai ntr-o anumit lun, este necesar accesarea

butonului de Actualizare pentru a putea vizualiza datele astfel filtrate:

48

Tot aici, pentru a aduga un nou pacient se va accesa butonul de adugare care afieaz fereastra urmtoare:

49

Categoria din care face parte pacientul se selecteaz din tabela care se deschide la apsarea butonului Toogle din dreptul cmpului etichetat Cod categorie. Astfel, codul i categoria se vor completa automat. Tabul Ieiri permite scoaterea unui pacient de pe lista

medicului. Un pacient care va iei de pe lista medicului va avea memorat n baza de date n cmpul Valid, codul 0, ceea ce nseamn c nu i se vor mai putea aduga n viitor, servicii sau documente medicale. Mai inti se va selecta pacientul dorit din tabela Selector de pacieni, apoi se vor completa restul cmpurilor:

Tabelele de pe fiecare panou permit att sortarea ct i filtrarea coloanelor:


[..] //permite sau nu filtrarea tabelei public void setFilteringEnabled(boolean enable){ this.isFilteringEnabled = enable; FilterModel fm = ((FilterModel)getModel()); if (fm != null){ fm.rebuildIndex(); }

50

JTableHeader th = getTableHeader(); if (th != null){ th.repaint(); } } //permite sau nu sortarea tabelei public void setSortEnabled(boolean enable){ this.isSortEnabled = enable; FilterModel fm = ((FilterModel)getModel()); if (fm != null){ fm.rebuildIndex(); } // must repaint as sorting images are not bound properties JTableHeader th = getTableHeader(); if (th != null){ th.repaint(); } } [..]

3. Meniul Servicii i documente medicale


n meniul Sevicii i documente, cadrul medical are urmtoarele opiuni: Servicii medicale Reete medicale Certificate medicale Bilete de trimitere

Opiunea

Servicii

medicale

permite

adugarea

de

servicii

efectuate pacienilor existeni n baza de date. De asemenea, medicul poate face modificare/tergerea unei nregistrri, selectnd o linie

din tabela afiat la acionarea butonului de vizualizare. Panoul principal afiat la alegerea opiunii este un obiect

JSplitPane, format din dou panouri: panoul pentru opiuni situat n partea stng, cuprinznd cmpuri JComboBox pentru luna i anul de raportare i butoane pentru realizarea operaiilor, i panoul din

dreapta avnd un gestionar de poziionare CardLayout care afieaz iniial un formular pentru servicii, ca n figura urmtoare:

51

Din subpanoul de opiuni pentru servicii se poate deschide fereastra Selector pacieni, din care se alege pacientul:

52

Datele pacientului ales se completeaz automat n cmpurile formularului; pentru a introduce serviciul efectuat, acesta se va

selecta din arborele ce se deschide la accesarea butonului de tip BasicArrowButton din dreptul cmpului etichetat Denumire serviciu. n funcie de calitatea pacientului - asigurat, respectiv nesigurat - arborele afieaz serviciile din pachetul de baz, respectiv pe cele din pachetul minimal:

Crearea componentei de tip JTree se face prin apelul metodei urmtoare care primete ca parametru String-ul reprezentnd numele pachetului de servicii:
[..] //creeaza arborele cu servicii protected JPanel creazaArbore(String pachet) { JPanel panou_arbore = new JPanel(new BorderLayout()); //citeste categoriile InterogareBaza conectare = new InterogareBaza ("creeazaModel","SELECT [Denumire_cat_serviciu] FROM [medicina_familie].[dbo]. [View_arbore_servicii] "+ "where Denumire_pachet = '"+ pachet + "' GROUP BY [Denumire_cat_serviciu]"); try { conectare.fir.join(); } catch (InterruptedException e) {e.printStackTrace();} Vector v_categorii = conectare.getVectorRezultat2(); DefaultMutableTreeNode root = new DefaultMutableTreeNode(pachet); DefaultMutableTreeNode child;

53

DefaultMutableTreeNode grandChild; //pt fiecare categorie citeste subserviciile for (int childIndex=0; childIndex<v_categorii.size(); childIndex++) { Vector vv_categorii = new Vector(); //v_categorii e vector de vectori vv_categorii.add(0, v_categorii.elementAt(childIndex)); String cat = vv_categorii.elementAt(0).toString(); cat = removeChar(cat,'[',']'); child = new DefaultMutableTreeNode(cat); root.add(child); InterogareBaza conectare2 = new InterogareBaza ("creeazaModel","SELECT Denumire FROM [medicina_familie].[dbo]. [View_arbore_servicii]" + "WHERE Denumire_cat_serviciu = '"+ cat +"'"); try { conectare2.fir.join(); } catch (InterruptedException e) {e.printStackTrace();} Vector v_subservicii = conectare2.getVectorRezultat2(); //=> pt fiecare subserviciu din categorie avem cate un nod for (int grandChildIndex=0; grandChildIndex<v_subservicii.size() ; grandChildIndex++) { //eliminam [ si ] grandChild = new DefaultMutableTreeNode( removeChar (v_subservicii.elementAt(grandChildIndex).toString(), '[',']' )); child.add(grandChild); } } arbore_servicii = new JTree(root); [..] MouseListener ml = new MouseAdapter() { public void mousePressed(MouseEvent e) { int selRow = arbore_servicii.getRowForLocation(e.getX(), e.getY()); TreePath selPath = arbore_servicii.getPathForLocation(e.getX(), e.getY()); if(selRow != -1) { if(e.getClickCount() == 2) { DefaultMutableTreeNode nod = (DefaultMutableTreeNode)arbore_servicii.getLastSelectedPathComponent( ); if (nod==null) return; if (nod.isLeaf()) { String inf= (String)nod.getUserObject(); camp_serviciu.setText(inf); diag.dispose(); //inchidem fereastra } } } } }; [..]

54

De asemenea, pentru serviciile de urgen din pachetul minimal este necesar s se completeze cmpul cu eticheta Denumire diagnostic, prin selectarea unei linii i accesarea butonului Selecteaz, fapt care duce la copierea ntr-un vector a datelor de pe linia respectiv, pentru afiarea n cmpuri de pe container-ul ferestrei anterioare:

Clasa denumit Selector extinde clasa EscapeDialog i conine un constructor cu doi parametri: titlul ferestrei de tip Dialog care reacioneaz la tasta ESC i determin nchiderea acesteia, i un String reprezentnd interogarea ce se trimite ctre serverul de baze de date. Astfel, crearea unui obiect din clasa Selector se face astfel:
[..] //pt diagnostic if (camp_diagnostic.isEditable()) //doar pt din pachetul minimal { Selector diag = new Selector("Selector diagnostice","SELECT * FROM tblDiagnosticServiciiUrgenta"); diag.table_categorii.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); TableColumnModel model = diag.table_categorii.getColumnModel(); model.getColumn(0).setPreferredWidth(100); model.getColumn(1).setPreferredWidth(500); if (diag.rand_selectat != -1 & !camp_pachet.getText().isEmpty()) //denumire diagnostic pe pozitia 1 in vector camp_diagnostic.setText(diag.data_rand_selectat.elementAt(1).toString ()); } } [..]

55

n final, dup completarea cmpurilor din seciunea cu detaliile serviciului medical, noul serviciu se poate salva n baza de date prin apsarea butonului Salveaz. Exemplu de adugare serviciu pentru o persoan neasigurat:

Vizualizarea nregistrrilor dintr-o anumit lun se face prin accesarea butonului Vizualizare care face vizibil un nou panou. Acest lucru permite ca butoanelor de modificare i tergere s devin accesibile. Pentru a face acest lucru posibil prin implementarea interfeei ComponentListener intercepteaz JPanel, aflat i suprascrierea produse ei pe de un a dou dintre metode de care tip de

evenimente la rndul

componenta panou al

grafic

crei

gestionar

poziionare este un obiect CardLayout:


[..] public void componentHidden(ComponentEvent e) { if ( e.getComponent().equals(panel_vizualizare)) { luna.setEnabled(false); an.setEnabled(false); butonActualizare.setEnabled(false); butonModifica.setEnabled(false); butonSterge.setEnabled(false);

56

} } public void componentShown(ComponentEvent e) { if ( e.getComponent().equals(panel_vizualizare)) { luna.setEnabled(true); an.setEnabled(true); butonActualizare.setEnabled(true); butonModifica.setEnabled(true); butonSterge.setEnabled(true); } } [..]

Panoul de vizualizare arat astfel:

Dup realizarea unei conexiuni la baza de date i trimiterea unei interogri, rezultatul pstrat n obiectul ResultSet se salveaz ntr-un vector de vectori. String-ul pentru interogarea tabelei de servicii pentru pacieni este:
String sql_servicii = "SELECT CNP],[Nume],[Prenume],[Sex], "+ "[Denumire],CONVERT(varchar(10),[Data_efectuarii],103) as "Data_efectuarii,[Denumire_pachet]"+ " FROM [medicina_familie].[dbo].[View_servicii_efectuate] ";

57

Butonul Actualizare realizeaz o nou citire din baza de date i recrearea modelul tabelei:
[..] if (ev.getSource().equals(butonActualizare)) { tabel_vizualizare.citire(sql_servicii + " where (datepart(month,Data_efectuarii)="+luna.getSelectedItem().toString() +" and datepart(year,Data_efectuarii)= "+ an.getSelectedItem().toString() +" )"); } [..]

Salvarea

serviciului

baz

se

poate

face

numai

dup

completarea tuturor cmpurilor editabile, n caz contrar ne avertizeaz o fereastra de dialog cu un mesaj sugestiv. Exemplu de modificare a unui serviciu:

Metoda care realizeaz modificarea unui serviciu identificat n tabela de servicii prin cmpul cheii primare Id_serviciu_pacient:
[..]

58

public int modifica(int id_serviciu) { String sql = "UPDATE [medicina_familie].[dbo].[tblServiciiPacient] "+ " SET [Data_efectuarii] = '"+ camp_data_ef.getDateSQL() + "' ,[Id_subserviciu] = (select Id_subserviciu from tblSubserviciu where Denumire ='"+camp_serviciu.getText().trim() +"') , [Nr_registru] = "+ camp_nr_registru.getText().trim() +" , [Cod_diagnostic] = (select Cod_diagnostic from tblDiagnosticServiciiUrgenta where Denumire_diagnostic = '"+camp_diagnostic.getText().trim()+"')"+ " WHERE Id_serviciu_pacient = "+ id_serviciu; InterogareBaza conectare = new InterogareBaza("modifica",sql); //asteapta sa termine firul try { conectare.fir.join(); } catch (InterruptedException e) {e.printStackTrace();} return conectare.getRezultat();} [..]

tergerea

se

face

prin

selectarea

unei

linii

din

tabela

de

vizualizare a serviciilor din baza de date i acionarea butonului terge. n urma operaiei se afieaz pe ecran un mesaj:

Opiunea

Reete

permite

introducerea

datelor

referitoare

la

reetele prescrise.

59

Adugarea unei noi reete se face accesnd butonul de adugare din panoul cu opiuni pentru reete, deschizndu-se astfel fereastra din care se va alege un pacient existent n baza de date. Datele acestuia se completeaz n cmpurile seciunii Detalii Pacient prin apelul metodei afiseaza_data_formular(Vector v), care se face n seciunea urmtoare de cod:
[..] if (ev.getSource().equals(butonAdauga)) { cardLayout.show(panou_formular,"unu"); //se deschide fereastra selector pacienti Selector sel_pacienti = new Selector("Selector Pacienti","SELECT * FROM View_selector_pacienti"); if (sel_pacienti.rand_selectat != -1) afiseaza_data_formular(sel_pacienti.data_rand_selectat); } [..]

Accesnd butonul de Adugare din seciunea Detalii medicaie se pot aduga medicamentele prescrise pe reeta eliberat.

60

Selectorul de medicamente prezint medicamentele memorate n baz. Dup alegerea unei linii, datele aferente se completeaz n cmpurile din umtoarea fereastr; se pot aduga oricte medicamente, i de asemenea se pot terge din tabelul afiat n seciunea Detalii medicaie. Un medicament se alege din selectorul de medicamente prin acionarea butonului Caut, iar apoi i se va completa cantitatea prescris:

Cmpurile

care

afieaz

restul

datelor

din

baza

de

date

referitoare la un medicament sunt needitabile.

Exemplu de adugare reet:

61

Panoul cu reete eliberate ntr-o anumit lun dintr-un anumit an se afieaz acionnd butonului Vizualizare. Asemenea modului de lucru prezentat n paragraful referitor la Servicii i documente

medical, dac se modific luna/anul se va aciona butonul Actualizare pentru a actualiza tabela. Datele afiate n tabela din seciunea Detalii medicaie se memoreaz acionarea n tabela din baza de n date metoda denumit tblReet. La a

butonului

Salveaz, pentru

actionPerformed() se

obiectului-asculttor urmtoarea metod:

tratarea

evenimentelor,

apeleaz

[..] public void salveaza_reteta() { String id_pacient = " (SELECT Id_pacient FROM tblPacienti WHERE CNP='" + camp_cnp.getText() + "'); "; String sql_reteta_pacient ="declare @id int; set @id = " + id_pacient +" INSERT INTO [medicina_familie].[dbo].[tblRetetaPacient] "+ "[Serie_reteta],[Nr_reteta],[Id_pacient],[Data_inregistrare], [Nr_registru],[Tip_reteta],[Diagnostic]) "+

62

" VALUES ('" +camp_serie.getText().trim()+ "',"+ camp_nr_reteta.getText().trim()+" ,@id, '" +camp_data.getDateSQL()+ "', "+camp_nr_fo.getText().trim()+ " ,'" +camp_tip_reteta.getSelectedItem().toString() +"','"+camp_diagnostic.getText().replace("\n",";")+"')"; InterogareBaza conectare = new InterogareBaza("adauga",sql_reteta_pacient); try { conectare.fir.join(); } catch (InterruptedException e) {e.printStackTrace();} if (conectare.getRezultat()==1) { //salv in tabela Reteta String sql = "{call proc_adauga_reteta(?,?,?,?)}"; for (int i = 0; i<tabela.aTable.getRowCount() ;i++) { int idmed = Integer.parseInt(tabela.aTable. getValueAt(i,0).toString()); //pe prima coloana - id, pe ultima -cant int cant = Integer.parseInt(tabela.aTable. getValueAt(i,2).toString()); InterogareBaza conect = new InterogareBaza("adauga_reteta", sql,camp_serie.getText().trim(),Integer.parseInt (camp_nr_reteta.getText().trim()),idmed, cant); try { conect.fir.join(); } catch (InterruptedException e) { e.printStackTrace();}

} [..]

Opiunea Certificate medicale permite introducerea n baza de date a concediilor acordate:

63

Dup

alegerea

pacientului,

fapt

care

duce

la

completarea

automat a cmpurilor cu datele personale stocate n baz, mai ramn de completat cmpurile referitoare la certificatul medical. Codul de indemnizaie, cel de urgen medical/boala contagioas i codul de diagnostic se completeaz prin alegerea din selectorul care se

deschide la accesarea butoanelor Toogle din dreptul lor. Seciunea de cod urmtoare aparine metodei actionPerformed():
[..] else if (ev.getSource().equals(up1)){ Selector select_indemn = new Selector("Selector indemniza\u0163ii","SELECT * FROM tblIndemnizatie"); if (select_indemn.rand_selectat!=-1) //daca s-a selectat o //linie cod_indemnizatie.setText(select_indemn.data_rand_selectat.elementAt(0 ).toString()); } else if (ev.getSource().equals(up2)){ Selector select_diag = new Selector("Selector diagnostice","SELECT * FROM tblDiagnosticPrezumtivBilete"); if (select_diag.rand_selectat != -1) cod_diag.setText(select_diag.data_rand_selectat.elementAt(0).toString ());

64

} else if (ev.getSource().equals(up3)){ Selector select_urgenta = new Selector("Selector urgen\0163\u0103","SELECT * FROM tblDiagnosticServiciiUrgenta"); if (select_urgenta.rand_selectat != -1) urgenta.setText(select_urgenta.data_rand_selectat.elementAt(0).toStri ng()); } else if (ev.getSource().equals(up4)){ Selector select_boala = new Selector("Selector boli infectocontagioase","SELECT * FROM tblBoliInfectoContagioaseCertificate"); if (select_boala.rand_selectat != -1) boala_contag.setText(select_boala.data_rand_selectat.elementAt(0).toS tring()); } [..]

naintea salvrii certificatului n baza de date, n funcie de valoarea codului de indemnizaie, vor trebui completate n plus, unul dintre cele dou cmpuri: cmpul pentru codul de urgen medicochirurgical i cel pentru boala infecto-contagioas. Un exemplu de adugare certificat medical:

65

Data de nceput a valabilitii certificatului medical trebuie s fie mai mic dect cea de sfrit, validarea fcndu-se naintea salvrii n baza de date. De asemenea, dac este un certificat medical n continuarea unuia deja existent n baza de date, acesta din urm se alege prin accesarea butonului Certif_initial:
[..] int nr = calcul_nr_zile(valabil_de_la.getDate(),valabil_pana_la.getDate()); nr_zile.setText(Integer.toString(nr)); if(!camp_cnp.getText().isEmpty() & !nr_registru.getText().isEmpty() & !cod_indemnizatie.getText().isEmpty() &cod_diag.getText().isEmpty() ) { if (nr!=0) { if (verifica_certif_initial()) salveaza_in_baza(); } else JOptionPane.showMessageDialog(null, "Data de sf\u00e2r\u015fit a certificatului nu poate fi\n mai mic\u0103 dec\u00e2t data de \u00eenceput! ","Atentie" ,JOptionPane.WARNING_MESSAGE); } [..] [..] public int calcul_nr_zile(java.util.Date de_la,java.util.Date pana_la ) { long DAY = 86400000; if (de_la.after(pana_la)) return 0; return (int) ((pana_la.getTime() - de_la.getTime()) / DAY +1 ); } [..]

Am

definit care

nou vin din

clas partea

listener

pentru

interceptarea codul de

evenimentelor

cmpului

pentru

indemnizaie, clas care implementeaz interfaa DocumentListener. Una dintre metodele suprascrise ale acestei intrefee se poate vedea mai jos:
[..] public void changedUpdate(DocumentEvent e) { if ( e.getDocument().equals(cod_indemnizatie.getDocument())) { //in tabela indemzinatiilor codul pentru urgente -> 6 if ( Integer.parseInt(cod_indemnizatie.getText().trim()) ==6) urgenta.setEditable(true);

66

else if ( Integer.parseInt(cod_indemnizatie.getText().trim()) ==5) //codul pt boli infecto-contag -> 5 boala_contag.setEditable(true); //in celelalte cazuri nu trebuie completat else { urgenta.setText(""); boala_contag.setText(""); urgenta.setEditable(false); boala_contag.setEditable(false); } } } [..]

Accesnd butonul Vizualizare se pot vizualiza, modifica sau terge nregistrri efectuate n luna i anul de raportare selectate din panoul principal.

Opiunea Bilete de trimitere permite adugarea celor dou tipuri de bilete de trimitere acordate de laborator i clinice (pentru specialist sau eventual pentru internare). Dup alegerea unui pacient existent n baza de date, se vor completa cmpurile referitoare la detaliile biletului i eventual,

cmpul cu observaii. Diagnosticul prezumtiv se alege din selectorul urmtor de diagnostice. n mod asemnator, specialitatea ctre care se face trimiterea se alege din tabela de specialiti. Exemplu de adugare bilet ctre specialist:

67

Panoul cu biletele eliberate ntr-o anumit luna i an se afieaz la accesarea butonului de vizualizare. De aici, ca n ferestrele

anterioare, se pot face operaii de modificare sau tergere asupra informaiilor din baza de date.

4. Meniul Raportri
Accesnd opiunea Formulare de raportare se va deschide

browser-ul Internet Explorer n care se ncarca raportul pentru luna i anul selectate din bara cu parametri. Iniial, aceti doi parametri iau valorile lunii i anului curent:

68

Clasa BrowserControl a fost creat pentru a deschide browser-ul conine metoda static displayURL(String url) ce folosete metoda getRuntime().exec(comand) program extern din mediul din clasa Runtime nti care se lanseaz un daca

JAVA.

Mai

determin

aplicaia ruleaz sub Windows sau o alt platform.


[..] boolean windows = isWindowsPlatform(); String cmd = null; try { if (windows){ cmd = "C:/Program Files/Internet Explorer/IEXPLORE.EXE" + " " + url; Process p = Runtime.getRuntime().exec(cmd); } [..]

5. Meniul Ajutor

69

Opiunea Despre deschide o fereastr de tip JOptionPane care afieaz un mesaj de informare cu datele dezvoltatorului aplicaiei prezentate:

4.3.2

Interfaa grafic pentru pacient

Aa cum s-a observat, la executarea aplicaiei se deschide fereastra principal ce afieaz formularul de logare att pentru medic, ct i pentru pacient. Dup autentificarea pacientului se deschide fereastra cu fia medical personal care conine informaiile nregistrate n baza de date de-a lungul timpului i grupate n: - seciunea de date personale;

seciunea servicii medicale primite; seciunea de documente medicale: reete, certificate i bilete de

trimitere, eliberate pentru acesta. De exemplu, pentru un anumit pacient fereastra afiat dup autentificare va arta ca n imagine:

70

Prin accesarea butonului Descarc fi se poate salva/deschide n cel mai utilizat format PDF, raportul realizat folosind

instrumentul Business Intelligence, raportul al crui format afieaz acelai model de fi medical:

71

Avnd acces restricionat, utilizatorul pacient nu poate efectua operaii de actualizare a bazei de date, el i poate doar vizualiza informaiile legate de propria sa persoan.

4.4

Operaii efectuate asupra bazei de date 4.4.1 Conectarea la baza de date

Prin intermediul interfeelor grafice, utilizatorul acceseaz baza de date pentru a regsi sau a actualiza date. Conectarea la baza de date n modul de lucru standard. Mai nti se declar obiectele JDBC:
[..] static String driver = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; static String connectionUrl = "jdbc:sqlserver://localhost:1433;databaseName= medicina_familie; integratedSecurity=true;"; static Connection con = null; static Statement stmt = null; static CallableStatement cs = null; [..]

Baza de date nu necesit autentificare cu un username i parol, de aceea se folosete o form fr parametri a metodei statice

getConnection(). Modul de autentificare este Windows Authentication, cunoscut ca i Trusted Connection sau Integrated Security, care

utilizeaz contul utilizatorului Microsoft Windows pentru a se conecta la sursa de date. Urmeaz nregistrarea driverului JDBC folosind gestionarul de drivere DriverManager, crearea conexiunii i a unui obiect Statement pentru execuia unei instruciuni SQL:
[..] try {

72

Class.forName(driver); } catch (ClassNotFoundException e) { e.printStackTrace(); System.out.println("Eroare incarcare driver!\n" + e); } try { con = DriverManager.getConnection(connectionUrl); ConectareServerBD.stmt = con.createStatement(); System.out.println("Server pornit..."); } catch (SQLException e) {e.printStackTrace();} [..]

nchiderea obiectelor folosite se face astfel:


[..] { try { //se inchide baza de date; System.out.println("Se inchide conexiunea la baza de date."); if (stmt != null) stmt.close(); if (cs != null) cs.close(); if (con != null) con.close(); } catch (SQLException e) {e.printStackTrace();} } [..]

API-ul

JDBC

specific

trei

interfee

pentru

trimiterea

de

interogri ctre baza de date, fiecreia corespunzndu-i o metod proprie n clasa Connection: - Statement i metoda sa de creare, createStatement() se folosesc pentru trimiterea de instruciuni SQL simple, neparametrizate; PreparedStatement i metoda sa, prepareStatement() permit

folosirea de instruciuni SQL precompilate i a parametrilor de intrare n interogri; - CallableStatement i metoda sa, prepareCall() permit folosirea procedurilor stocate pe serverul SGBD. Aa cum este recomandat, dup ce datele au fost procesate, se nchide conexiunea ctre baza de date folosind metoda close(). n plus, nainte de a se inchide conexiunea trebuie nchise i obiectele Statement sau CallableStatement i ResultSet folosind metodele lor close().

73

4.4.2

Operaii

de

m a n i pu l a r e

datelor:

SELECT, INSERT, UPDATE, DELETE


SQL Server 2005 folosete un dialect SQL denumit TransactSQL sau T-SQL. Transact-SQL (T-SQL) este o extensie a standardului deschis SQL, definit i administrat de Institutul American pentru Standarde Naionale (ANSI) i adoptat de Organizaia Internaional pentru Standardizare (ISO) SQL este limbajul de programare standard pentru crearea, modificarea, tergerea i regsirea informaiilor

stocate n bazele de date prin intermediul sistemelor de gestionare a bazelor de date (SGBD). Comenzile T-SQL se mpart n dou mari categorii: limbajul de manipulare a datelor (DML data manipulation

language): acest tip de instruciuni regsesc, calculeaz, insereaz, editeaz i terg datele stocate ntro baza de date (SELECT,

INSERT, UPDATE si DELETE); - limbajul de definire a datelor (DDL data definition language): acest tip de instruciuni creeaz, modific i distrug obiectele din baza de date, cum ar fi tabele, indeci i vederi (CREATE, ALTER si DROP); Ne vom referi n urmtoarele pagini la operaiile care se fac din interiorul aplicaiei asupra bazei de date. Instruciunea SELECT

Unui obiect Statement i se pot aplica urmtoarele metode: executeQuery(), executeUpdate() sau execute(). Prima este folosit n cazul interogrilor care returneaz

mulimi-rezultat, instane ale clasei ResultSet, aa cum face clasica instruciune SELECT. De exemplu, un pacient cruia urmeaz s i se adauge un serviciu se selecteaz din tabela al crei header i ale crei linii se completeaz cu valorile vectorilor de date rezultate n urma execuiei instruciunii urmtoare:

74

String sql_servicii = "SELECT "+ " [CNP],[Nume],[Prenume],[Sex],[Denumire], " + "CONVERT(varchar(10),[Data_efectuarii],103) as "+ "Data_efectuarii,[Denumire_pachet]"+ "FROM [medicina_familie].[dbo].[View_servicii_efectuate]";

String-ul este trimis ca parametru unei metode care ncearc s culeag rezultatele:
[..] try{ rs = stmt.executeQuery(SQL); meta = rs.getMetaData(); colNo = meta.getColumnCount(); // nr de coloane ale tabelei while (rs.next()) //parcurge inregistrarile { v = new Vector(colNo); for(int i=0; i<colNo; i++) //proceseaza rezultatele v.addElement(rs.getObject(i+1)); } } catch [..]

Instruciunea INSERT Cea de-a doua metod, executeUpdate() este folosit pentru pentru operaiile de actualizare sau de tergere, cum sunt INSERT, UPDATE sau DELETE, ntorcnd un numr ntreg ce reprezint

numrul nregistrrii afectate. Pentru instruciunile care nu returneaz nimic, rezultatul ntors este 0. Ca exemplu de instruciunie INSERT am ales procedura stocat

pe SGBD i denumit proc_adauga_reteta, care realizeaz o astfel de operaie. Cei patru parametri vor lua valori prin intermediul

parametrilor funciei care apeleaz procedura. Sintaxa instruciunii este urmtoarea :


INSERT INTO [medicina_familie].[dbo].[tblReteta] ([Serie_reteta],[Nr_reteta],[Id_medicament],[Cantitate]) VALUES (@serie , @nr, @id_med, @cant)

JDBC permite apelul procedurilor stocate n baza de date, din aplicaia JAVA; primul pas este crearea unui obiect

75

CallableStatement.

Ca

cazul

obiectelor

Statement

PreparedStatement, aceasta se face folosind o conexiune deschis la baza de date. n cazul n care o procedur a stocat conine o

interogare,

metoda

folosit

pentru

executa

acest

obiect

CallableStatement este executeQuery(), pentru ca acesta va ntoarce un obiect ResultSet. n cazul n care procedura ar conine o

instruciune de INSERT sau una din clasa DDL , metoda care ar trebui utilizat ar fi executeUpdate(). De asemenea, procedurile stocate pot conine mai mult de o instruciune SQL i vor produce mai mult de un set de rezultate, mai mult de un singur update sau o combinaie ntre cele doua, ceea ce implic folosirea metodei execute(). Clasa CallableStatement este o subclas a clasei

PreparedStatement, aadar un obiect CallableStatement poate primi ca i un obiect PreparedStatement, parametri de intrare - ce nu sunt modificai de procedura (engl. input parameters); n plus, poate avea parametri de ieire (engl. Output parameters) - care conin valori returnate de procedur sau parametri de intrare/ieire (engl.

Input/output parameters). Prezentm n continuare modul de construcie a unei astfel de instruciuni pentru cazul aparte n care s-a dorit inserarea de noi nregistrri n tabela tblReteta, n care se memoreaz reetele i medicamentele trecute pe acestea. String-ul urmtor este trimis ca parametru unei funcii care ncearc execuia procedurii stocate menionate:
String SQL = "{call proc_adauga_reteta(?,?,?,?)}";

Prin construcie, obiectul de tip CallableStatement primete ca intrare o instruciune SQL. Pentru a da valori variabilelor procedurii stocate folosim metoda setX():

cs = con.prepareCall(SQL); cs.setString(1, p1); cs.setInt(2, p2); cs.setInt(3, p3); cs.setInt(4, p4);

76

cs.execute();

Am ales aceast manier de interogare datorit faptului c este mai rapid dect folosirea clasei Statement n cazul n care se dorete execuia repetat a unei instruciuni SQL, aa cum s-a urmrit pentru adugarea medicamentelor pentru o reet. Instruciunea UPDATE Aadar, pentru operaii de modificare se folosete un obiect Statement returnat la execuia metodei executeUpdate() asupra unui obiect Connection. Ca exemplu de folosire a acestui tip de

instruciune DML menionm seciunea de cod pentru modificarea datelor unui angajat al unitii sanitare:
String sql ="UPDATE medicina_familie].[dbo].[tblAngajati]"+ "SET [Nume_prenume] ='"+ nume_prenume2.getText().trim()+"',"+ "[CNP] = '"+ cnp2.getText().trim()+"',"+ "[Parafa] = '" + ( parafa2.getText().trim().isEmpty()? null: parafa2.getText().trim() ) +"',"+ "[Medic] = '" + check2.isSelected()+","+ "[Valid_de_la] = '"+ de_la2.getDateSQL()+"'"+ "WHERE [CNP]='"+ data_rand_selectat.elementAt(1).toString() +"'";

Dup ce se verific dac este deschis conexiunea i avem creat un obiect Statement , n caz contrar relundu-se paii, se ncearc execuia instruciunii primite ca parametru. n funcie de valoarea returnat se afieaz un MessageBox cu mesajul corespunztor.

Instruciunea DELETE Dac se dorete tergerea unui bilet de trimitere din baza de date, obiectul String urmtor se trimite ca parametru unei metode care va realiza acest lucru:
String sql = "DELETE FROM [medicina_familie].[dbo].[tblBiletTrimitere]" +

77

" WHERE ( Serie_bilet = " + data_rand_selectat.elementAt(0) + " AND Nr_bilet = " + data_rand_selectat.elementAt(1) + " )");

n mod asemntor metodei care face modificarea, vom primi un mesaj privind succesul sau eecul operaiei de tergere.

4.4.3

Rapoarte
o

n general, n toate sistemele informatice cutam s regsim

mulime de informaii, fiind uneori crucial s extragem informaia util ntr-un mod concis, prezentabil i uor de neles. Pentru acest lucru, Business Intelligence din SSRS ofer o larg gam de soluii. Este fundamental n toate instrumentele de raportare s ofere posibilitatea de a exporta rapoartele create n alte formate de

document des folosite. SSRS 2005 suport astfel urmtoarele tipuri: XML, CVS, TIFF, PDF, Web Archive, Excel, pentru a satisface nevoile personale ale cadrelor medicale i ale pacienilor. De altfel, pentru a face rapoartele cat mai flexibile avem posibilitatea utilizrii parametrilor n raport: intrri ce primesc valori de la utilizatori, folosite n general pentru a filtra setul de date

(engl. Dataset) ce st la baza raportului. Pentru raportul destinat medicului am definit doi parametri: luna_raportare i an_raportare de tip String, statici (non-queried) cu valoare unica, iniializai cu luna, respectiv anul curent returnate de funcia predefinit DateTime.Now. n mod asemnator, pentru raportul destinat pacientului am definit parametrul de raport cu numele cnp. Accesul prin URL n SSRS exist alternativa de a a deschide un raport n Raport Manager sau de a-l integra n propria aplicaie folosind Report Viewer Control, mecanismul fiind de acces prin URL. Sintaxa este

urmtoarea:

78

http://[server]/reportserver?/[cale]/[nume_raport] Se pot aduga anumite atribute de control la URL n funcie de cerine sau preferine:

Rs:Format=PDF realizeaz exportul raportului n format PDF. Printre alte formate amintim: HTML 4.0 (HTML with Office

Web Components), EXCEL (Microsoft Excel), WORD (Microsoft Word), MHTML (Web Archive), IMAGE (TIFF), File, CSV (CSV- comma delimited), XML (XML file with report data);

Rc:Toolbar=False ascunde bara de unelte, i nclusiv bara cu parametri; Rc:Parameters=False ascunde bara cu parametri; Rc:Zoom=PageWidth potrivit la limea de pagin; &nume_parametru=valoare_parametru seteaz valoarea

valoare_parametru la parametrul nume_parametru Odat publicat pe serverul de rapoarte, raportul se poate accesa prin URL i download-a sub un anumit format de pe bara de unelte, n funcie de cerinele autoritilor ctre care se predau. De asemenea, SSRS pune da dispoziie opiunea de printare pe hrtie. Raportul pentru medic Raportul Report_servicii_lunare.rdl destinat cadrelor medicale se afla pe serverul local de rapoarte. Valorile parametrilor vizibili pe bara de parametri se pot modifica pentru a vedea rezultatele activitii medicale n decursul unei luni dintr-un anumit an. Coleciile de date ce stau la baza acestui raport folosesc sursa de date (engl. data source) medicina_familie i reunesc informaii prin metoda compunerii de tabele, sau selecii din vederi; n plus, datele sunt filtrate n funcie de luna i anul pentru care se dorete gruparea sau centralizarea datelor:

79

Primele pagini cuprind tabelele serviciilor din pachetul de baz, pentru asigurai i cel minimal, pentru neasigurai:

Urmtoarea pagin este destinat afirii informaiilor legate de micarea pacienilor - intrarea sau ieirea din evidena medicului:

80

Dup

lista

reetelor,

certificatelor

biletelor

de

trimitere

contorizate, urmeaz un centralizator de punctaje obinute pentru serviciile efectuate: Pe ultima pagin a raportului se pot analiza un Chart de tipul Pie referitor la situaiile serviciilor pe categorii de servicii, i unul de tip Column privind punctajul pentru aceste categorii:

81

Raportul n format PDF arat ca n figura urmtoare:

Prezentm n continuare cteva dintre interogrile ce stau la baza celor mai importante seturi de date pentru raport:

lista serviciilor medicale efectuate:

SELECT CNP,Nume,Prenume,

82

CONVERT(VARCHAR(10),Data_efectuarii,103) as Data_efectuarii, Denumire,Denumire_cat_serviciu,Denumire_pachet,Punctaj FROM View_ServiciiPacienti WHERE (DATEPART(month, Data_efectuarii)=@luna_raportare and DATEPART(year, Data_efectuarii)=@an_raportare)

lista punctajelor obinute pentru serviciile efectuate:

SELECT Denumire_pachet, SUM(Punctaj) AS Subtotal, Denumire_cat_serviciu FROM View_ServiciiPacienti WHERE (DATEPART(month, Data_efectuarii) = @luna_raportare) AND (DATEPART(YEAR, Data_efectuarii) = @an_raportare) GROUP BY Denumire_pachet, Denumire_cat_serviciu

Chart-ul in form de placint are la baza setul de date

Chart_categorii obinut n urma execuiei urmtoarei interogri:


SELECT Categorii, [Nr.servicii], Luna_efectuarii, Anul_efectuarii FROM View_nr_servicii WHERE (Luna_efectuarii = @luna_raportare) AND (Anul_efectuarii = @an_raportare)

Lista pacienilor noi nscrii la medic:

SELECT CNP, Nume, Prenume, CONVERT(varchar(10), Data_intrarii, 103) AS Data_intrarii, Motiv_intrare, Judet, Localitate, Asigurat FROM View_Intrati WHERE (DATEPART(month, Data_intrarii) = @luna_raportare) AND (DATEPART(year, Data_intrarii) = @an_raportare)

Raportul pentru pacient Raportul report_pacient.rdl, publicat tot pe serverul local de rapoarte, are un parametru ascuns care ia valoarea CNP-ului

pacientului pentru care se dorete vizualizarea informaiilor eseniale din baza de date. Valoarea parametrului se transmite prin URL. Coleciile de date ce stau la baza raportului sunt vizibile n figura urmtoare:

83

Fiecare set de date este obinut dintr-o operaie de SELECT asupra tabelelor sau prin intermediul vederilor existente n baza de date; fiind n principiu asemntoare seturilor descrise pentru raportul destinat medicilor, nu le vom mai detalia. Ca structur, raportul este mprit n trei seciuni: datele personale, serviciile medicale primite grupate ntr-un tabel i

documentele medicale prescise pentru acesta, separate n alte trei tabele, aa cum a fost prezentat n subcapitolul referitor la descrierea interfeei pentru pacient. Accesul prin URL este cea mai obinuit i simpl metod de acces a rapoartelor publicate pe serverul de rapoarte local. Exist ns i dezavantajul c n acest fel adresa URL face vizibil valori ale parametrilor, care uneori se doresc a fi private.

84

CONCLUZII
n ncheiere, putem spune c aplicaia prezentat se nscrie n

rndul soluiilor informatice destinate sectorului medicinei de familie, care susin procesul de trecere de la un sistem de sntate bazat exclusiv pe hrtie, la unul modern, cu suport electronic. Ofer suport n ndeplinirea responsabilitilor profesionale i administrative ale personalului medical, ncercnd s aduc

mbuntiri n procesul de urmrire a strii pacienilor. Datorit tehnologiilor folosite n dezvoltare, sistemul software poate rula pe orice platform, fiind independent de aceasta, iar serverul de Microsoft SQL este uor de ntreinut i scalabil.

Sistemului oricnd i se pot aduga noi rapoarte ce pot fi folosite n raportarea ctre alte nivele ierarhice din sistemul romnesc de

snatate. La specificarea clientului pot fi incluse diverse rapoarte, astfel sistemul se dovedete a fi uor de extins. Informatizarea medicinei constituie un pas evolutiv ctre un management performant al activitilor medicale. Pe viitor, ca noi mbuntiri aduse sistemului, acesta ar putea adopta o arhitectur multi-nivel specific aplicaiilor de reea, acest lucru aducnd un grad mai mare de flexibilitate i o mai mare accesibilitate la resursele oferite de SGBD. Astfel, sistemul ar putea fi mprit n dou pri distincte, aplicaia-client i aplicaia-server. Clientul, fie cadru medical, fie pacient, i va putea vizualiza sau actualiza date, n funcie de drepturile de utilizator, pe propriul su calculator, n timp ce serverul va aciona ca un mainframe ce

stocheaz i recupereaz date. Avnd n vedere necesitatea implementrilor de soluii software care s creasc randamentul unitilor medicale de profil, aplicaia de fa vine n sprijinul medicului de familie i a relaiei acestuia cu nivelele superioare din sectorul medical.

85

BIBLIOGRAFIE
1 . Referine cri: 1.1. 1.2. 1.3. 1.4. 1.5.

Burdescu Dumitru Dan, Ionescu Augustin Iulian, Stnescu Liana

Baze de date (curs), editura Tipografia Universitii din Craiova 2004; tefan Tnas, Cristian Olaru, tefan Andrei - Java de la 0 la

expert, ediia a 2-a Polirom 2007; Chris Fehily - SQL vizual quickstart guide, editura ALL 2004; Robin Dewson - Beginning SQL Server 2005 for Developers From

Novice to Professional; Cristian Frsinaru - Curs practic de Java;

2.

Referine Web:
2 . 1 . Microsoft SQL Server 2005:
http://www.microsoft.com

2 . 2 . Instrumente

avansate

de

Business

Intelligence

oferite

de

Microsoft:
http://www.computerworld.ro/proiecte/2005/nr.8/microsoft.pdf; http://www.computerworld.ro/proiecte/microsoft-II-2004.pdf

2 . 3 . Using SQL Server 2005 Reporting Services with SQL Server

2005 Express Edition:


http://download.microsoft.com/download/4/7/a/47a548b9-249e-484cabd7-29f31282b04d/UsingSSRSwithSQLExpress.doc

2 . 4 . JAVA, bazele de date i securitatea pe Internet:


http://revistaie.ase.ro/content/18/stanciu.pdf

2 . 5 . Simon Ho - SQL Server Reporting Services - Experience Talk


http://books.google.com/books?id=WRiDA69xNHEC&dq= expericenced+talk

2.6. Java Swing Calendar Components:


http://www.gimlisys.com/articles-jdatechooser.html

86

2.7. Enhancing the JTable with filtering and sorting:


http://www.vlsolutions.com/en/documentation/articles/jtable/index.p hp

ANEXE

ConectareBD.java
package sql; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; public class ConectareServerBD { // declaram obiectele JDBC static String driver ="com.microsoft.sqlserver.jdbc.SQLServerDriver"; static String connectionUrl ="jdbc:sqlserver://localhost:1433;" + "databaseName=medicina_familie;integratedSecurity=true ;"; public static Connection con = null; public static Statement stmt = null; public static CallableStatement cs = null; public static void close_conexiune() { try { //se inchide baza de date System.out.println("Se inchide conexiunea la baza de date."); if (stmt != null) stmt.close(); if (cs != null) cs.close(); if (con != null) con.close(); } catch (SQLException e) {e.printStackTrace();} } public static void conectareBD() { try { Class.forName(driver); //incarcare dinamic driver } catch (ClassNotFoundException e) { e.printStackTrace(); System.out.println("Eroare incarcare driver!\n" + e);

87

} try { con = DriverManager.getConnection(connectionUrl); ConectareServerBD.stmt = con.createStatement(); System.out.println("Conexiune realizata..."); } catch (SQLException e) {e.printStackTrace();} } }//sf clasei ConectareBD

InterogareBaza.java
package sql; import java.sql.*; import java.util.Vector; public class InterogareBaza implements Runnable { String comanda="",sql="",p1; int p2,p3,p4; //pentru procedura stocata cu 4 parametri //variabile pentru tabele public String[] colNames = {}; public int colNo = 0,rowNo =0; public String[] numeColoane; public Object[][] data = null; public int colNo2, rowNo2; public String[][] data_string = null; //variabile pt valori returnate de interogari int rezultat; Vector<String> vector_rezultat = new Vector<String> (); Vector<Object> vector_rezultat2 = new Vector<Object> (); //firul de executie public Thread fir; //constructori cu parametri public InterogareBaza(String comanda, String sql) { this.comanda = comanda; this.sql = sql; this.fir = new Thread(this); this.fir.start(); } public InterogareBaza(String comanda,String sql, String p1,int p2, int p3, int p4) { this.comanda = comanda;

88

this.sql = sql; this.p1 = p1; this.p2=p2; this.p3=p3; this.p4=p4; this.fir = new Thread(this); this.fir.start(); } //metoda run public void run() { if (this.comanda.equals("adauga")) rezultat = adauga(this.sql); else if (this.comanda.equals("modifica")) rezultat = modifica(this.sql); else if (this.comanda.equals("stergere")) rezultat = stergere(this.sql); else if (this.comanda.equals("adauga_reteta")) adauga_reteta(this.sql,this.p1, this.p2,this.p3,this.p4); else if (this.comanda.equals("creeazaModel")) vector_rezultat =creeazaModel(this.sql); else if (this.comanda.equals("citire")) vector_rezultat2 = citire(this.sql); else if (this.comanda.equals("citire2")) citire2(this.sql); else if (this.comanda.equals("citire3")) citire3(this.sql); //System.out.println("Firul a terminat!"); } public Vector<Object> getVectorRezultat(){ return this.vector_rezultat2; } public Vector<String> getVectorRezultat2(){ return this.vector_rezultat; } public int getRezultat(){ return this.rezultat; } private int adauga(String SQL) { int rezultat = 0; try { if (ConectareServerBD.con.isClosed()) //creeam alta conexiune { ConectareServerBD.con = DriverManager.getConnection(ConectareServerBD.connectionUrl ); ConectareServerBD.stmt = ConectareServerBD.con.createStatement(); } rezultat = ConectareServerBD.stmt.executeUpdate(SQL);

89

// Handle any errors that may have occurred. }catch (Exception e) { e.printStackTrace(); } return rezultat; } private void adauga_reteta(String SQL,String p1,int p2,int p3, int p4) { try { if (ConectareServerBD.con.isClosed()) //creeam alta conexiune { ConectareServerBD.con = DriverManager.getConnection(ConectareServerBD.connectionUrl ); ConectareServerBD.stmt = ConectareServerBD.con.createStatement(); } // Call a procedure with one IN parameter ConectareServerBD.cs = ConectareServerBD.con.prepareCall(SQL); ConectareServerBD.cs.setString(1, p1); ConectareServerBD.cs.setInt(2, p2); ConectareServerBD.cs.setInt(3, p3); ConectareServerBD.cs.setInt(4, p4); ConectareServerBD.cs.execute(); // Handle any errors that may have occurred. }catch (Exception e) { e.printStackTrace(); } private int modifica(String SQL) { int rezultat = 0; try { if (ConectareServerBD.con.isClosed()) //creeam alta conexiune { ConectareServerBD.con = DriverManager.getConnection(ConectareServerBD.connectionUrl ); // Create and execute an SQL statement ConectareServerBD.stmt = ConectareServerBD.con. createStatement(); } rezultat = ConectareServerBD.stmt.executeUpdate(SQL); // Handle any errors that may have occurred. }catch (Exception e) {e.printStackTrace();} return rezultat; } private int stergere(String SQL)

90

{ int rezultat = 0; try { if (ConectareServerBD.con.isClosed()) //creeam alta conexiune { ConectareServerBD.con = DriverManager.getConnection(ConectareServerBD.connectionUrl ); // Create and execute an SQL statement ConectareServerBD.stmt = ConectareServerBD.con.createStatement(); } rezultat = ConectareServerBD.stmt.executeUpdate(SQL); // Handle any errors that may have occurred. }catch (Exception e) {e.printStackTrace();} return rezultat; } private Vector<Object> citire(String SQL) { ResultSet rs = null; ResultSetMetaData meta = null; Vector<Object>v = new Vector<Object>(); try { if (ConectareServerBD.con.isClosed()) //creeam alta conexiune { ConectareServerBD.con = DriverManager.getConnection(ConectareServerBD.connectionUrl ); ConectareServerBD.stmt = ConectareServerBD.con.createStatement(); } rs = ConectareServerBD.stmt.executeQuery(SQL); meta = rs.getMetaData(); int colNo = meta.getColumnCount(); while (rs.next()) { v = new Vector(colNo); for(int i=0; i<colNo; i++) v.addElement(rs.getObject(i+1)); } } catch (SQLException e) {e.printStackTrace();} finally { if (rs != null) try { rs.close(); } catch(Exception e) {} } return v; } private Vector<String> creeazaModel(String SQL) { ResultSet rs = null; ResultSetMetaData meta = null;

91

Vector vv = new Vector<String>(); try { if (ConectareServerBD.con.isClosed()) //creeam alta conexiune { ConectareServerBD.con = DriverManager.getConnection(ConectareServerBD.connectionUrl ); // creeaza un SQL statement ConectareServerBD.stmt = ConectareServerBD.con.createStatement(); } rs = ConectareServerBD.stmt.executeQuery(SQL); meta = rs.getMetaData(); colNo = meta.getColumnCount(); //numele coloanelor colNames = new String[colNo]; for (int c = 0; c < colNo ; c++) colNames[c] = meta.getColumnLabel(c+1); int r =0; //returnam liniile while(rs.next()) { Vector v = new Vector(colNo); for(int i=0;i<colNo;i++) v.addElement(rs.getString(i+1)); vv.addElement(v); //vv -vector de vectori r++; } rowNo = r; } // Handle any errors that may have occurred. catch (Exception e) { e.printStackTrace(); } finally { if (rs != null) try { rs.close(); } catch(Exception e) {} } return vv; } private void citire2(String SQL) { ResultSet rs = null; ResultSetMetaData meta = null; try { if (ConectareServerBD.con.isClosed()) //creeam alta conexiune { ConectareServerBD.con = DriverManager.getConnection(ConectareServerBD.connectionUrl ); // Create and execute an SQL statement that returns some data.

92

ConectareServerBD.stmt = ConectareServerBD.con.createStatement(); } rs = ConectareServerBD.stmt.executeQuery(SQL); meta = rs.getMetaData(); colNo2 = meta.getColumnCount(); //afla nr de coloane //numele coloanelor numeColoane = new String[colNo2]; for (int c = 0; c < colNo2 ; c++) numeColoane[c] = meta.getColumnName(c+1); //returneaza liniile data = new Object[10000][colNo2]; int R=0; while(rs.next()) { for(int C=1; C<=colNo2;C++) data[R][C-1]=rs.getObject(C); R++; } rowNo2 = R; Object[][] temp_vector = data; data = new Object[rowNo2][colNo2]; for (R=0;R< rowNo2;R++) for(int C=0; C<colNo2;C++) data[R][C]=temp_vector[R][C]; // Handle any errors that may have occurred. }catch (Exception e) {e.printStackTrace();} finally { if (rs != null) try { rs.close(); } catch(Exception e) {} } } }//sf clasei InterogareBaza

Interfata.java
package interfata; import java.awt.*; import javax.swing.*; import sql.*; import meniuri.*; import java.awt.event.*; import java.util.Vector; public class Interfata extends JFrame implements ActionListener { private JLabel label_autentificare,label_medici,label_pacienti, label_user_med,label_parola_med,label_user_pac, label_parola_pac; private Image imagine1 = Toolkit.getDefaultToolkit().getImage("imagini/back.jpg"),

93

imagine2 = Toolkit.getDefaultToolkit().getImage("imagini/medic.jpg"), imagine3 = Toolkit.getDefaultToolkit().getImage("imagini/mesaj.jpg"), imagine4 = Toolkit.getDefaultToolkit().getImage("imagini/semn_med.gif" ); private private private private private private JTextField usermed; JPasswordField parolamed; JTextField userpac; JPasswordField parolapac; JButton login_medic,login_pacient; JTextArea mesaj_autentif;

Vector v_pacient = new Vector(); Vector v_medic = new Vector(); public Interfata() { super("Aplica\u0163ie medical\u0103"); // This method ensures that all pixels have been loaded before returning imagine2 = new ImageIcon("imagini/medic.jpg").getImage(); imagine1 = new ImageIcon("imagini/back.jpg").getImage(); imagine3 = new ImageIcon("imagini/mesaj.jpg").getImage();; imagine4 = new ImageIcon("imagini/semn_med.gif").getImage();; this.setContentPane(new JPanel(){ protected void paintComponent(Graphics g) { g.drawImage(imagine2,0,200,this); g.drawImage(imagine1,230,200,this); g.drawImage(imagine3,780,200,this); g.drawImage(imagine4,860,400,this); g.setColor(Color.white); g.drawRect(235, 220,535,260); g.drawLine(500,220,500,480 ); } }); this.getContentPane().setLayout(new BorderLayout()); this.setBackground(new Color(116,186,186)); JPanel pannou = new JPanel(); pannou.setLayout(null); pannou.setOpaque(false); label_autentificare = new JLabel("Autentificare"); label_autentificare.setFont(new Font("Monotype Corsiva", Font.ITALIC, 40)); label_autentificare.setForeground(new Color(117,0,117)); label_autentificare.setBounds(380,50 ,300,100);

94

label_medici = new JLabel("Pentru medici:"); label_medici.setFont(new Font("Book Antiqua", Font.BOLD, 20)); label_medici.setForeground(new Color(117,0,117)); label_medici.setBounds(260,130 ,300,100); label_pacienti = new JLabel("Pentru pacien\u0163i:"); label_pacienti.setFont(new Font("Book Antiqua", Font.BOLD, 20)); label_pacienti.setForeground(new Color(117,0,117)); label_pacienti.setBounds(540,130 ,300,100); label_user_med = new JLabel("Utilizator:"); label_user_med.setForeground(Color.white); label_user_med.setBounds(245,270 ,80,40); label_user_med.setFont(new Font("Monotype Corsiva", Font.ITALIC, 20)); label_parola_med = new JLabel("Parol\u0103:"); label_parola_med.setForeground(Color.white); label_parola_med.setBounds(270,320 ,80,40); label_parola_med.setFont(new Font("Monotype Corsiva", Font.ITALIC, 20)); label_user_pac = new JLabel("Utilizator:"); label_user_pac.setForeground(Color.white); label_user_pac.setBounds(520,270 ,80,40); label_user_pac.setFont(new Font("Monotype Corsiva", Font.ITALIC, 20)); label_parola_pac = new JLabel("Parol\u0103:"); label_parola_pac.setForeground(Color.white); label_parola_pac.setBounds(540,320 ,80,40); label_parola_pac.setFont(new Font("Monotype Corsiva", Font.ITALIC, 20)); usermed = new JTextField(); usermed.setBounds(330,280 ,160,30); parolamed = new JPasswordField(20); parolamed.setBounds(330,330 ,160,30); userpac = new JTextField(); userpac.setBounds(600,280 ,160,30); parolapac = new JPasswordField(20); parolapac.setBounds(600,330,160,30); login_medic = new JButton("Logare"); login_medic.setBounds(410, 400, 80, 30); login_pacient = new JButton("Logare"); login_pacient.setBounds(680, 400, 80, 30); mesaj_autentif = new JTextArea(); mesaj_autentif.append( "Pentru a intra \u00een cont"+"\n"+ " \u015fi a vizualiza datele " + "\n"+"personale trebuie s\u0103 v\u0103" + "\n"+"loga\u0163i folosind User-ul \u015fi " + "\n"+"Parola ob\u0163inute de la" + "\n"+"CJAS."); mesaj_autentif.setFont(new Font("Book Antiqua", Font.BOLD, 16)); mesaj_autentif.setForeground(new Color(117,0,117)); mesaj_autentif.setOpaque(false);

95

mesaj_autentif.setEditable(false); mesaj_autentif.setBounds(800,260 , 250, 300); // adauga ascultator login_medic.addActionListener(this); login_pacient.addActionListener(this); //adauga componentele pe container pannou.add(label_autentificare); pannou.add(label_medici); pannou.add(label_pacienti); pannou.add(label_user_med,JLabel.CENTER); pannou.add(label_parola_med,JLabel.CENTER); pannou.add(label_user_pac,JLabel.CENTER); pannou.add(label_parola_pac,JLabel.CENTER); pannou.add(usermed,JLabel.CENTER); pannou.add(parolamed,JLabel.CENTER); pannou.add(userpac,JLabel.CENTER); pannou.add(parolapac,JLabel.CENTER); pannou.add(login_medic,JLabel.CENTER); pannou.add(login_pacient,JLabel.CENTER); pannou.add(mesaj_autentif,JLabel.CENTER); this.getContentPane().add(pannou, BorderLayout.CENTER); this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { ConectareServerBD.close_conexiune(); System.exit(0); } }); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); setBounds(0,0,screenSize.width, screenSize.height-25); } public void actionPerformed(ActionEvent evt) { JButton btn = (JButton)evt.getSource(); if (btn == login_medic) { if (! autentificare_medic(usermed.getText(),parolamed.getText())) { MenuMedic fereastra_medic = new MenuMedic(); fereastra_medic.setVisible(true); } else JOptionPane.showMessageDialog(null, "Autentificare e\u015fuat\u0103!","Eroare" ,JOptionPane.ERROR_MESSAGE); } else if (btn == login_pacient) {

96

if (! autentificare_pacient(userpac.getText(),parolapac.getText() )) { MenuPacient fereastra_pacient = new MenuPacient(v_pacient.elementAt(0).toString()); fereastra_pacient.setVisible(true); } else JOptionPane.showMessageDialog(null, "Autentificare e\u015fuat\u0103!","Eroare" ,JOptionPane.ERROR_MESSAGE); } } public Boolean autentificare_pacient(String user, String parola) { String sql = "SELECT CNP FROM tblUtilizatoriPacienti where (Utilizator ='"+ user +"' and Parola = '"+ parola+"')"; InterogareBaza conectare = new InterogareBaza("citire",sql); try { conectare.fir.join(); } catch (InterruptedException e) {e.printStackTrace();} v_pacient = conectare.getVectorRezultat(); return (v_pacient.isEmpty()); } public Boolean autentificare_medic(String user, String parola) { String sql = "SELECT CNP FROM tblAngajati where (Utilizator ='"+ user +"' and Parola = '"+ parola+"')"; InterogareBaza conectare = new InterogareBaza("citire",sql); try { conectare.fir.join(); } catch (InterruptedException e) {e.printStackTrace();} v_medic = conectare.getVectorRezultat(); return (v_medic.isEmpty()); } public static void main(String[] args) { //ne conectam la SGBD ConectareServerBD.conectareBD(); Interfata interfata = new Interfata(); interfata.setVisible(true); } };//sf clasei Interfata

97

Servicii.java
package servicii; import java.awt.*; import java.awt.event.*; import java.util.Vector; import javax.swing.*; import javax.swing.table.TableColumnModel; import javax.swing.tree.*; import javax.swing.border.*; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import import import import import import meniuri.MenuMedic; calendar.JDateChooser; javax.swing.plaf.basic.BasicArrowButton; sql.*; tabela.TabelaSimpla; escape.*;

public class Servicii implements ActionListener,ComponentListener { private JTree arbore_servicii; private JPanel panou_optiuni, panel_vizualizare,panou_formular; private JSplitPane mainSplitPane; private JComboBox luna, an; private JButton butonActualizare, butonAdauga, butonModifica,butonSterge, butonVizualizare,butonIesire,salveaza ,renunta, salv_modif; private CardLayout cardLayout; private JTextArea camp_adresa ; private JTextField camp_parafa,camp_cnp,camp_nume, camp_prenume,camp_data ,camp_judet,camp_localitate, camp_pachet, camp_serviciu, camp_diagnostic; private JRadioButton masculin,feminin; private ButtonGroup group; private JDateChooser camp_data_ef; private NumericTextField camp_nr_registru; private BasicArrowButton up1,up2; String sql_servicii = "SELECT [CNP],[Nume],[Prenume],[Sex],[Denumire]" +",CONVERT(varchar(10),[Data_efectuarii],103) as Data_efectuarii,[Denumire_pachet]"+ " FROM [medicina_familie].[dbo]. [View_servicii_efectuate] "; static Color culoare = new Color(49,98,102); TabelaSimpla tabel_vizualizare; Vector<Object> data_rand_selectat; EscapeDialog diag; //fereastra cu arborele servicii

98

int id_serviciu =0 ; public Servicii() { mainSplitPane = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT, creeaza_panou_optiuni(), creeaza_panou_formular() ); mainSplitPane.setDividerSize(5); mainSplitPane.setOneTouchExpandable(false); mainSplitPane.setDividerLocation(200); } protected JPanel creeaza_panou_optiuni() //panou butoane si //calendare { panou_optiuni = new JPanel(new BorderLayout()); panou_optiuni.setBackground(new Color(100,186,186)); //tine subpanou1-ul si subpanou2 panou_optiuni.setBorder(BorderFactory.createCompoundBorder( new EtchedBorder(EtchedBorder.RAISED), BorderFactory.createEmptyBorder(15,15,15,15))); //partea de jos JPanel subpanou1 = new JPanel(new GridLayout(7,1,0,10)); subpanou1.setPreferredSize(new Dimension(300,350)); subpanou1.setOpaque(false); JLabel label_optiuni = new JLabel("Op\u0163iuni Servicii",JLabel.CENTER); label_optiuni.setFont(new Font("Verdana", Font.BOLD ,14 )); label_optiuni.setForeground(Color.white); butonActualizare = new JButton("Actualizare"); butonAdauga = new JButton("Adaug\u0103 serviciu"); butonModifica = new JButton("Modific\u0103"); butonSterge = new JButton("\u015eterge"); butonVizualizare = new JButton("Vizualizare"); butonIesire = new JButton("Ie\u015fire meniu Servicii"); butonActualizare.setToolTipText("Actualizarea tabelei serviciilor salvate"); butonAdauga.setToolTipText("Adaug\u0103 un serviciu"); butonModifica.setToolTipText("Modific\u0103 un serviciu salvat"); butonSterge.setToolTipText("\u015fterge un serviciu salvat"); butonVizualizare.setToolTipText("Vizualizare servicii salvate"); butonIesire.setToolTipText("Ie\u015fire din meniul Servicii"); subpanou1.add(label_optiuni); subpanou1.add(butonActualizare); subpanou1.add(butonAdauga); subpanou1.add(butonModifica); subpanou1.add(butonSterge); subpanou1.add(butonVizualizare); subpanou1.add(butonIesire);

99

//partea de sus JPanel subpanou2 = new JPanel(new GridLayout(4,1,0,10)); Border border = new TitledBorder(new EtchedBorder(5), "Perioada de raportare:", TitledBorder.ABOVE_TOP, TitledBorder.DEFAULT_POSITION, new Font("Arial",Font.BOLD,12), Color.white); subpanou2.setBorder(border); subpanou2.setOpaque(false); luna = new JComboBox(MenuMedic.luni); luna.setSelectedItem(Integer.toString(MenuMedic.month)); luna.setBounds(40,80,150,25); an = new JComboBox(MenuMedic.ani); an.setBounds(40,150,150,25); an.setSelectedItem(Integer.toString(MenuMedic.year)); JLabel l1 = new JLabel("Luna:"); JLabel l2 = new JLabel("Anul:"); subpanou2.add(l1); subpanou2.add(luna); subpanou2.add(l2); subpanou2.add(an); panou_optiuni.add(subpanou1,BorderLayout.SOUTH); panou_optiuni.add(subpanou2,BorderLayout.NORTH); butonActualizare.addActionListener(this); butonAdauga.addActionListener(this); butonModifica.addActionListener(this); butonSterge.addActionListener(this); butonVizualizare.addActionListener(this); butonIesire.addActionListener(this); return panou_optiuni; } protected JPanel creeaza_panou_formular() { cardLayout = new CardLayout(10,10); panou_formular = new JPanel(cardLayout); JPanel panou_campuri = new JPanel(); panou_campuri.setMinimumSize(new Dimension(600,400)); //panoul cu date medic JPanel panel_date1 = new JPanel(); panel_date1.setLayout(new BoxLayout(panel_date1, BoxLayout.X_AXIS)); panel_date1.setBorder(BorderFactory.createCompoundBorder (new TitledBorder (new LineBorder(culoare), "Detalii medic", TitledBorder.DEFAULT_POSITION, TitledBorder.DEFAULT_JUSTIFICATION, new Font("Comic Sans",Font.ITALIC,12),

100

culoare), new EmptyBorder(5,5,5,5))); panel_date1.setPreferredSize(new Dimension(600,80)); JPanel subpan = new JPanel();//FlowLayout() implicit subpan.setPreferredSize(new Dimension(80,80)); JLabel label_parafa = new JLabel("Paraf\u0103 medic"); camp_parafa = new JTextField(12); camp_parafa.setEditable(false); subpan.add(label_parafa); subpan.add(new JLabel()); subpan.add(camp_parafa); panel_date1.add(subpan); panel_date1.add(new JPanel()); //panou date pacient JPanel panel_date2 = new JPanel(); panel_date2.setBorder(BorderFactory.createCompoundBorder (new TitledBorder (new LineBorder(culoare), "Detalii pacient", TitledBorder.DEFAULT_POSITION, TitledBorder.DEFAULT_JUSTIFICATION, new Font("Comic Sans",Font.ITALIC,12), culoare), new EmptyBorder(5,5,5,5))); panel_date2.setPreferredSize(new Dimension(600,280)); JPanel sub_panel_date21 = new JPanel(new GridLayout(3,1,10,10)); sub_panel_date21.setPreferredSize(new Dimension(80,100)); JPanel sub_panel_date22 = new JPanel(new GridLayout(3,1,10,10)); sub_panel_date22.setPreferredSize(new Dimension(180,100)); JPanel sub_panel_date23 = new JPanel(new GridLayout(3,1,10,10)); sub_panel_date23.setPreferredSize(new Dimension(120,100)); JPanel sub_panel_date24 = new JPanel(new GridLayout(3,1,10,10)); sub_panel_date24.setPreferredSize(new Dimension(180,100)); JPanel sub_panel_date26 = new JPanel(new GridLayout(1,3,20,10)); sub_panel_date26.setPreferredSize(new Dimension(580,20)); JPanel sub_panel_date25 = new JPanel(); sub_panel_date25.setPreferredSize(new Dimension(590,60)); JLabel label_adresa = new JLabel("Adres\u0103"); label_adresa.setPreferredSize(new Dimension(80,50)); camp_adresa = new JTextArea(); camp_adresa.setRows(3); camp_adresa.setLineWrap(true); JScrollPane scroller = new JScrollPane(camp_adresa); scroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VER TICAL_SCROLLBAR_ALWAYS);

101

scroller.setPreferredSize(new Dimension(490,50)); JLabel label_cnp = new JLabel("CNP"); JLabel label_nume = new JLabel("Nume"); JLabel label_prenume = new JLabel("Prenume"); camp_cnp = new JTextField(); camp_nume = new JTextField(); camp_prenume = new JTextField(); JLabel label_data = new JLabel("Data na\u015fterii"); JLabel label_judet = new JLabel("Jude\u0163"); JLabel label_localitate = new JLabel("Localitate"); camp_data = new JTextField(); camp_judet = new JTextField(); camp_localitate = new JTextField(); sub_panel_date21.add(label_cnp); sub_panel_date21.add(label_nume); sub_panel_date21.add(label_prenume); sub_panel_date22.add(camp_cnp); sub_panel_date22.add(camp_nume); sub_panel_date22.add(camp_prenume); sub_panel_date23.add(label_data); sub_panel_date23.add(label_judet); sub_panel_date23.add(label_localitate); sub_panel_date24.add(camp_data); sub_panel_date24.add(camp_judet); sub_panel_date24.add(camp_localitate); sub_panel_date25.add(label_adresa); sub_panel_date25.add(scroller); JLabel label_sex = new JLabel("Sex"); masculin = new JRadioButton("Masculin"); feminin = new JRadioButton("Feminin"); //Group the radio buttons. group = new ButtonGroup(); group.add(masculin); group.add(feminin); sub_panel_date26.add(label_sex); sub_panel_date26.add(masculin); sub_panel_date26.add(feminin); panel_date2.add(sub_panel_date21); panel_date2.add(sub_panel_date22); panel_date2.add(sub_panel_date23); panel_date2.add(sub_panel_date24); panel_date2.add(sub_panel_date26); panel_date2.add(sub_panel_date25); //panou serviciu medical JPanel panel_date3 = new JPanel(); panel_date3.setBorder(BorderFactory.createCompoundBorder (new TitledBorder (new LineBorder(culoare), "Detalii serviciu medical", TitledBorder.DEFAULT_POSITION, TitledBorder.DEFAULT_JUSTIFICATION, new Font("Comic Sans",Font.ITALIC,12),

102

culoare), new EmptyBorder(5,5,5,5))); panel_date3.setPreferredSize(new Dimension(600,250)); JPanel sub_panel_date31 = new JPanel(); JLabel label_data_ef = new JLabel("Data efectu\u0103rii"); JLabel label_nr_registru = new JLabel("Num\u0103r registru"); camp_data_ef = new JDateChooser(); camp_nr_registru = new NumericTextField(10); sub_panel_date31.add(label_data_ef); sub_panel_date31.add(camp_data_ef); sub_panel_date31.add(new JLabel(" ")); sub_panel_date31.add(label_nr_registru); sub_panel_date31.add(camp_nr_registru); JPanel sub_panel_date32 = new JPanel(new GridLayout(3,1,10,5)); sub_panel_date32.setPreferredSize(new Dimension(120,80)); JLabel label_pachet = new JLabel("Denumire pachet"); JLabel label_serviciu = new JLabel("Denumire serviciu"); JLabel label_diagnostic = new JLabel("Denumire diagnostic"); sub_panel_date32.add(label_pachet); sub_panel_date32.add(label_serviciu); sub_panel_date32.add(label_diagnostic); GridBagLayout grid = new GridBagLayout(); JPanel sub_panel_date33 = new JPanel(grid); sub_panel_date33.setPreferredSize(new Dimension(460,100)); camp_pachet = new JTextField(40); camp_pachet.setPreferredSize(new Dimension(100,25)); camp_serviciu = new JTextField(40); camp_serviciu.setPreferredSize(new Dimension(100,25)); camp_diagnostic = new JTextField(40); camp_diagnostic.setPreferredSize(new Dimension(100,25)); up1 = new BasicArrowButton(BasicArrowButton.NORTH); up2 = new BasicArrowButton(BasicArrowButton.NORTH); up1.addActionListener(this); up2.addActionListener(this); GridBagConstraints gBC = new GridBagConstraints(); //se stabileste prima coloana gBC.gridx = 0; //se stab primu rand gBC.gridy = 0; //componenta va ocupa 3 celule gBC.gridwidth = 50; gBC.weighty = 0.1; grid.setConstraints(camp_pachet, gBC); gBC.gridx = 0; gBC.gridy = 1; gBC.gridwidth = 50; grid.setConstraints(camp_serviciu, gBC);

103

gBC.gridx =51; grid.setConstraints(up1, gBC); gBC.gridx = 0; gBC.gridy = 2; gBC.gridwidth = 50; grid.setConstraints(camp_diagnostic, gBC); gBC.gridx =51; grid.setConstraints(up2, gBC); sub_panel_date33.add(camp_pachet); sub_panel_date33.add(camp_serviciu); sub_panel_date33.add(camp_diagnostic); sub_panel_date33.add(up1); sub_panel_date33.add(up2); camp_pachet.getDocument().addDocumentListener(new DocumentListener() { public void changedUpdate(DocumentEvent e) { if (camp_pachet.getText().equals("BAZA")) camp_diagnostic.setEditable(false); } public void insertUpdate(DocumentEvent e) { changedUpdate(e); } public void removeUpdate(DocumentEvent e) { changedUpdate(e); } }); camp_serviciu.getDocument().addDocumentListener(new DocumentListener() { public void changedUpdate(DocumentEvent e) { if (camp_serviciu.getText().contains("situatii de urgenta") ) camp_diagnostic.setEditable(true); else { camp_diagnostic.setEditable(false); camp_diagnostic.setText(""); } } public void insertUpdate(DocumentEvent e) { changedUpdate(e); } public void removeUpdate(DocumentEvent e) { changedUpdate(e); } }); JPanel parte_jos = new JPanel(); parte_jos.add(sub_panel_date32);

104

parte_jos.add(sub_panel_date33); panel_date3.add(sub_panel_date31); panel_date3.add(parte_jos); //panou butoanele Salveaza si Renunta JPanel panel_date4 = new JPanel(new BorderLayout()); JPanel panel_date41 = new JPanel(); panel_date41.setPreferredSize(new Dimension(300,70)); salveaza = new JButton("Salveaz\u0103"); renunta = new JButton("Renun\u0163\u0103"); salv_modif = new JButton("Salveaz\u0103 modific\u0103ri"); salv_modif.setEnabled(false); JLabel l = new JLabel(); l.setPreferredSize(new Dimension(50,70)); panel_date41.add(salveaza); panel_date41.add(l); panel_date41.add(renunta); JPanel panel_date42 = new JPanel(); panel_date42.setLayout(null); panel_date42.setPreferredSize(new Dimension(300,0)); salv_modif.setBounds(15,30,150,25); panel_date42.add(salv_modif); panel_date4.add(panel_date41,BorderLayout.EAST); panel_date4.add(panel_date42,BorderLayout.WEST); salveaza.addActionListener(this); renunta.addActionListener(this); salv_modif.addActionListener(this); //--JPanel tot = new JPanel(); tot.setLayout(new BoxLayout(tot,BoxLayout.PAGE_AXIS)); tot.add(panel_date1); tot.add(panel_date2); tot.add(panel_date3); tot.add(panel_date4); panou_campuri.setLayout(new BorderLayout()); panou_campuri.add(tot,BorderLayout.CENTER); panel_vizualizare = new JPanel(new BorderLayout()); tabel_vizualizare = new TabelaSimpla(); panel_vizualizare.add(tabel_vizualizare, BorderLayout.CENTER); tabel_vizualizare.citire(sql_servicii + " where ( datepart(month,Data_efectuarii) = " +luna.getSelectedItem().toString() +" and datepart(year,Data_efectuarii)= "+ an.getSelectedItem().toString() +" )"); panou_formular.add(panel_vizualizare,"vizualizare"); panel_vizualizare.addComponentListener(this); panou_formular.add(panou_campuri, "unu"); cardLayout.show(panou_formular, "unu"); return panou_formular; }

105

//creeaza arborele cu servicii protected JPanel creazaArbore(String pachet) { JPanel panou_arbore = new JPanel(new BorderLayout()); //citeste categoriile InterogareBaza conectare = new InterogareBaza("creeazaModel","SELECT [Denumire_cat_serviciu] FROM [medicina_familie].[dbo].[View_arbore_servicii] "+ "where Denumire_pachet = '"+ pachet + "' GROUP BY [Denumire_cat_serviciu]"); //asteapta sa termine firul try { conectare.fir.join(); } catch (InterruptedException e) {e.printStackTrace();} Vector v_categorii = conectare.getVectorRezultat2(); DefaultMutableTreeNode root = new DefaultMutableTreeNode(pachet); DefaultMutableTreeNode child; DefaultMutableTreeNode grandChild; //pt fiecare categorie citeste subserviciile for (int childIndex=0; childIndex<v_categorii.size(); childIndex++) { Vector vv_categorii = new Vector(); //v_categorii e //vector de vectori vv_categorii.add(0, v_categorii.elementAt(childIndex)); String cat = vv_categorii.elementAt(0).toString(); cat = removeChar(cat,'[',']'); child = new DefaultMutableTreeNode(cat); root.add(child); InterogareBaza conectare2 = new InterogareBaza("creeazaModel","SELECT Denumire FROM [medicina_familie].[dbo].[View_arbore_servicii]" + "WHERE Denumire_cat_serviciu = '"+ cat +"'"); //asteapta sa termine firul try { conectare2.fir.join(); } catch (InterruptedException e) {e.printStackTrace();} Vector v_subservicii = conectare2.getVectorRezultat2(); //=> pt fiecare subserviciu din categorie avem cate un nod for (int grandChildIndex=0; grandChildIndex<v_subservicii.size() ; grandChildIndex++) {

106

grandChild = new DefaultMutableTreeNode( removeChar (v_subservicii.elementAt(grandChildIndex).toString(), '[',']' )); child.add(grandChild); } } arbore_servicii = new JTree(root); arbore_servicii.expandRow(1); // arata frunzele DefaultTreeCellRenderer con = new DefaultTreeCellRenderer(); con.setFont(new Font("Verdana",Font.ITALIC,12)); arbore_servicii.setCellRenderer(con); MouseListener ml = new MouseAdapter() { public void mousePressed(MouseEvent e) { int selRow = arbore_servicii.getRowForLocation(e.getX(), e.getY()); TreePath selPath = arbore_servicii.getPathForLocation(e.getX(), e.getY()); if(selRow != -1) { if(e.getClickCount() == 2) { DefaultMutableTreeNode nod = (DefaultMutableTreeNode)arbore_servicii.getLastSelectedPath Component(); if (nod==null) return; if (nod.isLeaf()) { String inf= (String)nod.getUserObject(); camp_serviciu.setText(inf); diag.dispose(); //inchidem fereastra } } } } }; arbore_servicii.addMouseListener(ml); //adaugam arborele pe scrollpane JScrollPane pane = new JScrollPane(arbore_servicii); panou_arbore.add(pane, BorderLayout.CENTER); return panou_arbore; } //elimina 2 caractere dintr-un String public static String removeChar(String s, char c, char c2) { String r = ""; for (int i = 0; i < s.length(); i ++) { if (s.charAt(i) != c & s.charAt(i) != c2) r += s.charAt(i); }

107

return r; } //handler evenimente de la butoane public void actionPerformed(ActionEvent ev) { if (ev.getSource().equals(butonAdauga)) { cardLayout.show(panou_formular,"unu"); salv_modif.setEnabled(false); salveaza.setEnabled(true); //se deschide fereastra selector pacienti Selector selector = new Selector("Selector Pacienti", "SELECT * FROM View_selector_pacienti"); TableColumnModel model3 = selector.table_categorii.aTable.getColumnModel(); for (int i=0;i< model3.getColumnCount();i++) model3.getColumn(i).setPreferredWidth(200); //afisam in formular (daca s-a selectat un rand) if (selector.rand_selectat != -1) afiseaza_data_in_formular(selector.data_rand_selectat); } else if (ev.getSource().equals(butonActualizare)) { tabel_vizualizare.citire(sql_servicii + " where (datepart(month,Data_efectuarii)= "+luna.getSelectedItem().toString() +" and datepart(year,Data_efectuarii)= "+ an.getSelectedItem().toString() +" )"); } else if (ev.getSource().equals(butonModifica)) { if (panel_vizualizare.isVisible()) { if ( tabel_vizualizare.aTable.getSelectedRow() != -1) { Vector data_rand = tabel_vizualizare.afiseazaData(tabel_vizualizare.aTable); //pe poz 0-cnp,4-den, intoarce id_serviciu_pacient id_serviciu = cauta_serv_modif(data_rand.elementAt(0).toString(), data_rand.elementAt(4).toString()); } else JOptionPane.showMessageDialog(null, "Selecta\u0163i o linie din tabela de vizualizare!","Mesaj" ,JOptionPane.INFORMATION_MESSAGE); } }

108

else if (ev.getSource().equals(salv_modif)) { if (id_serviciu != 0) if ( modifica(id_serviciu) ==1){ JOptionPane.showMessageDialog(null, "Modificare cu succes!","Mesaj" ,JOptionPane.INFORMATION_MESSAGE); sterge_data_formular(); } else JOptionPane.showMessageDialog(null, "Eroare la modificare...","Eroare" ,JOptionPane.ERROR_MESSAGE); } else if (ev.getSource().equals(butonSterge)) { if (panel_vizualizare.isVisible()) { if ( tabel_vizualizare.aTable.getSelectedRow() != -1) { data_rand_selectat = tabel_vizualizare.afiseazaData(tabel_vizualizare.aTable); if (sterge_serviciu()==1){ JOptionPane.showMessageDialog(null, "\u015etergere cu succes!","Mesaj" ,JOptionPane.INFORMATION_MESSAGE); tabel_vizualizare.removeRow(tabel_vizualizare.aTable.g etSelectedRow()); } else JOptionPane.showMessageDialog(null, "Eroare la \u015ftergere...","Eroare" ,JOptionPane.ERROR_MESSAGE); } else JOptionPane.showMessageDialog(null, "Selecta\u0163i o linie din tabela de vizualizare!","Mesaj" ,JOptionPane.INFORMATION_MESSAGE); } } else if (ev.getSource().equals(butonVizualizare)) { cardLayout.show(panou_formular,"vizualizare"); } //pt serviciu else if (ev.getSource().equals(up1)) { if (! camp_pachet.getText().isEmpty()) { diag = new EscapeDialog(null,"Arbore servicii",JDialog.ModalityType.APPLICATION_MODAL); diag.getContentPane().add(creazaArbore(camp_pachet.get Text()));//in functie de pachet Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); Dimension windowSize = new Dimension(650,600);

109

int windowX = Math.max(0, (screenSize.width windowSize.width ) / 2); int windowY = Math.max(0, (screenSize.height windowSize.height) / 2); diag.setSize(windowSize); diag.setLocation(windowX, windowY); diag.setVisible(true); } } //pt diagnostic else if (ev.getSource().equals(up2)) { if (camp_diagnostic.isEditable()) //doar pt din pachetul minimal { Selector diag = new Selector("Selector diagnostice","SELECT * FROM tblDiagnosticServiciiUrgenta"); if (diag.rand_selectat != -1 & ! camp_pachet.getText().isEmpty()) //denumire diagnostic pe poz 1 camp_diagnostic.setText(diag.data_rand_selectat.elementAt(1 ).toString()); } } else if (ev.getSource().equals(salveaza)) { if (!camp_nr_registru.getText().isEmpty()) { salveaza(); sterge_data_formular(); } else JOptionPane.showMessageDialog(null, "Completa\u0163i datele pacientului \u015fi detaliile serviciului! ","Aten\u0163ie" ,JOptionPane.WARNING_MESSAGE); } else if (ev.getSource().equals(renunta)) { sterge_data_formular(); } else if (ev.getSource().equals(butonIesire)) { //ultimul panou care a fost vizibil MenuMedic.afiseaza_panel_gol(MenuMedic.cards.elementAt (MenuMedic.cards.size()-2)); MenuMedic.cards.removeElementAt(MenuMedic.cards.size()-1); } } public void afiseaza_data_in_formular(Vector<Object> v)

110

{ camp_cnp.setText(v.elementAt(0).toString()); camp_cnp.setEditable(false); camp_nume.setText(v.elementAt(1).toString()); camp_nume.setEditable(false); camp_prenume.setText(v.elementAt(2).toString()); camp_prenume.setEditable(false); //selecteaza unul din cele 2 butoane radio if (v.elementAt(3).toString().equals("M")) masculin.setSelected(true); else if (v.elementAt(3).toString().equals("F")) feminin.setSelected(true); camp_data.setText(v.elementAt(4).toString()); camp_data.setEditable(false); camp_judet.setText(v.elementAt(6).toString()); camp_judet.setEditable(false); camp_localitate.setText(v.elementAt(7).toString()); camp_localitate.setEditable(false); if (v.elementAt(8) != null) //adresa in baza poate fi nula camp_adresa.setText(v.elementAt(8).toString()); camp_adresa.setEditable(false); String pachet = v.elementAt(9).toString(); camp_pachet.setText(pachet.equalsIgnoreCase("DA")? "BAZA": "MINIMAL"); camp_pachet.setEditable(false); camp_parafa.setText(v.elementAt(11).toString()); } public void sterge_data_formular() { camp_cnp.setText(""); camp_cnp.setEditable(true); camp_nume.setText(""); camp_nume.setEditable(true); camp_prenume.setText(""); camp_prenume.setEditable(true); camp_data.setText(""); camp_data.setEditable(true); camp_judet.setText(""); camp_judet.setEditable(true); camp_localitate.setText(""); camp_localitate.setEditable(true); camp_adresa.setText(""); camp_adresa.setEditable(true); camp_pachet.setText(""); camp_pachet.setEditable(true); camp_diagnostic.setText(""); camp_diagnostic.setEditable(true); camp_serviciu.setText(""); camp_serviciu.setEditable(true); camp_nr_registru.setText(""); group.clearSelection(); camp_parafa.setText(""); }

111

public void salveaza() { String id_pacient = " (SELECT Id_pacient FROM tblPacienti WHERE CNP='" + camp_cnp.getText() + "'); "; String id_subserviciu = " (SELECT Id_subserviciu FROM tblSubserviciu WHERE Denumire= '"+ camp_serviciu.getText() +"'); "; String id_diagnostic = null; if(!camp_diagnostic.getText().isEmpty()) id_diagnostic = " (SELECT Cod_diagnostic FROM tblDiagnosticServiciiUrgenta WHERE Denumire_diagnostic= '"+ camp_diagnostic.getText() +"'); "; String SQL = "declare @id_pac int; set @id_pac = " + id_pacient + "declare @id_serv int; set @id_serv = " + id_subserviciu + "declare @id_diag int; set @id_diag = " + id_diagnostic + " INSERT INTO [medicina_familie].[dbo].[tblServiciiPacient] "+ " ([Id_pacient],[Data_efectuarii],[Id_subserviciu], [Nr_registru], [Cod_diagnostic]) VALUES ( @id_pac,'" + camp_data_ef.getDateSQL() +"',@id_serv,"+ camp_nr_registru.getText() +" , @id_diag )"; InterogareBaza conectare = new InterogareBaza("adauga",SQL) try { conectare.fir.join(); } catch (InterruptedException e) {e.printStackTrace();} if (conectare.getRezultat()==1) { JOptionPane.showMessageDialog(null, "Salvare cu succes!","Mesaj" ,JOptionPane.INFORMATION_MESSAGE); Vector<Object> v_serviciu = new Vector<Object>(); v_serviciu.add(camp_cnp.getText()); v_serviciu.add(camp_nume.getText()); v_serviciu.add(camp_prenume.getText()); v_serviciu.add(masculin.isSelected()? "M": "F"); v_serviciu.add(camp_serviciu.getText()); v_serviciu.add(camp_data_ef.getDataString()); v_serviciu.add(camp_pachet.getText()); //afiseaza in tabel vizualizare tabel_vizualizare.addRow(v_serviciu); } else JOptionPane.showMessageDialog(null, "Eroare la salvarea \u00een baza de date...","Eroare" ,JOptionPane.ERROR_MESSAGE); } public int cauta_serv_modif(String cnp, String den) {

112

String sql1 = " SELECT tblAngajati.Parafa, tblPacienti.CNP, tblPacienti.Nume, tblPacienti.Prenume, "+ " tblPacienti.Sex, convert(varchar(10),tblPacienti.Data_nasterii,103) as Data_nasterii, tblPacienti.Judet, "+ " tblPacienti.Localitate, tblPacienti.Adresa, "+ "convert(varchar(10),tblServiciiPacient.Data_efectuarii,103 ) as Data_efectuarii, tblServiciiPacient.Nr_registru, "+ " tblPachetServicii.Denumire_pachet,"+ " tblSubserviciu.Denumire, "+ " ( case tblServiciiPacient.Cod_diagnostic when NULL then '' else " (SELECT Denumire_diagnostic FROM tblDiagnosticServiciiUrgenta where " Cod_diagnostic=tblServiciiPacient.Cod_diagnostic) END) as exp, tblServiciiPacient.Id_serviciu_pacient"+ " FROM tblPacienti INNER JOIN"+ " tblServiciiPacient ON tblPacienti.Id_pacient ="+ " tblServiciiPacient.Id_pacient INNER JOIN"+ " tblAngajati ON tblAngajati.Id_angajat = tblPacienti.Parafa INNER " JOIN tblSubserviciu ON tblServiciiPacient.Id_subserviciu ="+ " tblSubserviciu.Id_subserviciu INNER JOIN"+ " tblCategoriiServicii ON tblSubserviciu.Id_cat_serviciu ="+ " tblCategoriiServicii.Id_cat_serviciu INNER JOIN"+ " tblPachetServicii ON tblCategoriiServicii.Cod_pachet = "+ " tblPachetServicii.Cod_pachet " + " where tblPacienti.CNP='"+cnp+"' and tblSubserviciu.Denumire='"+den+"'"; //cauta in baza serviciul ce se va modifica InterogareBaza conectare = new InterogareBaza("citire",sql1); //asteapta sa termine firul try { conectare.fir.join(); } catch (InterruptedException e) {e.printStackTrace();} Vector v1= conectare.getVectorRezultat(); if (v1.size()!=0) { cardLayout.show(panou_formular, "unu"); salv_modif.setEnabled(true); salveaza.setEnabled(false); camp_parafa.setText(v1.elementAt(0).toString()); camp_cnp.setText(v1.elementAt(1).toString()); camp_cnp.setEditable(false); camp_nume.setText(v1.elementAt(2).toString()); camp_nume.setEditable(false); camp_prenume.setText(v1.elementAt(3).toString()); camp_prenume.setEditable(false); //selecteaza unul din cele 2 butoane radio if (v1.elementAt(4).toString().equals("M")) masculin.setSelected(true); else

113

feminin.setSelected(true); camp_data.setText(v1.elementAt(5).toString()); camp_data.setEditable(false); camp_judet.setText(v1.elementAt(6).toString()); camp_judet.setEditable(false); camp_localitate.setText(v1.elementAt(7).toString()); camp_localitate.setEditable(false); if (v1.elementAt(8) != null) //adresa in baza poate fi nula camp_adresa.setText(v1.elementAt(8).toString()); camp_adresa.setEditable(false); camp_data_e.setDataString(v1.elementAt(9).toString()); camp_nr_registru.setText(v1.elementAt(10).toString()); camp_pachet.setText(v1.elementAt(11).toString()); camp_pachet.setEditable(false); camp_serviciu.setText(v1.elementAt(12).toString()); if (v1.elementAt(13) != null) camp_diagnostic.setText(v1.elementAt(13).toString ()); return Integer.parseInt(v1.elementAt(14).toString()); } else JOptionPane.showMessageDialog(null, "Serviciul nu exist\u0103 \u00een baza de date...","Eroare" ,JOptionPane.ERROR_MESSAGE); return 0; } public int modifica(int id_serviciu) { String sql =" UPDATE [medicina_familie].[dbo]. [tblServiciiPacient] "+ " SET [Data_efectuarii] = '"+ camp_data_ef.getDateSQL() + "', " [Id_subserviciu] = (select Id_subserviciu from tblSubserviciu where Denumire ='"+camp_serviciu.getText().trim()+"') ,"+ " [Nr_registru] = "+ camp_nr_registru.getText().trim() +" , [Cod_diagnostic] = (select Cod_diagnostic from tblDiagnosticServiciiUrgenta where Denumire_diagnostic = '"+camp_diagnostic.getText().trim()+"')"+ " WHERE Id_serviciu_pacient = "+ id_serviciu; InterogareBaza conectare = new InterogareBaza("modifica",sql); try { conectare.fir.join(); } catch (InterruptedException e) {e.printStackTrace();} return conectare.getRezultat(); } public int sterge_serviciu() {

114

String cauta_id = " (SELECT Id_pacient FROM tblPacienti WHERE CNP='" + data_rand_selectat.elementAt(0) + "')"; String cauta_subserviciu =" (SELECT Id_subserviciu FROM tblSubserviciu WHERE Denumire= '"+ data_rand_selectat.elementAt(4) +"')"; String sql = "DELETE FROM [medicina_familie].[dbo]. [tblServiciiPacient]" + " WHERE (Id_pacient = " + cauta_id + " AND Id_subserviciu = " + cauta_subserviciu + " )"; InterogareBaza conectare = new InterogareBaza("stergere",sql); try { conectare.fir.join(); } catch (InterruptedException e) {e.printStackTrace();} //intoarce rezultatul metodei stergere return conectare.getRezultat(); } public void componentHidden(ComponentEvent e) { if ( e.getComponent().equals(panel_vizualizare)) { luna.setEnabled(false); an.setEnabled(false); butonActualizare.setEnabled(false); butonModifica.setEnabled(false); butonSterge.setEnabled(false); } } public void componentShown(ComponentEvent e) { if ( e.getComponent().equals(panel_vizualizare)) { luna.setEnabled(true); an.setEnabled(true); butonActualizare.setEnabled(true); butonModifica.setEnabled(true); butonSterge.setEnabled(true); } } public void componentMoved(ComponentEvent arg0) {} public void componentResized(ComponentEvent arg0) {} //returneaza panoul principal pe care se afla restul panourilor public JComponent getComponent() { return mainSplitPane; } }//sf clasei Servicii

115

TabelaSimpla.java
package tabela; import java.awt.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.table.*; import sql.*; import java.util.Vector; public class TabelaSimpla extends JPanel { public JTable aTable; private MyTableModel aModel; private boolean ALLOW_ROW_SELECTION = true; private String[] numeColoane={}; private Object[][] data = null; private int colNo=0,rowNo=0; public TabelaSimpla() { super(new GridLayout(1,0)); aTable = new JTable(); aTable.setPreferredScrollableViewportSize(new Dimension(500, 70)); aTable.setFillsViewportHeight(true); //Create the scroll pane and add the table to it. JScrollPane scrollPane = new JScrollPane(aTable); add(scrollPane); aTable.setSelectionMode (ListSelectionModel.SINGLE_SELECTION); if (ALLOW_ROW_SELECTION) { // true by default ListSelectionModel rowSM = aTable.getSelectionModel(); rowSM.addListSelectionListener(new ListSelectonListener() { public void valueChanged(ListSelectionEvent e) { //Ignore extra messages. if (e.getValueIsAdjusting()) return; ListSelectionModel lsm = (ListSelectionModel)e.getSource(); if (lsm.isSelectionEmpty()) { } else { aTable.setRowSelectionAllowed(false); } } public void citire(String SQL) { //citim din baza

116

InterogareBaza conectare = new InterogareBaza("citire2",SQL); //asteapta sa termine firul try { conectare.fir.join(); } catch (InterruptedException e) {e.printStackTrace();} data = conectare.data; numeColoane = conectare.numeColoane; colNo = conectare.colNo2; rowNo = conectare.rowNo2; aModel = new MyTableModel(); aTable.setModel(aModel); } public void afisare_header(String[] header) { numeColoane = header; colNo = header.length; rowNo = 0; data = new Object[rowNo][colNo]; aModel = new MyTableModel(); aTable.setModel(aModel); } public Vector<Object> afiseazaData(JTable table) { Vector<Object> v = new Vector<Object>(); int rowSelected = table.getSelectedRow(); System.out.print(" Value of data: "); for (int j=0; j < table.getColumnCount(); j++) { System.out.print(" " + table.getModel().getValueAt(rowSelected, j)); v.add(table.getModel().getValueAt(rowSelect ed, j)); } return v; } class MyTableModel extends AbstractTableModel { public int getColumnCount() { return (colNo); } public int getRowCount() { return(rowNo); } public String getColumnName(int i) { return (numeColoane[i]); } public java.lang.Object getValueAt(int row, int column) { return(data[row][column]); } public Class getColumnClass(int c) { if (getValueAt(0, c)==null) return String.class;

117

return getValueAt(0, c).getClass(); } public boolean isCellEditable(int row, int col) { return false; //nu } public void setValueAt(Object value, int row, int col) { data[row][col] = value; fireTableCellUpdated(row, col); } }; public void addRow(Vector<Object> v) { int r = aModel.getRowCount(); rowNo = r+1; //creste nr de linii Object[][] temp_vector = data; data = new Object[rowNo][colNo]; for (int R=0;R< rowNo-1 ;R++) for(int C=0; C<colNo;C++) data[R][C]= temp_vector[R][C]; //pe ultima linie for(int C=0; C<colNo; C++) data[rowNo-1][C] = v.elementAt(C); aModel.fireTableRowsInserted(r,r); } public void removeRow(int index) { int r = aModel.getRowCount(); rowNo = r-1; //scade nr de linii Object[][] temp_vector = data; data = new Object[rowNo][colNo]; for (int R=0;R< rowNo; R++) { if (R>=index) { for(int C=0; C<colNo;C++) data[R][C]= temp_vector[R+1][C];//peste linia index }else for(int C=0; C<colNo;C++) data[R][C]= temp_vector[R][C]; } aModel.fireTableRowsDeleted(index, index); } public void updateRow(int index, Vector<Object> v) { int c = aModel.getColumnCount(); for (int i = 0 ;i<c; i++) aModel.setValueAt(v.elementAt(i), index, i);

118

aModel.fireTableRowsUpdated(index, index); } };//sf calsei TabelaSimpla

Pacienti.java
package pacienti; import java.awt.*; import javax.swing.*; import javax.swing.border.*; import javax.swing.event.*; import meniuri.MenuMedic; import java.awt.event.*; import java.util.*; import servicii.*; import sql.*; import tabela.*; public class Pacienti extends JSplitPane implements ActionListener { private JPanel panou_optiuni; private JTabbedPane panou_formular; private JComboBox luna, an; private JButton butonAdauga,butonModifica,butonSterge, butonActualizare,butonIesire; tabela_sortare_filtrare table_pacienti,table_intrati, table_iesiti; String SQL_inscrisi = "SELECT CNP, Nume, Prenume, Sex, " + "CONVERT(varchar(10), Data_nasterii, 103) AS Data_nasterii, "+ "CONVERT(varchar(10), Data_intrarii, 103) AS Data_intrarii, "CONVERT(varchar(10), Data_iesirii, 103) AS Data_iesirii, "+"Motiv_intrare, Motiv_iesire, Judet, Localitate, Adresa, Valid, Asigurat "+ FROM tblPacienti WHERE Valid=1"; String SQL_intrati ="SELECT CNP, Nume, Prenume, CONVERT(varchar(10), Data_intrarii, 103) as Data_intrarii, "Motiv_intrare, Judet, Localitate, Asigurat, Valid " + "FROM tblPacienti where Valid =1 "; String SQL_iesiti ="SELECT CNP, Nume, Prenume, CONVERT(varchar(10), Data_iesirii, 103) AS Data_iesirii," + "Motiv_iesire, Judet, Localitate,Asigurat, Valid " + "FROM tblPacienti where Valid =0 "; Vector data = new Vector(); public Pacienti()

119

{ super(JSplitPane.VERTICAL_SPLIT); add(creeaza_panou_optiuni()); add(creeaza_panou_formular()); setDividerSize(5); setOneTouchExpandable(false); butonAdauga.addActionListener(this); butonSterge.addActionListener(this); butonActualizare.addActionListener(this); butonModifica.addActionListener(this); butonIesire.addActionListener(this); luna.setEnabled(false); an.setEnabled(false); butonActualizare.setVisible(false); butonAdauga.setVisible(false); butonModifica.setVisible(false); butonSterge.setVisible(false); panou_formular.setSelectedIndex(0); panou_formular.addChangeListener(new ChangeListener() { // This method is called whenever the selected tab changes public void stateChanged(ChangeEvent evt) { JTabbedPane pane = (JTabbedPane)evt.getSource(); // Get current tab int selectat = pane.getSelectedIndex(); if (selectat == 0) { luna.setEnabled(false); an.setEnabled(false); butonActualizare.setVisible(false); butonAdauga.setVisible(false); butonSterge.setVisible(false); butonModifica.setVisible(false); } else if (selectat == 1) { luna.setEnabled(true); an.setEnabled(true); butonActualizare.setVisible(true); butonAdauga.setVisible(true); butonSterge.setVisible(true); butonModifica.setVisible(true); } else if (selectat == 2) { luna.setEnabled(true); an.setEnabled(true); butonActualizare.setVisible(true); butonAdauga.setVisible(true); butonSterge.setVisible(true);

120

butonModifica.setVisible(true); } } }); } protected JPanel creeaza_panou_optiuni() //panou butoane si calendare { panou_optiuni = new JPanel(new GridLayout(1,3,10,10)); panou_optiuni.setBackground(new Color(100,186,186)); panou_optiuni.setPreferredSize(new Dimension(600,100)); //tine subpanou1-ul si subpanou2 panou_optiuni.setBorder(BorderFactory.createCompoundBorder( new EtchedBorder(EtchedBorder.RAISED), BorderFactory.createEmptyBorder(15,15,15,15))); //partea de jos JPanel subpanou1 = new JPanel(new GridLayout(2,2,5,10)); subpanou1.setPreferredSize(new Dimension(400,80)); subpanou1.setOpaque(false); butonAdauga = new JButton("Adaug\u0103"); butonSterge = new JButton("\u015eterge"); butonModifica = new JButton("Modific\u0103"); butonActualizare = new JButton("Actualizare"); butonIesire = new JButton("Ie\u015fire"); subpanou1.add(butonActualizare); subpanou1.add(butonAdauga); subpanou1.add(new JLabel()); subpanou1.add(butonModifica); subpanou1.add(butonSterge); subpanou1.add(butonIesire); //partea de sus JPanel subpanou2 = new JPanel(new GridLayout(2,2,10,10)); Border border = new TitledBorder(new EtchedBorder(5), "Luna de raportare:", TitledBorder.ABOVE_TOP, TitledBorder.DEFAULT_POSITION, new Font("Arial",Font.BOLD,12), Color.white); subpanou2.setBorder(border); subpanou2.setOpaque(false); luna = new JComboBox(MenuMedic.luni); luna.setSelectedItem(Integer.toString(MenuMedic.month)); an = new JComboBox(MenuMedic.ani); an.setSelectedItem(Integer.toString(MenuMedic.year)); JLabel l1 = new JLabel("Luna:"); JLabel l2 = new JLabel("Anul:"); subpanou2.add(l1); subpanou2.add(luna);

121

subpanou2.add(l2); subpanou2.add(an); JPanel gol = new JPanel(); gol.setOpaque(false); panou_optiuni.add(subpanou2); panou_optiuni.add(gol); panou_optiuni.add(subpanou1); return panou_optiuni; } protected JTabbedPane creeaza_panou_formular() { panou_formular = new JTabbedPane(); panou_formular.setBorder (BorderFactory.createEmptyBorder(10,10,10,10)); panou_formular.addTab("Inscrisi", creeaza_panou_inscrisi()); panou_formular.addTab("Intrari", creeaza_panou_intrati()); panou_formular.addTab("Iesiri", creeaza_panou_iesiti()); return panou_formular; } public JPanel creeaza_panou_inscrisi() { table_pacienti = new tabela_sortare_filtrare(SQL_inscrisi); table_pacienti.aTable.setAutoResizeMode(JTable.AUTO_RESIZE_ OFF); return table_pacienti; } public JPanel creeaza_panou_intrati() { String sql = SQL_intrati + " AND DATEPART(month, Data_intrarii) = "+ luna.getSelectedItem().toString() + " and DATEPART(year, Data_intrarii)= "+ an.getSelectedItem().toString(); table_intrati = new tabela_sortare_filtrare(sql); return table_intrati; } public JPanel creeaza_panou_iesiti() { String lu = luna.getSelectedItem().toString(); String a = an.getSelectedItem().toString(); String sql = SQL_iesiti + " AND DATEPART(month, Data_iesirii) = "+ lu + " and DATEPART(year, Data_iesirii)= "+ a ; table_iesiti = new tabela_sortare_filtrare(sql);

122

return table_iesiti; } //handler evenimente de la butoanele de pe panou_optiuni public void actionPerformed(ActionEvent ev) { if (ev.getSource().equals(butonAdauga)) { if (panou_formular.getSelectedIndex()==1)//panoul vizibil e cel cu intrari { AdaugaPacient pacient_nou = new AdaugaPacient(); if (!pacient_nou.data_intrat.isEmpty()) table_intrati.addRow(pacient_nou.data_intrat); } else if (panou_formular.getSelectedIndex()==2)//panoul vizibil e cel cu iesiti { Selector selector = new Selector("Selector Pacienti","SELECT * FROM View_selector_pacienti"); if (selector.rand_selectat != -1) { String cnp = selector.data_rand_selectat.elementAt(0).toString(); String nume = selector.data_rand_selectat.elementAt(1).toString(); String prenume = selector.data_rand_selectat.elementAt(2).toString(); String judet =selector.data_rand_selectat.elementAt(6).toString(); String local = selector.data_rand_selectat.elementAt(7).toString(); String asig =selector.data_rand_selectat.elementAt(9).toString(); StergePacient stergere_pacient = new StergePacient (cnp, nume, prenume,judet,local,asig); table_iesiti.addRow(stergere_pacient. afiseaza_iesit());//afisam in tabela } } } else if (ev.getSource().equals(butonSterge)) { if (panou_formular.getSelectedIndex()==1)//panoul vizibil e cel cu intrari { int rand_selectat = table_intrati.aTable.getSelectedRow(); if (rand_selectat!=-1) { Vector data_rand_selectat = table_intrati.afiseazaData(table_intrati.aTable); String sql = "DELETE FROM tblPacienti where CNP='"+data_rand_selectat.elementAt(0)+"'";

123

InterogareBaza conectare = new InterogareBaza("stergere",sql); try { conectare.fir.join(); } catch (InterruptedException e1) { e1.printStackTrace(); } if (conectare.getRezultat()==1){ JOptionPane.showMessageDialog(null, "\u015etergere cu succes!","Mesaj" ,JOptionPane.INFORMATION_MESSAGE); table_intrati.removeRow(rand_selectat); } else JOptionPane.showMessageDialog(null, "Eroare la \u015ftergere...","Eroare" ,JOptionPane.ERROR_MESSAGE); } else JOptionPane.showMessageDialog(null, "Selecta\u0163i o linie din tabel!","Mesaj" ,JOptionPane.INFORMATION_MESSAGE); } else if (panou_formular.getSelectedIndex()==2)//panoul vizibil e cel cu iesiti { int rand_selectat = table_iesiti.aTable.getSelectedRow(); if (rand_selectat!=-1) { Vector data_rand_selectat = table_iesiti.afiseazaData(table_iesiti.aTable); String sql = "UPDATE tblPacienti SET Valid = 1,Data_iesirii = NULL,Motiv_iesire = NULL where CNP='"+data_rand_selectat.elementAt(0)+"'"; InterogareBaza conectare = new InterogareBaza("modifica",sql); try { conectare.fir.join(); } catch (InterruptedException e1) { e1.printStackTrace(); } if (conectare.getRezultat()==1){ JOptionPane.showMessageDialog(null, "Modificare cu succes!","Mesaj" ,JOptionPane.INFORMATION_MESSAGE); //il scoatem de le lista de iesiti table_iesiti.removeRow(rand_selectat); } else JOptionPane.showMessageDialog(null, "Eroare la modificare...","Eroare" ,JOptionPane.ERROR_MESSAGE); } else JOptionPane.showMessageDialog(null, "Selecta\u0163i o linie din tabel!","Mesaj" ,JOptionPane.INFORMATION_MESSAGE); } } else if (ev.getSource().equals(butonActualizare))

124

{ //recream modelul String lu = luna.getSelectedItem().toString(); String a = an.getSelectedItem().toString(); String sql1 = SQL_intrati + " AND DATEPART(month, Data_intrarii) = "+lu + " AND DATEPART(year, Data_intrarii)= "+ a ; table_intrati.actualizare(sql1); String sql2 = SQL_iesiti + " AND DATEPART(month, Data_iesirii) = "+ lu + " AND DATEPART(year, Data_iesirii)= "+ a ; table_iesiti.actualizare(sql2);//refacem modelul } else if (ev.getSource().equals(butonIesire)) { //nultimul panou care a fost vizibil MenuMedic.afiseaza_panel_gol(MenuMedic.cards.elementAt(Menu Medic.cards.size()-2)); MenuMedic.cards.removeElementAt(MenuMedic.cards.size()-1); } } }//sf clasei Pacienti

MenuMedic.java
package meniuri; import java.awt.*; import javax.swing.*; import java.awt.event.*; import java.util.Calendar; import java.util.Vector; import admin.*; import raport.BrowserControl; import servicii.*; import pacienti.*; public class MenuMedic extends JFrame implements ActionListener { private JPanel mainPanel,panou_meniu; private JMenuBar menuBar; private JToolBar bara_unelte; private JMenu opt_servicii,opt_lista,opt_administrare, opt_raportari,opt_ajutor; private JMenuItem menuItemServicii,menuItemRetete, menuItemCertificate,menuItemBilete, menuItemUnitate, menuItemContracte, menuItemUtilizatori, menuItemIesire, menuItemInscrisi,

125

menuItemFormulareRaportare, menuItemDespre; public static CardLayout cardLayout; public static JPanel panel_continut; private ToolBarButton buttons[]; public static String luni[] = new String[] {"1","2","3","4","5","6","7","8","9","10","11","12"}; public static String ani[] = new String[] {"2009","2010","2010","2010"}; public static Calendar cal = Calendar.getInstance(); public static int month = cal.get(Calendar.MONTH) + 1; public static int year = cal.get(Calendar.YEAR); public static Vector<String> cards = new Vector<String>(); private JComponent gol, panou_servicii , panou_retete,panou_bilete , panou_certificate , panou_pacienti; public MenuMedic() { super("Medic"); mainPanel = new JPanel(new BorderLayout()); ImagePanel pan = new ImagePanel(new ImageIcon("imagini/bun.jpg").getImage()); pan.setLayout(new BorderLayout()); pan.setPreferredSize(new Dimension(600,60)); pan.add(creeazaMeniu(),BorderLayout.NORTH); pan.add(creeaza_bara_unelte(),BorderLayout.EAST); mainPanel.add(pan,BorderLayout.NORTH); mainPanel.add(creeazaContinut(),BorderLayout.CENTER); this.getContentPane().add(mainPanel); this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);//d istruge fereastra si continutul this.setSize(1000,700); this.setLocationRelativeTo(null); } class ImagePanel extends JPanel { private Image img; public ImagePanel(String img) { this(new ImageIcon(img).getImage()); } public ImagePanel(Image img) { this.img = img; Dimension size = new Dimension(img.getWidth(null), img.getHeight(null)); setPreferredSize(size); setMinimumSize(size); setMaximumSize(size); setSize(size);

126

setLayout(null); } public void paintComponent(Graphics g) { g.drawImage(img, 0, 0, null); } } protected JPanel creeazaMeniu() { //panelul pe care se adauga meniul si calendarul panou_meniu = new JPanel(new BorderLayout()); panou_meniu.setBackground(new Color(49,98,102)); //creeam bara de meniu menuBar = new JMenuBar(); //creeam meniurile // Lista pacienti Menu, L - Mnemonic opt_lista = new JMenu("Pacien\u0163i"); opt_lista.setMnemonic(KeyEvent.VK_P);//definim shortcut opt_lista.getAccessibleContext().setAccessibleDescription(" Lista cu pacientii inscrisi"); // Servicii Menu, S - Mnemonic opt_servicii = new JMenu("Servicii \u015fi documente"); opt_servicii.setMnemonic(KeyEvent.VK_S); // Imunizari Menu, A - Mnemonic opt_administrare = new JMenu("Administrare"); opt_administrare.setMnemonic(KeyEvent.VK_A); // Raportari Menu, I - Mnemonic opt_raportari = new JMenu("Raport\u0103ri"); opt_raportari.setMnemonic(KeyEvent.VK_R); opt_ajutor = new JMenu("Ajutor"); //creeam submeniurile // Servicii->Servicii, S - Mnemonic menuItemServicii = new JMenuItem("Servicii medicale"); opt_servicii.add(menuItemServicii); menuItemServicii.setAccelerator(KeyStroke.getKeyStroke(KeyE vent.VK_S, ActionEvent.CTRL_MASK)); opt_servicii.addSeparator(); // Servicii->Servicii, S - Mnemonic menuItemRetete = new JMenuItem("Re\u0163ete"); opt_servicii.add(menuItemRetete); menuItemRetete.setAccelerator(KeyStroke.getKeyStroke(KeyEve nt.VK_R, ActionEvent.CTRL_MASK)); opt_servicii.addSeparator(); // Servicii->Retete, C - Mnemonic menuItemCertificate = new JMenuItem("Certificate medicale");

127

opt_servicii.add(menuItemCertificate); menuItemCertificate.setAccelerator(KeyStroke.getKeyStroke(K eyEvent.VK_C, ActionEvent.CTRL_MASK)); opt_servicii.addSeparator(); // Servicii->Bilete, B - Mnemonic menuItemBilete = new JMenuItem("Bilete de trimitere"); opt_servicii.add(menuItemBilete); menuItemBilete.setAccelerator(KeyStroke.getKeyStroke(KeyEve nt.VK_B, ActionEvent.CTRL_MASK)); // Administrare->Unitate medicala, U - Mnemonic menuItemUnitate = new JMenuItem("Unitate medical\u0103"); opt_administrare.add(menuItemUnitate); menuItemUnitate.setAccelerator(KeyStroke.getKeyStroke(KeyEv ent.VK_U, ActionEvent.CTRL_MASK)); opt_administrare.addSeparator(); // Administrare->Contracte, K - Mnemonic menuItemContracte = new JMenuItem("Contracte \u015Fi conven\u0163ii"); opt_administrare.add(menuItemContracte); menuItemContracte.setAccelerator(KeyStroke.getKeyStroke(Key Event.VK_K, ActionEvent.CTRL_MASK)); opt_administrare.addSeparator(); // Administrare->Contracte, K - Mnemonic menuItemUtilizatori = new JMenuItem("Utilizatori"); opt_administrare.add(menuItemUtilizatori); menuItemUtilizatori.setAccelerator(KeyStroke.getKeyStroke(K eyEvent.VK_U, ActionEvent.ALT_MASK)); opt_administrare.addSeparator(); opt_administrare.addSeparator(); menuItemIesire =new JMenuItem("Ie\u015Fire"); opt_administrare.add(menuItemIesire); // Lista pacienti->Inscrisi, I - Mnemonic menuItemInscrisi = new JMenuItem("List\u0103 pacien\u0163i \u00eenscri\u015Fi"); opt_lista.add(menuItemInscrisi); //Raportari->Formulare, F - Mnemonic opt_raportari.addSeparator(); menuItemFormulareRaportare = new JMenuItem("Formulare de raportare"); opt_raportari.add(menuItemFormulareRaportare); menuItemFormulareRaportare.setAccelerator(KeyStroke.getKeyS troke(KeyEvent.VK_F, ActionEvent.ALT_MASK)); opt_ajutor.addSeparator(); menuItemDespre = new JMenuItem("Despre..."); opt_ajutor.add(menuItemDespre); //adaugam optiunile pe bara si bara pe panoul panou_meniu menuBar.add(opt_administrare);

128

menuBar.add(opt_lista); menuBar.add(opt_servicii); menuBar.add(opt_raportari); menuBar.add(opt_ajutor); panou_meniu.add(menuBar,BorderLayout.NORTH); //adaugam ascultator pt JMenuItem menuItemServicii.addActionListener(this); menuItemRetete.addActionListener(this); menuItemCertificate.addActionListener(this); menuItemBilete.addActionListener(this); menuItemUnitate.addActionListener(this); menuItemContracte.addActionListener(this); menuItemInscrisi.addActionListener(this); menuItemFormulareRaportare.addActionListener(this); menuItemIesire.addActionListener(this); menuItemDespre.addActionListener(this); menuItemUtilizatori.addActionListener(this); return panou_meniu; } protected JToolBar creeaza_bara_unelte() { bara_unelte = new JToolBar(); String[] imageFiles = { "servicii.gif","retete.gif","certificate2.gif", "pacienti.gif" }; //imaginile de pe butoane String[] toolbarLabels = {"Servicii medicale","Re\u0163ete","Certificate medicale" ,"Bilete de trimitere" }; Insets margins = new Insets(0, 0, 0, 0); buttons = new ToolBarButton[toolbarLabels.length]; for(int i=0; i<toolbarLabels.length; i++) { buttons[i] = new ToolBarButton("imagini/" + imageFiles[i]); buttons[i].setToolTipText(toolbarLabels[i]); buttons[i].setMargin(margins); buttons[i].addActionListener(this); bara_unelte.add(buttons[i]); bara_unelte.addSeparator(new Dimension(1,10)); } return bara_unelte; } class ToolBarButton extends JButton { private final Insets margins = new Insets(0, 0, 0, 0); public ToolBarButton(Icon icon) { super(icon); setMargin(margins); setVerticalTextPosition(BOTTOM); setHorizontalTextPosition(CENTER); } public ToolBarButton(String imageFile) {

129

this(new ImageIcon(imageFile)); } public ToolBarButton(String imageFile, String text) { this(new ImageIcon(imageFile)); setText(text); } };//inner class public JPanel creeazaContinut() { cardLayout = new CardLayout(0,0); panel_continut = new JPanel(cardLayout); //un panel gol colorat gol = new JPanel(); gol.setBackground(new Color(150,179,184)); cards.add("6"); panou_servicii = new Servicii().getComponent(); panou_retete = new Reteta().getComponent(); panou_bilete = new Bilet_trimitere().getComponent(); panou_certificate = new Certificat_medical().getComponent(); panou_pacienti = new Pacienti(); panel_continut.add(gol,"6"); panel_continut.add(panou_servicii,"1" ); panel_continut.add(panou_retete,"2" ); panel_continut.add(panou_bilete,"3" ); panel_continut.add(panou_certificate,"4" ); panel_continut.add(panou_pacienti,"5"); return panel_continut; } public static void afiseaza_panel_gol(String panou) { cardLayout.show(panel_continut, panou); } public void actionPerformed(ActionEvent ev) { if(ev.getSource()== menuItemServicii || ev.getSource()== buttons[0] ) { cardLayout.show(panel_continut, "1"); cards.add("1"); } else if(ev.getSource()== menuItemRetete || ev.getSource()== buttons[1] ) { cardLayout.show(panel_continut, "2"); cards.add("2"); }

130

else if(ev.getSource()== menuItemBilete || ev.getSource()== buttons[3]) { cardLayout.show(panel_continut, "3"); cards.add("3"); } else if(ev.getSource()== menuItemCertificate || ev.getSource()== buttons[2]) { cardLayout.show(panel_continut, "4"); cards.add("4"); } else if(ev.getSource()== menuItemInscrisi) { cardLayout.show(panel_continut, "5"); cards.add("5"); } else if(ev.getSource()== menuItemUnitate) { UnitateMedicala unitate = new UnitateMedicala(); } else if(ev.getSource()== menuItemContracte) { ContracteConventii con = new ContracteConventii(); } else if(ev.getSource()== menuItemDespre) { JOptionPane.showMessageDialog(null, "Absolvent: Manda Mihaela-Adina\n Sec\u0163ia: Calculatoare Rom\u00e2n\u0103 ","Despre" ,JOptionPane.INFORMATION_MESSAGE); } else if(ev.getSource()== menuItemUtilizatori) { Utilizator utiliz = new Utilizator(); } else if(ev.getSource()== menuItemFormulareRaportare) { BrowserControl.displayURL("http://experience/ReportServer/P ages/ReportViewer.aspx?%2fRapoarte_medic %2fReport_servicii_lunare&rs:Command=Render"); } else if(ev.getSource()== menuItemIesire) { this.dispose(); // iesire

131

} } }//sf clasei MenuMedic

132