Ihealth – Aplicatie Pentru Clinici de Gestiune a Datelor

PROIECT DE DISERTAȚIE

Ionovici Raluca – Daniela

COORDONATOR ȘTIINȚIFIC

Sef Lucrari Dr. Ing. Marius Marian

Iulie 2016

CRAIOVA

iHEALTH – Aplicație pentru clinici de gestiune a datelor

Ionovici Raluca – Daniela

COORDONATOR ȘTIINȚIFIC

Sef Lucrari Dr. Ing. Marius Marian

Iulie 2016

CRAIOVA

„Învățătura este o comoară care își urmează stăpânul pretutindeni.”

Proverb popular

DECLARAȚIE DE ORIGINALITATE

Subsemnata IONOVICI RALUCA – DANIELA studenta la specializarea AUTOMATICA SISTEMELOR COMPLEXE din cadrul Facultății de Automatică, Calculatoare și Electronică a Universității din Craiova, certific prin prezenta că am luat la cunoștință de cele prezentate mai jos și că îmi asum, în acest context, originalitatea proiectului meu de disertație:

cu titlul iHEALTH – Aplicație pentru clinici de gestiune a datelor

coordonată de Sef Lucrari Dr. Ing. MARIUS MARIAN,

prezentată în sesiunea IULIE 2016

La elaborarea proiectului de disertație, se consideră plagiat una dintre următoarele acțiuni:

reproducerea exactă a cuvintelor unui alt autor, dintr-o altă lucrare, în limba română sau prin traducere dintr-o altă limbă, dacă se omit ghilimele și referința precisă,

redarea cu alte cuvinte, reformularea prin cuvinte proprii sau rezumarea ideilor din alte lucrări, dacă nu se indică sursa bibliografică,

prezentarea unor date experimentale obținute sau a unor aplicații realizate de alți autori fără menționarea corectă a acestor surse,

însușirea totală sau parțială a unei lucrări în care regulile de mai sus sunt respectate, dar care are alt autor.

Pentru evitarea acestor situații neplăcute se recomandă:

plasarea între ghilimele a citatelor directe și indicarea referinței într-o listă corespunzătoare la sfărșitul lucrării,

indicarea în text a reformulării unei idei, opinii sau teorii și corespunzător în lista de referințe a sursei originale de la care s-a făcut preluarea,

precizarea sursei de la care s-au preluat date experimentale, descrieri tehnice, figuri, imagini, statistici, tabele et caetera,

precizarea referințelor poate fi omisă dacă se folosesc informații sau teorii arhicunoscute, a căror paternitate este unanim cunoscută și acceptată.

Data, Semnătura candidatului,

PROIECTUL DE DISERTAȚIE

REFERATUL CONDUCĂTORULUI ȘTIINȚIFIC

În urma analizei lucrării candidatului au fost constatate următoarele:

În concluzie, se propune:

Data, Semnătura conducătorului științific,

REZUMATUL PROIECTULUI

Aplicația iHealth își propune să îmbunatățească eficiența operațională a actului medical prin diferite servicii puse la dispoziția tuturor persoanelor care interacționează direct sau indirect într-un centru medical de diagnostic și/sau tratament.

Necesitatea unei astfel de aplicații web pornește de la idea că medicina modernă presupune și o schimbare a mentalității atât a pacienților, în ceea ce privește propria sănătate, dar și a personalului medical în asigurarea unui relații medic-pacient mult mai strânsă și menținută în timp real si accesibilă de oriunde.

Într-un mediu economic deosebit de dinamic, prezența pe internet este o necesitate, o aplicație de genul iHealth îmbunătățește imaginea firmei și astfel poate atrage mai mulți clienți. Pe lângă necesitate, aplicația iHealth mai vine cu o calitate, și anume simplitate dispunând de o interfață intuitive și ușor de folosit de absolut orice persoana. Pe lângă acest lucru, interfața aplicației este una responsive și se adaptează dispozitivului de pe care aplicația este accesată. Astfel in interiroul unei clinici, se poate renunța la banalul PC, prin inlocuirea s-a, de ce nu, cu o tabletă, astfel încât răspunsul și actualizarea datelor să se facă pe măsura ce pacientul este sub control.

Obtinerea unei interfete intuitive se realizeaza prin integrarea naturala a elementelor de raportare, analiza si monitorizare a performantelor activitatilor. De asemenea, prezentand o arhitectura scalabila si o singura metadata, utilizatorii pot naviga cu usurinta de la meniuri si tabele de performanta catre rapoarte si analize fara a fi nevoiti sa foloseasca o multitudine de instrumente si sa interactioneze cu diverse interfete.

Din punctul de vedere al unui utilizator, consumul de resurse al aplicației este insesizabil, tot ceea ce se înseamnă procesarea datelor este facută de serverul Web. Această aplicație putând fi accesată de pe orice browser.

Aplicația iHealth este un produs software accesibil oricarei categorii de utilizatori ai unui calculator. Totusi, avand in vedere complexitatea aplicatiei, este necesara realizarea unor interfete dedicate in functie de rolul utilizatorului, astfel aceasta va fi structurată în patru module diferite. În urma acestor patru secțiuni s-au definit și patru tipuri de acces în aplicație

Termenii cheie: produs software, aplicație, utilizator, sănătate, interfață, clinică, php, mysql, symfony.

MULȚUMIRI

De-a lungul celor șase ani petrecuți în Facultatea de Automatică Calculatoare și Electronică am întâlnit curs de curs, semetru de semestru, an de an, cadre didactice de prestigiu, care s-au ridicat la nivelul așteptaților mele, atât la ciclul licență, cât și la masterat. Prin prisma experiențelor din alte instituții de învățământ atât din țara cât și din afară, am realizat că avem un corp profesoral foarte bine pregătit și care se dezvoltă continuu.

Pe această cale aș vrea să mulțumesc tuturor cadrelor didactice care au contibuit la dezvoltarea mea profesională, dar și mai mult decât atâta, la dezvoltarea mea ca om. Datorez tot succesul omului care sunt acum fiecărui cadru didactic care a pus o cărămidă la temelia mea profesională.

Nu în ultimul rând aș vrea să mulțumesc domnului Dr. Ing. MARIUS MARIAN, coordonatul lucrării de disertație, pentru tot sprijinul și toate sfaturile acordate de-a lungul studiui pentru această lucrare.

CUPRINSUL

1. Introducere 1

1.1 Scopul 1

1.2 Motivația 1

2. tehnologii folosite 2

2.1 Baze de date SQL 2

2.2 Limbajul PHP 4

2.3 Limbajul HTML 8

2.4 Serverul web Apache 9

3. DESCRIEREA APLICAȚIEI 11

3.1 Baza de date 13

4. MANUALUL DE UTILIZARE 20

4.1 Modulul de administrare 20

4.1.1 Logarea 20

4.1.2 Meniu 24

4.1.3 Pacienți 26

4.1.3.1 Submeniul Listă 26

4.1.3.2 Submeniul Carduri pacienți 33

4.1.3.3 Submeniul Programări 35

4.1.4 Analize 43

4.1.4.1 Submeniul Tipuri analize 44

4.1.4.2 Submeniul Programări Analize 45

4.1.5 Doctori 46

4.1.5.1 Submeniul Lista 46

4.1.5.2 Submeniul Tipuri consultatii 53

4.1.6 Setari 54

4.1.6.1 Specializări 55

4.1.6.2 Utilizatori interni 56

4.2 Modulul Medicului 61

4.2.1 Logarea 61

4.2.2 Meniu 61

4.2.2.1 Submeniul Programările mele 61

4.2.2.2 Submeniul Consultațiile mele 73

4.3 Modulul de laborator 74

4.3.1 Logarea 74

4.3.2 Meniu 74

4.3.2.1 Submeniul Analize programate 75

4.3.2.2 Submeniul Tipuri analize 80

5. Termeni de utilizare 82

5.1 Autorii 82

5.2 Licența de utilizare 82

6. Concluzii 83

7. Bibliografie 84

8. Referințe web 85

A. Codul sursă 86

B. CD / DVD 104

C. INDEX 105

LISTA FIGURILOR

Figura 1 – Deservirea unei pagini dinamice, modificata de PHP in momentul request-ul 4

Figura 2 – Deservirea unei pagini statice, fara interventia interpretorului 5

Figura 3 – Fluxul aplicației iHealth – adăugare programare 13

Figura 4 – Diagrama bazei de date iHealth 14

Figura 5 – Logarea în aplicație ca administrator 20

Figura 6 – Validarea unui user înainte de autentificare 21

Figura 7 – Meniul aplicației din punctul de vedere al admin-ului 24

Figura 8 – Secțiunea pacienți 26

Figura 9 – Butonul de căutare al pacienților în listă 26

Figura 10 – Listă pacienți 27

Figura 11 – Butonul de adăugare al unui pacient în baza de date 30

Figura 12 – Detalii pacient nou 31

Figura 13 – Butonul de salvare al datelor pacienților 31

Figura 14 – Butonul pentru căutarea cardurilor 33

Figura 15 – Lista cardurilor pacienților 34

Figura 16 – Butonul de adăugare al unui card nou 34

Figura 17 – Butonul de salvare al cardului pacientului 34

Figura 18 – Detalii card pacient 35

Figura 19 – Butonul pentru căutarea programărilor 35

Figura 20 – Afișarea tuturor programărilor 36

Figura 21 – Butonul de salvare al programărilor pacienților 40

Figura 22 – Adăugarea unei noi programări 40

Figura 23 – Secțiunea Analize 43

Figura 24 – Afișarea tuturor analizelor inserate în program 44

Figura 25 – Adăugarea analizelor 44

Figura 26 – Listare programări analize 45

Figura 27 – Adaugă programare nouă 46

Figura 28 – Secțiunea Doctori 46

Figura 29 – Afișarea tuturor doctorilor introduși în program 47

Figura 30 – Butonul de căutare al doctorilor în listă 47

Figura 31 – Butonul de adăugare al unui doctor în baza de date 49

Figura 32 – Adaugarea detelor unui doctor 49

Figura 33 – Butonul de căutare al consultațiilor în listă 53

Figura 34 – Afișarea consultațiilor 53

Figura 35 – Butonul de adăugare al unei consultații în baza de date 53

Figura 36 – Adăugarea unei noi consultații 54

Figura 37 – Secțiunea Setari 54

Figura 38 – Adăugarea unei noi specializări 55

Figura 39 – Lista specializărilor 56

Figura 40 – Afișarea utilizatorilor interni 57

Figura 41 – Căutarea unui utilizator 57

Figura 42 – Adăugarea unui nou utilizator 60

Figura 43 – Logarea în aplicație ca medic 61

Figura 44 – Meniul din modulul doctorului 61

Figura 45 – Lista programărilor doctorului 62

Figura 46 – Căutarea unei programări 62

Figura 47 – Adăugarea unei noi programări 63

Figura 48 – Butonul de Acțiuni 64

Figura 49 – Vizualizarea programării 65

Figura 50 – Programare începută 69

Figura 51 – Buton Finalizare programare 69

Figura 52 – Buton Anulează programare 69

Figura 53 – Adaugă programare 69

Figura 54 – Programare finalizată 70

Figura 55 – Factura pacientului 70

Figura 56 – Lista consultațiilor 73

Figura 57 – Filtrarea consultațiilor 73

Figura 58 – Logarea în aplicație ca administrator de laborator 74

Figura 59 – Meniul laboratorului 75

Figura 60 – Filtrarea analizelor 75

Figura 61 – Vizualizarea analizei 76

Figura 62 – Anulează analiza 80

Figura 63 – Afișarea tuturor analizelor inserate în program 80

Figura 64 – Adăugarea analizelor 81

LISTA TABELELOR

Tabelul 1 – Tabelul application_settings 14

Tabelul 2 – Tabelul doctors 15

Tabelul 3 – Tabelul doctors_consultations 15

Tabelul 4 – Tabelul specialities 15

Tabelul 5 – Tabelul invoices 16

Tabelul 6 – Tabelul invoices_lines 16

Tabelul 7 – Tabelul laboratory_analysis 17

Tabelul 8 – Tabelul laboratory_analysis_schedule 17

Tabelul 9 – Tabelul laboratory_analysis_schedule_details 17

Tabelul 10 – Tabelul patients 18

Tabelul 11 – Tabelul patients_addresses 18

Tabelul 12 – Tabelul patients_appointments 18

Tabelul 13 – Tabelul patients_appointments_consultations 19

Tabelul 14 – Tabelul patients_fidelity_cards 19

Tabelul 15 – Tabelul users 19

Introducere

Scopul

Scopul acestui program este de a ușura munca angajaților unei clinici pentru a nu încetini fluxul intern al acesteia.De acum, evidența pacienților și programărilor nu mai este o problemă. Utilizatorul are la dispoziție toate instrumentele de care are nevoie pentru a gestiona cu succes activitățile de administrare a clinicii și pentru a avea un dosar electronic medical al pacienților

Facturile pot fi emise mult mai ușor, acestea ușor sunt înregistrate și centralizate, iar monitorizarea creanțelor devine un procedeu cât se poate de simplu. Un alt avantaj este acela că centralizarea pacienților se face pe fișe ample. Configurarea se poate face simplu, prin modulul de administrare a datelor firmei.

Motivația

Motivația principală a realizării acestui program de administrare a unei clinici este de a gestiona tot mai bine timpul utilizatorului pentru ca acesta să câștige timp în efectuarea diferitelor activități de administrare a programărilor și pacienților din cadrul clinicii. Acesta are rolul de a elimina orice efort depus pentru emiterea acestor documente și de a ține o evidența a acestora.

Am ales această aplicație doarece are o aplicabilitate sporită în zilele noastre.Modul electronic creează o perspectivă mare în viitor iar o asemenea aplicație este punctul de reper pentru orice clinică care dorește a intra pe piață.

tehnologii folosite

Pentru realizarea siteului am folosit baze de date MySql, operațiunile asupra bazelor de date sunt realizate cu ajutorul limbajului PHP, designul siteu-ului este realizate folosind HTML și CSS, iar verificările asupra formularelor sunt realizate cu ajutorul unor funcții de JavaScript

Baze de date SQL

SQL este acronimul de la Structural Query Language. SQL este folosit pentru a stoca și regăsi datele în și dintr-o bază de date.Este utilizat în sisteme de baze de date cum sunt MySQL , Oracle, Microsoft SQL Server și altele.

Inserarea datelor în baza de date

Instrucțiunea INSERT se poate folosi pentru a introduce linii în baza de date.

Operatorul SQL pentru inserare este INSERT INTO și prezintă două variante :

– inserare simplă : pentru inserarea unei tuple individuale

– inserare multiplă : pentru inserarea mai multor tuple

Actualizarea înregistrărilor din baza de date

Update este instrucțiunea care permite actualizarea înregistrărilor unei baze de date .

Operatorul SQL de actualizare îndeplinește două funcții :

selectează prin condiția de căutare din clauza WHERE tuplele care urmează a fi actualizate (în lipsa clauzei WHERE se actualizează implicit toate tuplele relației specificate).

În tuplele selectate modifică valorile atributelor specificate.Expresiile de actualizare pot conține : constante , nume de atribute , valoarea NULL sau expresii aritmetice construite cu acestea.

Formularea interogărilor în limbajul SQL

Instrumentul de bază al SQL este instrucțiunea SELECT.Este folosită pentru a regăsi datele dintr-o bază de date prin selectarea acelor linii din tabelă care corespund criteriului specificat.

Se pot specifica oricâte coloane din tabelă prin trecerea lor după cuvântul cheie SELECT.De asemenea se pot specifica și alte elemente.Un element foarte util este operatorul de înlocuire * , care specifică toate coloanele din tabela sau tabelele specificate.

Valoarea ( valorile) corespunzătoare parametrului ( parametrilor) nume_atribut1 . precizează în mod explicit atributele după care se face selecția.Dacă există ambiguități referitor la relațiile din care fac parte atributele specificate , atunci acestea vor fi precedate de numele relației corespunzătoare.

Dacă există ambiguități referitor la relațiile din care fac parte atributele specificate , atunci acestea vor fi precedate de numele relației corespunzătoare.

– în lipsa operatorului opțional DISTINCT selecția se face fără eliminarea duplicatelor , iar dacă acesta apare , atunci se elimină eventualele duplicate rezultate în urma operației de selecție

– în cazul cel mai general, parametrul nume¬_atribut1 poate fi o expresie aritmetică combinând atribute și/sau funcții de agregare având ca operanzi unul sau mai multe atribute

– parametrul calificator1 precizează criteriul de selecție al tuplelor unei relații

– clauza GROUP BY are ca efect gruparea tuplelor unei relații pe baza valorilor unui atribut sau grup de atribute.Parametrul nume_atribut2 furnizează criteriul de grupare al tuplelor unei relații în submulțimi de tuple , toate avînd aceeași valoare pentru atributul (atributele) nume_atribut2.Criteriul de grupare este format din unul sau mai multe atribute.

– clauza HAVING , opțiune a clauzei GROUP BY, este o formă specială a clauzei WHERE caracterizată prin faptul că se aplică nu unor tuple individuale , ci unor submulțimi (grupuri) de tuple , rezultate ca urmare a selecției făcute prin clauza GROUP BY.

– clauza ORDER BY specifică ordonarea tuplelor unei relații rezultat după valorile parametrului nume¬_atribut3, iar cuvintele ASC și DESC indică modul în care se face ordonarea .

Limbajul PHP

PHP (PHP: Hypertext Prepocessor), este un limbaj de programare de tip interpretat. Asta înseamnă că fișierele ce conțin cod-sursă PHP sunt interpretate că atare în momentul execuției, de către PHP. Așadar, pentru execuția unei porțiuni de cod PHP este folosit codul-sursă așa cum a fost scris el, și nu este transformat într-o formă intermediară (binară sau cod-mașină) cum se întâmplă la Java sau C/C++. Acest lucru oferă flexibilitate, întrucât orice modificare a fișierelor sursă va fi aplicată imediat la următoarea execuție, fără alți pași intermediari. Există și dezavantaje la acest mod de lucru, cum ar fi timp mai mare de execuție a codului, dar în anumite situații avantajele pot cântări mai mult decât dezavantajele. Datorită faptului că limbajul este unul interpretat, PHP mai este numit și limbaj de scripting.

În sens mai larg, PHP este un limbaj de programare universal (sau general-purpose), oferind toate facilitățile oricărui limbaj avansat. Codul scris în PHP poate face aproape aceleași lucruri că un cod de C/C++ sau Java. Cu toate astea, PHP s-a impus în zona web, că limbaj server-side, ce extinde funcționalitatea serverelor web. Din acest motiv programarea în PHP mai este denumită și programare web sau programare web server-side.

Figura – Deservirea unei pagini dinamice, modificata de PHP in momentul request-ul

Interpretorul PHP acționează că o componentă adițională, o extensie a serverului web care este invocată de ori câte ori o pagină PHP este accesată. Această componentă procesează codul-sursă din pagină și apoi transmite rezultatul înapoi la web-server, ajungând în final în browserele utilizatorilor.

Din imaginile de mai jos, se observă că atunci când nu există un interpretor PHP, paginile sunt transmise direct către utilizatori așa cum sunt salvate pe disc, fără modificări. Pentru a actualiza conținutul acestora, este nevoie de intervenție directă asupra lor și salvarea modificărilor pe server. Aceste pagini sunt denumite "pagini statice".

Figura – Deservirea unei pagini statice, fara interventia interpretorului

Programele PHP sunt o mixtură de trei elemente : text, cod HTML și script PHP. Pentru că paginile ce conțin script PHP să poată fi procesate de modulul PHP implementat în Apache sau alt server de pagini Web este necesar ca paginile să aibă acea extensie pe care ați specificat-o la încărcarea modulului în serverul de web (standard, extensia implicită este .php).

Exemplu de program – deschideti un editor de text si scrieti :

<HTML>

<BODY>Program 1 <BR>

<?php

echo “Salut studentule !!”;

?>

</BODY>

</HTML>

Salvati acest fisier in directorul radacina al paginilor de web, sub numele de program1.php, directorul radacina al paginilor web fiind pentru htdocs, creandu-se in cadrul acestuia un folder propriu in care se vor salva toate fisierele dvs. Pentru a deschide o pagina de tip PHP se va scrie in browser-ul de Internet adresa: http://localhost/ urmat de numele directorului in care este salvat fisierul.

Funcțiile sunt porțiuni de cod definite pentru a executa anumite sarcini. Ele pot fi chemate de mai multe ori pe parcursul execuției unui program, primind argumente (valori de intrare) cu ajutorul cărora execută câteva operații după care returnează o valoare. Funcțiile transferă orice valoare primită ca argument în variabile temporare numite parametrii ce pot fi folosiți numai pe parcursul execuției funcției.

Definirea unei funcții se face astfel:

function <nume_functie> (<parametrii>)

{//cod

//cod}

Exemplu:

function tva($lei)

{$total=$lei*1.19;

return $total;}

Apelarea acestei funcții de forma: echo tva(100000); va produce rezultatul 119000. Funcția poate fi apelata si fara argumente :

function tva()

{echo “Valoarea tva este de 19%”;}

Variabilele din interiorul funcțiilor nu se pot vedea in exteriorul lor (se distrug la terminarea funcției) decat daca sunt transmise ca referința.

Variabilele pot fi :

globale

locale

Variabilele globale – sunt variabilele ce își mențin existența pe parcursul execuției întregului program, în timp ce variabilele locale sunt variabilele din interiorul funcțiilor ce își încetează existența după terminarea funcției.

Daca dorim o vizualizare globala a variabilelor locale funcției avem 2 posibilitați :

le trimitem ca referința

le asociem parametrul global inainte de a opera cu variabilele sau folosind vectorul $GLOBALS[]

Variabilele statice – sunt folosite atunci cand este necesar ca acestea sa existe pe parcursul mai multor apelari ale funcțiilor, fara a mai fi necesara o reatribuire.

<?

function vizitatori()

{return ++$vizitatori;}

?>

Rezultatul acestui exemplu este la apelul de forma: echo vizitatori(); – 1 vizitator, iar daca se mai executa inca o data atunci rezultatul va fi tot 1, deoarece variabila este statica.

Este destul ne neplacut ca pe parcursul unei numaratori sa se reseteaza variabila la fiecare apelare a funcției. Pentru a asigura persistenta variabilei, se foloseste cuvantul cheie static.

<?

function vizitatori(){

static $vizitatori;

return ++$vizitatori;}

?>

Rezultatul acestei funcții la prima apelare prin echo vizitatori(); – va fi 1 vizitator, iar prin repetarea apelulului se va afisa 2 vizitatori.

Lucrul cu clientul

PHP poate prelua interactiv datele de la client prin intermediul formularelor. Elementele cele mai importante ale unui formular sunt :

– ACTION – transmite serverului la ce pagina sa se duca si sa transmita datele completate in momentul in care utilizatorul a trimis formularul.

– METHOD – reprezinta modul in care datele sunt trimise serverului.

Metoda GET adauga variabilele in campul de adresa al paginii web.

Metoda POST trimite ascuns variabilele catre pagina descrisa la ACTION.

In cadrul formularului putem avea campuri :

text

textarea

list box (select)

radio

checkbox

hidden

password

Aceste campuri se trimit catre scriptul PHP printr-un buton de tip submit.

Limbajul HTML

Unul din primele elemente fundamentale ale WWW (World Wide Web) este HTML ( Hypertext Markup Language ), care descrie formatul primar în care documentele sunt distribuite și văzute pe Web. Multe din trăsăturile lui, cum ar fi independența față de platformă, structurarea formatării și legăturile hipertext, fac din el un foarte bun format pentru documentele Internet și Web. Primele specificații de bază ale Web-ului au fost HTML, HTTP și URL. HTML a fost dezvoltat inițial de Tim Berners-Lee la CERN în 1989. HTML a fost văzut că o posibilitate pentru fizicienii care utilizează computere diferite și schimbă între ei informație utilizând Internetul. Erau prin urmare necesare câteva trăsături : independența de platformă, posibilități hypertext și structurarea documentelor. Independența de platformă înseamnă că un document poate fi afișat în mod asemănător de computere diferite ( deci cu fonte, grafica și culori diferite ), lucru vital pentru o audienta atât de variata. Hipertext înseamnă că orice cuvânt, frază, imagine sau alt element al documentului văzut de un utilizator (client) poate face referință la un alt document, ceea ce ușurează mult navigarea între multiple documente sau chiar în interiorul unui aceluiași document. Structurarea riguroasă a documentelor permite convertirea acestora dintr-un format în altul precum și interogarea unor baze de date formate din aceste documente

Orice document HTML începe cu notația <html> și se termină cu notația </html>. Aceste "chestii" se numesc în literatura de specialitate "TAG-uri". Prin convenție, toate informațiile HTML încep cu o paranteză unghiulară deschisă " < " și se termină cu o paranteză unghiulară închisă " > ".

Tag-urile între aceste paranteze transmit comenzi către browser pentru a afișa pagina într-un anumit mod. Unele blocuri prezintă delimitator de sfârșit de bloc, în timp ce pentru alte blocuri acest delimitator este opțional sau chiar interzis.

Serverul web Apache

Serverul de Web Apache sta la baza a peste 60% din domenii, potrivit unui studiu Netcraft Web Server. Providerii de Internet si companiile de gazduire de aplicatii pe Web apeleaza deseori la Apache din cauza suportului sau pentru numeroase platforme, capabilitatilor de gazduire virtuala usor de implementat si modulelor sale care ii extind capabilitatile.

Caracteristica Apache Portable Routine(APR) optimizeaza capabilitatile precum administrarea proceselor pentru fiecare sistem de operare, dar permite serverului propriu-zis sa ignore distinctiile specifice fiecarei platforme. Acest lucru a imbunatatit performanta si stabilitatea implementarilor Windows, prin eliminarea emulatorului. Mai mult APR este accesibil si dezvoltatorilor Web care scriu programe multi-platforme in C, care este mai rapid decit limbajele interpretative, precum PHP si Perl, folosite de obicei pentru dezvoltare Web.

La acest lucru se adauga faptul ca serverul propriu-zis este independent de protocoale. Cu toate ca este in principal un server HTTP(Web), este proiectat sa suporte alternative cum ar fi FTP. O astfel de structura simplifica administrarea si reduce riscurile de securitate. O parte insemnata din atractivitatea Apache o constituie versabilitatea sa. API-ul sau deschis a permis dezvoltatorilor sa scrie diferite module care i-au schimbat comportamentul. Daca serverului ii lipseste o functie de care are nevoie un sit, sunt mari sanse ca undeva sa fie disponibil un modul plug-in.

Serverele de Web au ca functionalitate de baza receptionarea de cereri anonime de la clienti si furnizarea de informatii intr-o maniera dorita a fi eficienta si rapida. De fapt un server Web este un daemon care accepta conexiuni conforme protocolului HTTP, raspunzind cererilor receptionate de la clienti. Pentru a asigura servicii HTTP, serverul Apache trebuie sa fie instalat in sistem(in mod uzual, fiind vorba de un pachet RPM in Linux sau de un program executabil .exe in Windows), iar daemon-ul httpd pornit. Apache este un sistem modular, alcatuit dintr-un server de baza si mai multe module care sunt incarcate dinamic intr-un mod similar cu functionarea modulelor din nucleul Linux.

Apache poate fi configurat cu ajutorul interfetei grafice apacheconf(Apache Configuration Tool). Fisierul de configurare principal este http-conf si este de obicei localizat in directorul /etc/httpd (in versiunile de Linux sau Unix).

In anumite cazuri, este necesar sa se restrictioneze accesul la anumite documente, prin intermediul autentificarii prin nume de utilizator si parola sau in functie de adresa calculatorului clientului Web.

Pentru autentificarea utilizatorilor, vom parcurge doi pasi:

Se creeaza un fisier continind numele si parolele utilizatorilor care vor avea acces la anumite date de pe serverul Web(in particular Apache)

Se configureaza serverul pentru a seta care resurse vor fi protejate si care sunt utilizatorii avind permisiunea accesarii lor, dupa introducerea unei parole valide

Configurarea serverului se poate realiza fie prin fisierul httpd-conf, fie prin .htacces, indicind o zona protejata, de obicei in functie de directoarele dorite a fi accesate pe baza de autentificare. Fisierul .htaccess va fi stocat in directorul asupra caruia dorim sa modificam comportamentul implicit al serverului Web. Inainte de a modifica maniera de autentificare din fisierul .htaccess, administratorul serverului Apache va specifica in httpd.conf ca autentificarile sa se realizeze via .htaccess.

De asemenea, Apache ofera posibilitatea de a servi mai multe site – uri Web simultan, altfel spus, gazduire virtuala(virtual hosting). Exista doua metode de implementare a gazduirii virtuale: prima bazata pe nume si a doua bazata pe adrese IP. Masinile virtuale bazate pe adresa utilizeaza adresa IP a conexiunii pentru a determina masina virtuala corecta. Astfel pentru fiecare gazduire virtuala bazata pe nume, determinarea masinii virtuale se face pe baza numelui acestuia.

Gazduirea virtuala bazata pe nume este mai simplu de implementat, si este recomandata utilizarea acesteia. Pentru a utiliza serviciul de gazduire virtuala, trebuie mai intii stabilite adresa IP si portul pentru serverul care va accepta cereri pentru respectiva masina virtuala.

DESCRIEREA APLICAȚIEI

Aplicația iHealth își propune să îmbunatățească eficiența operațională a actului medical prin diferite servicii puse la dispoziția tuturor persoanelor care interacționează direct sau indirect într-un centru medical de diagnostic și/sau tratament.

Necesitatea unei astfel de aplicații web pornește de la idea că medicina modernă presupune și o schimbare a mentalității atât a pacienților, în ceea ce privește propria sănătate, dar și a personalului medical în asigurarea unui relații medic-pacient mult mai strânsă și menținută în timp real si accesibilă de oriunde.

Principalele atuuri pe care o aplicatie de genul iHealth sunt următoarele:

fluidizarea și îmbunătățirea fluxului de lucru

achizitonarea și gestionarea unui volum ridicat de date medicale despre pacienți

eliminarea ”obstacolului” fizic din interiorul organizației

punerea la dispoziția personalului medical de informații în timp real despre datele medicale ale pacientului

asigurarea unei securități sporite a informației

Într-un mediu economic deosebit de dinamic, prezența pe internet este o necesitate, o aplicație de genul iHealth îmbunătățește imaginea firmei și astfel poate atrage mai mulți clienți. Pe lângă necesitate, aplicația iHealth mai vine cu o calitate, și anume simplitate dispunând de o interfață intuitive și ușor de folosit de absolut orice persoana. Pe lângă acest lucru, interfața aplicației este una responsive și se adaptează dispozitivului de pe care aplicația este accesată. Astfel in interiroul unei clinici, se poate renunța la banalul PC, prin inlocuirea s-a, de ce nu, cu o tabletă, astfel încât răspunsul și actualizarea datelor să se facă pe măsura ce pacientul este sub control.

Obtinerea unei interfete intuitive se realizeaza prin integrarea naturala a elementelor de raportare, analiza si monitorizare a performantelor activitatilor. De asemenea, prezentand o arhitectura scalabila si o singura metadata, utilizatorii pot naviga cu usurinta de la meniuri si tabele de performanta catre rapoarte si analize fara a fi nevoiti sa foloseasca o multitudine de instrumente si sa interactioneze cu diverse interfete.

Din punctul de vedere al unui utlizator, consumul de resurse al aplicației este insesizabil, tot ceea ce se înseamnă procesarea datelor este facută de serverul Web. Această aplicație putând fi accesată de pe orice browser.

Aplicația iHealth este un produs software accesibil oricarei categorii de utilizatori ai unui calculator. Totusi, avand in vedere complexitatea aplicatiei, este necesara realizarea unor interfete dedicate in functie de rolul utilizatorului, astfel aceasta va fi structurată în patru module diferite. În urma acestor patru secțiuni s-au definit și patru tipuri de acces în aplicație

Modulul Administrator – oferă interfețe de modificare sau adaugare a tuturor datelor gestionate de aplicație. Este modulul oferit pentru persoanele cu care de obicei un pacient interacționează prima dată într-o clinică. Aceasta poate sa adauge pacienți , programări și poate printa facutrile generate automat dupa finalizarea unei consultații.

Modulul Medic – este modulul doctorilor, în care aceștia își pot vedea sau adăuga programări, pot evalua pacienții sau își pot adăuga specializări

Modulul Laborator – este oferit doar pentru partea de analize de laborator, astfel încât operatorii din laboratorul clinicii să poată sa vadă analize cerute și sa le evalueze corespunzător.

Figura – Fluxul aplicației iHealth – adăugare programare

Baza de date

Baza de date a aplicației iHealth este dezvoltată pe un server de MySQL și conține 18 tabele a căror structură si funcționalitate este descrisă mai jos. O să se observe că toate tabelele precum și denumirea coloanelor sunt în limba engleză deoarece trăim într-un mediu dinamic, iar structura bazei trebuie să fie înțeleasă de orice. Pe lângă această generalitate, toate tabelele dispun de coloanele status, added(data în care inregistrarea a fost modifică) și modified(data la care s-a facut ultima modifcare pe linia respectivă), aceste coloane au fost adăugate, în primul rând pentru a menține un istoric pentru înregistrările respective dar și pentru a standardiza baza de date.

Figura – Diagrama bazei de date iHealth

Tabelul application_settings – are rolul de a păstra setările generale are aplicației. Cum ar fi denumirea societății, adresa etc. Aceste date nu pot fi șterse, pot fi doar modificate doar de utilizatori din modulul de administrare.

Tabelul – Tabelul application_settings

Tabelul doctors – reține toate datele despre doctorii din aplicatie. De asemenea acest tabel realizează legătura dintre doctori și utilizatorii cu care un doctor se va autentifica in aplicație. Această legătură este tipul one-to-one.

Tabelul – Tabelul doctors

Tabelul doctors_consultations – În acest tabel se salvează informațiile despre tipurile de consulații din aplicație cum ar fi: specialitate, doctor, preț, durată estimată. Acest tabel se leagă atât de tabelul de specializări, cât și de cel de doctori. Ambele legături sunt de tipul many-to-one, atfel un doctor poate avea una sau mai multe tipuri de consulații.

Tabelul – Tabelul doctors_consultations

Tabelul specialities – conține date generale despre specializările administrate în aplicație. Acest tabel este folosit pentru gestionarea mai rapidă a tipurilor de consultații ce se pot împărți diferit pe fiecare specializare în parte.

Tabelul – Tabelul specialities

Tabelul invoices – în acest tabel se salveaza datele principale ale unei facturi, cum ar fi: seria și numărul ei, data facturării, numele și datele personale ale pacientului, precum si totalurile, cu și fără TVA ale facturii.

Tabelul – Tabelul invoices

Tabelul invoices_lines – în acest tabel practic se regăsește conținutul facturii, fiecare linie a unei facturi va avea corespondentă o înregistrare in acest tabel. Are legatura de tip many-to-one cu tabelul de facturi

Tabelul – Tabelul invoices_lines

Tabelul laboratory_analysis – în acest tabel se vor ține datele despre tipurile de analize ce pot fi efectuate de laborator.

Tabelul – Tabelul laboratory_analysis

Tabelul laboratory_analysis_schedule – acest tabel este folosit pentru a programa o serie de analize pentru laboratorul clinicii. Are legătura de tipul many-to-many cu tabelul de pacienți.

Tabelul – Tabelul laboratory_analysis_schedule

Tabelul laboratory_analysis_schedule_details – în acest tabel vom salva date despre ce analize se vor face în urma programării la laborator.

Tabelul – Tabelul laboratory_analysis_schedule_details

Tabelul patients – folosim acest tabel pentru a tine datele principale despre un pacient. Acest tabel este printre cele mai importante din structura bazei de date, având legaturi multiple cu majoritatea tabelelor existente.

Tabelul – Tabelul patients

Tabelul patients_addresses – în acest tabel vom tine datele de contact pentru un pacient. Este nevoie sa dăm posibilitatea unui pacient să își poată adăuga mai multe adrese.

Tabelul – Tabelul patients_addresses

Tabelul patients_appointments – acest tabel va reține principale date despre programările unui pacient: zi, ora de început și de sfârșit. Acest tabel contine legături de tipul many-to-one catre tabelele de doctori și pacienți.

Tabelul – Tabelul patients_appointments

Tabelul patients_appointments_consultations – pentru o programare un doctor poate efectua mai multe consultații, pentru asta am construit acest tabel, care va conține date detaliate despre operațiile facute de doctor în timpul unei programări. Acest tabel este folosit si la generarea facturii către client.

Tabelul – Tabelul patients_appointments_consultations

Tabelul patients_fidelity_cards – Reține datele despre cardurile de fidelitate oferite clienților clinicii.

Tabelul – Tabelul patients_fidelity_cards

Tabelul users – În acest tabel salvăm toate datele necesare autentificării în aplicație. Există trei tipuri de utilizatori: admin, doctor și user laborator. Pentru doctori utilizatorul se genereaza automat la adăugarea unei noi înregistrări, în schimb pentru celelalte tipuri de utilizatori este necesară adăugarea manuală.

Tabelul – Tabelul users

MANUALUL DE UTILIZARE

Modulul de administrare

Logarea

Logarea în aplicație în modulul de administrare se va face pe baza unui user și o parolă unică.

Figura – Logarea în aplicație ca administrator

Acest modul va fi accesat doar de persoane autorizate pentru gestionarea tuturor datelor din aplicație:

Adăugarea pacienților în baza de date a clinicii

Editarea datelor fiecărui pacient în parte

Programarea pacienților la laboratorul de analize

Programarea pacienților în funcție de orarul fiecărui doctor de specializare și de necesităti

Adăugarea doctorilor și specializărilor

Crearea conturilor de acces ale doctorilor

Adăugarea tipurilor de analize cerute

Editarea și ștergerea conturilor de acces ale fiecărui doctor

Adăugarea consultațiilor

Figura – Validarea unui user înainte de autentificare

Gestionarea autentificării utilizatorilor se face in clasa: UserService care este exemplificată mai jos:

class UserService extends BaseService
{
const SERVICE_NAME = 'ihealth.user_service';

protected $sendConfirmationMail;

public function doLogin(Users $user)
{
$session = $this->getSession();
$session->set('user_logged_in', true);
$session->set('username', $user->getUsername());
$session->set('userToken', md5($user->getUsername() . "051715"));
}

public function doLogout()
{
$this->getSession()->remove('user_logged_in');
$this->getSession()->remove('username');
$this->getSession()->remove('userToken');
}

public function checkLogin()
{
if ($this->getSession()->get('user_logged_in')) {
if ($this->getSession()->get('userToken') == md5($this->getSession()->get('username') . "051715")) {
return true;
}
}

return false;
}

public function checkUsername($username)
{
$user = $this->getEntityManager()->getRepository('HealthBaseBundle:Users')->findOneByUsername($username);

if ($user instanceof Users) {
throw new \Exception($this->getTranslator()->trans('user_errors.existent_username'));
}
}

public function checkEmailAddress($emailAddress)
{
$user = $this->getEntityManager()->getRepository('HealthBaseBundle:Users')->findOneByEmail($emailAddress);

if ($user instanceof Users) {
throw new \Exception($this->getTranslator()->trans('user_errors.existent_email'));
}
}

protected function checkPasswords($password, $confirmPassword)
{
if ($password != $confirmPassword) {
throw new \Exception($this->getTranslator()->trans('user_errors.passwords_not_match'));
}
}

public function checkLoginData($formData)
{
if (array_key_exists('username', $formData) && (array_key_exists('password', $formData))) {
/** @var User $user */
$user = $this->getEntityManager()->getRepository('HealthBaseBundle:Users')->findOneBy(
array(
'username' => $formData['username'],
'password' => md5($formData['password'])
)
);

if ($user instanceof Users) {
$this->doLogin($user);

return true;
}

throw new \Exception($this->getTranslator()->trans('login_form.invalid_credentials'));
}

throw new \Exception($this->getTranslator()->trans('login_form.unknown_error'));

}

/**
* @param $requiredTypes
* @return bool
*/
public function hasRequiredPermissions($requiredTypes)
{
if (!is_array($requiredTypes)) {
$requiredTypes = array($requiredTypes);
}

$session = $this->getSession();

/** @var Users $user */
$user = $this->getEntityManager()->getRepository('HealthBaseBundle:Users')->findOneBy(
array(
'username' => $session->get('username')
)
);

if ($user instanceof Users) {
if (in_array($user->getUserType(), $requiredTypes) || $user->getUserType() == Users::TYPE_ADMIN) {
return true;
}
}

return false;
}
}

Meniu

Meniul aplicației cuprinde:

Pacienți

Analize

Doctori

Setări

Figura – Meniul aplicației din punctul de vedere al admin-ului

Contrucția meniului este realizată de următoarea secvență de cod:

<p class="menu-title">Cauta <span class="pull-right"><a href="javascript:;"><i class="fa fa-refresh"></i></a></span></p>
<ul>
{% if userType == 1 %}
<li class="start active "> <a href="{{ url('health_base_homepage') }}"> <i class="icon-custom-home"></i>
<span class="title">iHealth</span> <span class="selected"></span></a> </li>
<li class=""> <a href="javascript:;"> <i class="fa fa fa-adjust"></i> <span class="title">{{ 'menu.patients' | trans }}</span> <span class="arrow "></span> </a>
<ul class="sub-menu">
<li > <a href="{{ url('patients_index') }}">{{ 'menu.patients_lists' | trans }} </a> </li>
<li > <a href="{{ url('patientsappointments_index') }}">{{ 'menu.patients_appointments' | trans }} </a> </li>
<li > <a href="{{ url('patientsfidelitycards_index') }}">{{ 'menu.patients_fidelitycards' | trans }} </a> </li>
</ul>
</li>

<li class=""> <a href="javascript:;"> <i class="fa fa fa-adjust"></i> <span class="title">{{ 'menu.analysis' | trans }}</span> <span class="arrow "></span> </a>
<ul class="sub-menu">
<li > <a href="{{ url('laboratoryanalysis_index') }}">{{ 'menu.analysis_index' | trans }} </a> </li>
<li > <a href="{{ url('laboratoryanalysisschedule_index') }}">{{ 'menu.analysis_schedule' | trans }} </a> </li>
</ul>
</li>

<li class=""> <a href="javascript:;"> <i class="fa fa fa-adjust"></i> <span class="title">{{ 'menu.doctors' | trans }}</span> <span class="arrow "></span> </a>
<ul class="sub-menu">
<li > <a href="{{ url('doctors_index') }}">{{ 'menu.doctors_list' | trans }} </a> </li>
<li > <a href="{{ url('doctorsconsultations_index') }}">{{ 'menu.doctors_consultations' | trans }}</a> </li>
</ul>
</li>

<li class=""> <a href="javascript:;"> <i class="fa fa fa-adjust"></i> <span class="title">{{ 'menu.settings' | trans }}</span> <span class="arrow "></span> </a>
<ul class="sub-menu">
<li class=""> <a href="{{ url('specialities_index') }}">{{ 'menu.specialities' | trans }}</a> </li>
<li class=""> <a href="{{ url('users_index') }}">{{ 'menu.users' | trans }}</a> </li>
</ul>
</li>
{% elseif userType == 2 %}
{% elseif userType == 3 %}
<li > <a href="{{ url('doctors_my_appointments') }}"> <i class="fa fa-th"></i> <span class="title">Programarile mele</span></a> </li>
<li > <a href="{{ url('doctorsconsultations_doctor') }}"> <i class="fa fa-th"></i> <span class="title">Consultatiile mele</span></a> </li>
{% elseif userType == 4 %}
<li > <a href="{{ url('laboratoryanalysisschedule_index_lab') }}"> <i class="fa fa-th"></i> <span class="title">Analize programate</span></a> </li>
<li > <a href="{{ url('laboratoryanalysis_index') }}">{{ 'menu.analysis_index' | trans }} </a> </li>
{% else %}
{% endif %}
</ul>

Pacienți

Secțiunea Pacienți curpinde trei submeniuni:

Listă

Programări

Carduri pacienți

Figura – Secțiunea pacienți

Submeniul Listă

Aici adminul poate vizualiza lista pacienților adăugati în aplicație. Tot aici se va face căutarea în funcție de:

Nume și Prenume

CNP

Se vor completa field-urile dorite după care se face căutarea (Nume și Prenume, CNP sau ambele) și se va apasă butonul Caută.

Figura – Butonul de căutare al pacienților în listă

În listă se vor afișa doar pacienții care îndeplinesc cerințele căutării.

Figura – Listă pacienți

Listarea pacienților se face cu ajutorul următoarei secvențe de cod:

{% extends 'DacsoftUiBundle:Default:base-list.html.twig' %}

{% block breadcrumb %}{{ "pages.patients.list.breadcrump" | trans }}{% endblock%}

{% block pageTitle %}{{ "pages.patients.list.title" | trans }} {% endblock %}

{% block gridTitle %}{{ "pages.patients.list.title" | trans }} {% endblock %}

{% block gridActions %}
<a href="{{ path('patients_new') }}" class="btn btn-small btn-primary"><i
class="fa fa-plus"></i>&nbsp;
{{ 'buttons.add' | trans }} </a>
{% endblock %}

{% block gridForm %}
<div class="row">
<div class="col-md-8 col-sm-8 col-xs-8">
<div class="form-group">
<label class="form-label">{{ 'forms.patients.name' | trans }}</label>
<div class="controls">
<input type="text" class="form-control" id="patientName" name="patientName"/>
</div>
</div>

</div>
</div>
<div class="row">
<div class="col-md-8 col-sm-8 col-xs-8">
<div class="form-group">
<label class="form-label">{{ 'forms.patients.identification_code' | trans }}</label>
<div class="controls">
<input type="text" class="form-control" id="identificationCode" name="identificationCode"/>
</div>
</div>

</div>
</div>
{% endblock %}

{% block gridTable %}
<table class="table table-striped table-hover dataTable" id="grid-table">
<thead>
<tr>
<th style="width:1%">Id</th>
<th>{{ "grids.patients.name" | trans }}</th>
<th>{{ "grids.patients.identificationcode"| trans }}</th>
<th>{{ "grids.patients.phonenumber"| trans }}</th>
<th style="width:5%">Actiuni</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
{% endblock %}

{% block gridScripts %}
<script>
function drawTable(url) {
var $customDataTableSettings = {
"sAjaxSource": url,
"aoColumns": [
{"mData": "id", "sortable": false, "width": "10px"}, {
"mData": "name",
"sortable": false,
"width": "10px"
}, {
"mData": "identificationCode",
"sortable": false,
"width": "10px"
},
{
"mData": "phoneNumber",
"sortable": false,
"width": "10px"
}, {
"mData": null,
"sortable": false,
"sClass": "center",
"width": "10%"
},
],
"aoColumnDefs": [
{
"aTargets": [4],
"mRender": function (data, type, full) {
var deleteButton = "<a id='delete-button' data-object-id = '" + full.id + "' title='"
+ 'Sterge'
+ "' class='red btn-link'><i class='fa fa-trash-o'></i></a>";
var viewButton = "<a id='view-button' data-object-id = '" + full.id + "' title='"
+ 'View'
+ "' class='red btn-link'><i class='fa fa-search'></i></a>";

return viewButton + " " + deleteButton;

}
}
]
};

$.extend($defaultGridSettings, $customDataTableSettings);
$('#grid-table').dataTable($defaultGridSettings);
}

$(document).ready(function () {
var table = $("#grid-table").DataTable();
drawTable("{{ path('patients_list_ajax') }}");

$('#grid-table tbody').on('click', 'a#view-button', function () {
var objectId = $(this).data("objectId");
window.location.href = Routing.generate('patients_show', {patientId: objectId}, true);

return false;
});

$('#grid-table tbody').on('click', 'a#delete-button', function () {
var objectId = $(this).data("objectId");
deleteObjects(objectId);
});

function deleteObjects(objectId) {
var objectIds = JSON.stringify(objectId);
drawTable("{{ path('patients_delete_ajax') }}?object=" + objectIds);
}

$("#search-form").submit(function (event) {
event.preventDefault();
var formData = $("#search-form").serialize();
var url = "{{ url('patients_list_ajax') }}?" + formData;
drawTable(url);

});
});
</script>

{% endblock %}

Adăugarea pacienților în listă se va face foarte simplu, doar apăsând butonul verde din dreapta sus

Figura – Butonul de adăugare al unui pacient în baza de date

Pentru a adăuga un pacient în program, este necesară completarea unui formular cu datele personale ale sale:

Nume și Prenume

Sex

CNP

Serie buletin

Nume buletin

Numărul de telefon

Figura – Detalii pacient nou

După ce au fost completate datele, acestea vor fi salvate apăsând butonul albastru Salvează

Figura – Butonul de salvare al datelor pacienților

Formularul de adăugare pacienți este realizat cu ajutorul următorului cod:

class PatientsType extends AbstractType
{
protected $source;

/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add(
'name',
TextType::class,
array(
'label' => 'forms.patients.fields.name',
'help' => 'forms.patients.help.name',
'attr' => array(
)
)
)->add(
'sex',
ChoiceType::class,
array(
'label' => 'forms.patients.fields.sex',
'choices' => array(
'Feminin' => "F",
'Masculin' => "M",
),
'attr' => array(
)
)
)->add(
'identificationCode',
TextType::class,
array(
'label' => 'forms.patients.fields.identificationcode',
'help' => 'forms.patients.help.identificationcode',
'attr' => array(
)
)
)->add(
'identityCardSeries',
TextType::class,
array(
'label' => 'forms.patients.fields.identitycardseries',
'help' => 'forms.patients.help.identitycardseries',
'attr' => array(
)
)
)->add(
'identityCardNumber',
TextType::class,
array(
'label' => 'forms.patients.fields.identitycardnumber',
'help' => 'forms.patients.help.identitycardnumber',
'attr' => array(
)
)
)->add(
'phoneNumber',
TextType::class,
array(
'label' => 'forms.patients.fields.phonenumber',
'help' => 'forms.patients.help.phonenumber',
'attr' => array(
)
)
);
}

/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{

$resolver->setDefaults(array(
'data_class' => 'Health\BaseBundle\Entity\Patients'
));
}
}

Submeniul Carduri pacienți

În această secțiune, în funcție de fidelitatea pacienților la clinică, se pot oferi carduri de reducere. Aceastea se pot folosi la aplicarea discounturilor în diferite situații.

Pentru a găsi mai ușor un card de reducere, se pot folosi filtrele de căutare. Căutarea se poate face în funcție de nume, prenume, seria cardului sau numărul de telefon

Figura – Butonul pentru căutarea cardurilor

Figura 15 – Lista cardurilor pacienților

Adăugarea unui card se va face apăsând butonul “Adauga”

Figura – Butonul de adăugare al unui card nou

După apăsarea acestui buton se completează câmpurile necesare:

Se selectează din listă numele pacientului

Se completează seria cardului

Se completează numărul cardului

Se apăsa butonul salvează

Figura – Butonul de salvare al cardului pacientului

Figura – Detalii card pacient

Submeniul Programări

Adminul poate programa pacienții pentru o consultație la un anumit doctor. În această parte a aplicației, se face afișarea tuturor programărilor pacienților la medici în funcție de specializare, data programată și oră. Căutarea se face în funcție de numele și prenumele pacientului numărul de telefon și data la care a fost programat. După completarea acestor date se apăsa butonul Caută iar programul va afișa toate programările în funcție de datele cerute .

Figura – Butonul pentru căutarea programărilor

Figura – Afișarea tuturor programărilor

Interfața de căutare a programărilor este realizată cu ajutorul următoarei secvențe de cod:

{% extends 'DacsoftUiBundle:Default:base-list.html.twig' %}

{% block breadcrumb %} {{ "pages.doctors.list.breadcrump" | trans }} {% endblock %}

{% block pageTitle %}{{ "pages.doctors.list.title" | trans }} {% endblock %}

{% block gridTitle %}{{ "pages.doctors.list.title" | trans }} {% endblock %}

{% block gridActions %}
<a href="{{ path('doctors_new') }}" class="btn btn-small btn-primary"><i
class="fa fa-plus"></i>&nbsp;
{{ 'buttons.add' | trans }} </a>
{% endblock %}

{% block gridForm %}
<div class="row">
<div class="col-md-8 col-sm-8 col-xs-8">
<div class="form-group">
<label class="form-label">{{ 'forms.doctors.name' | trans }}</label>
<div class="controls">
<input type="text" class="form-control" id="name" name="name"/>
</div>
</div>

</div>
</div>

<div class="row">
<div class="col-md-8 col-sm-8 col-xs-8">
<div class="form-group">
<label class="form-label">{{ 'forms.doctors.email' | trans }}</label>
<div class="controls">
<input type="text" class="form-control" id="email" name="email"/>
</div>
</div>

</div>
</div>

<div class="row">
<div class="col-md-8 col-sm-8 col-xs-8">
<div class="form-group">
<label class="form-label">{{ 'forms.doctors.phone' | trans }}</label>
<div class="controls">
<input type="text" class="form-control" id="phone" name="phone"/>
</div>
</div>

</div>
</div>

{% endblock %}

{% block gridTable %}
<table class="table table-striped table-hover dataTable" id="grid-table">
<thead>
<tr>
<th style="width:1%">Id</th>
<th>{{ "grids.doctors.name" | trans }}</th>
<th>{{ "grids.doctors.emailAddress" | trans }}</th>
<th>{{ "grids.doctors.phone"| trans }}</th>
<th>Specializare</th>
<th>Cabinet</th>
<th style="width:5%">Actiuni</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
{% endblock %}

{% block gridScripts %}
<script>
function drawTable(url) {
var $customDataTableSettings = {
"sAjaxSource": url,
"aoColumns": [
{"mData": "id", "sortable": false, "width": "10px"}, {
"mData": "name",
"sortable": false,
"width": "10px"
},
{
"mData": "emailAddress",
"sortable": false,
"width": "10px"
},

{
"mData": "phone",
"sortable": false,
"width": "10px"
},
{
"mData": "speciality",
"sortable": false,
"width": "10px"
},
{"mData": "cabinet", "sortable": false, "width": "10px"},
{
"mData": null,
"sortable": false,
"sClass": "center",
"width": "10%"
},
],
"aoColumnDefs": [
{
"aTargets": [1],
"mRender": function (data, type, full) {
return "<a id='edit-button' data-object-id = '" + full.id + "'>" + data + "</a>"
}
},
{
"aTargets": [6],
"mRender": function (data, type, full) {
return "<a id='delete-button' data-object-id = '" + full.id + "' title='"
+ 'Sterge'
+ "' class='red btn-link'><i class='fa fa-trash-o'></i></a>"

}
}
]
};

$.extend($defaultGridSettings, $customDataTableSettings);
$('#grid-table').dataTable($defaultGridSettings);
}

$(document).ready(function () {
var table = $("#grid-table").DataTable();
drawTable("{{ path('doctors_list_ajax') }}");

$('#grid-table tbody').on('click', 'a#edit-button', function () {
var objectId = $(this).data("objectId");
window.location.href = Routing.generate('doctors_edit', {id: objectId}, true);

return false;
});

$('#grid-table tbody').on('click', 'a#delete-button', function () {
var objectId = $(this).data("objectId");
deleteObjects(objectId);
});

function deleteObjects(objectId) {
var objectIds = JSON.stringify(objectId);
drawTable("{{ path('doctors_delete_ajax') }}?object=" + objectIds);
}

$("#search-form").submit(function (event) {
event.preventDefault();
var formData = $("#search-form").serialize();
var url = "{{ url('doctors_list_ajax') }}?" + formData;
drawTable(url);

});
});
</script>

{% endblock %}

Pentru adăugarea unei noi programări, adminul trebuie să apese butonul Adaugă apoi să urmeze pașii de mai jos:

se selectează pacientul

se alege specializarea

se alege doctorul la care se dorește programarea

se alege data programării

se alege intervalul orar(data de început și data de sfârșit)

dacă este nevoie se scriu eventuale observării ale programării

se apasă butonul Salvează

Figura – Butonul de salvare al programărilor pacienților

Figura – Adăugarea unei noi programări

Procesarea unei programări, precum și validarea acesteia se realizeaza cu următorul cod:

public function buildForm(FormBuilderInterface $builder, array $options)
{

$builder
->add(
'patient',
EntityType::class,
array(
'class' => 'Health\BaseBundle\Entity\Patients',
'label' => 'forms.patientsappointments.fields.patient',
'attr' => array(
'class' => 'col-md-12 no-padding'
)
)
)
->add(
'speciality',
EntityType::class,
array(
'class' => 'Health\BaseBundle\Entity\Specialities',
'label' => 'forms.patientsappointments.fields.speciality',
'attr' => array(
'class' => 'col-md-12 no-padding',
'onchange' => 'getDoctors();',
)
)
)
->add(
'appointmentDoctorId',
ChoiceType::class,
array(
'label' => 'forms.patientsappointments.fields.doctors',
'attr' => array(
'class' => 'col-md-12 no-padding',
'required' => true
),
)
)
->add(
'date',
DatePickerType::class,
array(
'label' => 'forms.patientsappointments.fields.date',
)
)->add(
'startHour',
TimePickerType::class,
array(
'label' => 'forms.patientsappointments.fields.startHour',
)
)->add(
'endHour',
TimePickerType::class,
array(
'label' => 'forms.patientsappointments.fields.endHour',
)
)
->add(
'description',
TextType::class,
array(
'label' => 'forms.patientsappointments.fields.description',
'required' => false
)
);
$builder->get('appointmentDoctorId')->resetViewTransformers();
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
$formData = $event->getData();
if (isset($formData['date'])) {
$date = explode(".",$formData['date']);
$formData['date'] = array(
'year' => intval($date['2']),
'month' => intval($date['1']),
'day' => intval($date['0']),
);

$startTime = explode(":",$formData['startHour']);
$formData['startHour'] = array(
'hour' => intval($startTime['0']),
'minute' => intval($startTime['1']),
);

$endTime = explode(":",$formData['endHour']);
$formData['endHour'] = array(
'hour' => intval($endTime['0']),
'minute' => intval($endTime['1']),
);
$event->setData($formData);
}
});
}

public function newAction(Request $request)
{
/** @var UserService $userService */
$userService = $this->get(UserService::SERVICE_NAME);

if (!$userService->hasRequiredPermissions(Users::TYPE_ADMIN)) {
return $this->render('@DacsoftUi/common/access_denied.html.twig');
}

$patientsAppointment = new PatientsAppointments();
$form = $this->createForm('Health\BaseBundle\Form\PatientsAppointmentsType', $patientsAppointment);
$form->handleRequest($request);

if ($form->isSubmitted() && $form->isValid()) {
$doctor = $this->getDoctrine()->getRepository('HealthBaseBundle:Doctors')->find($patientsAppointment->getAppointmentDoctorId());
$patientsAppointment->setDoctor($doctor);
$em = $this->getDoctrine()->getManager();
$em->persist($patientsAppointment);
$em->flush();

$translator = $this->get('translator');
$this->get('session')->getFlashBag()->add('success', $translator->trans('message.add.content'));

return $this->redirectToRoute('patientsappointments_index');
}
return $this->render('@HealthBase/patientsappointments/new.html.twig', array(
'patientsAppointment' => $patientsAppointment,
'form' => $form->createView(),
));
}

Analize

Această secțiune de analize cuprinde două submeniuri:

Tipuri analize

Programări analize

Figura – Secțiunea Analize

Submeniul Tipuri analize

Adminul are dreptul de a vizualiza lista tuturor analizelor adăugate în aplicație. Căutarea lor se va face în funcție de denumire. În lista se vor afișa toate analizele care îndeplinesc criteriile căutării.

Figura – Afișarea tuturor analizelor inserate în program

Adăugarea se va face apăsând butonul Adaugă, după care se va completea denumirea analizei și costul în lei al acesteia. După completarea acestor câmpuri, apăsarea butonului Salvează va permite salvarea în program a datelor.

Figura – Adăugarea analizelor

Submeniul Programări Analize

Fiecare pacient va fi programat pentru efectuarea analizelor cerute. În această interfață se va afișa lista tuturor datelor despre programări (un id unic, codul analizei, numele și prenumele pacientului și tipul de analiză efectuat). Căutarea se va face în baza codului de programare, al tipului analizei precum și al numelui și prenumelui pacientului. După completarea acestor date, se va apăsa butonul Caută iar în lista vor apărea toate datele care îndeplinesc criteriile de căutare cerute.

Figura – Listare programări analize

Adăugarea unei programări la analize se va face apăsând butonul Adaugă din stânga sus. Pentru această programare vom avea nevoie de numele pacientului, care se va selecta din drop-down, tipul de analiză care se vrea și data la care a fost programat pacientul pentru efectuarea analizei.

După ce s-au completat aceste câmpuri se va apăsa butonul Salvează iar pacientului i se va asigura automat o programare la laboratorul de analiză pentru efectuarea sa.

Figura – Adaugă programare nouă

Doctori

Secțiunea Doctori cuprinde două submeniuri

Listă

Tipuri de consultații

Figura – Secțiunea Doctori

Submeniul Lista

Aici, adminul poate vedea lista tuturor doctorilor din aplicație precum și informații despre aceștia (numărul de telefon, numele și prenumele, cabinetul si specializarea)

Figura – Afișarea tuturor doctorilor introduși în program

Doctorii se pot filtra după nume și prenume, adresa de email și nr de telefon. După completarea acestor câmpuri se apasă butonul Caută, iar filtrarea se va face în funcție de cerințele introduse

Figura – Butonul de căutare al doctorilor în listă

Funcția de căutare a doctorilor se realizează astfel:

public function getAjaxListDoctors(Request $request, $repository)
{
$filters = $request->query->all();

list($data,$recordCount) = $repository
->getDataByFilters($filters);

$data = $this->formatData($data, $recordCount, $request->get('iDisplayLength'), $request->get('iDisplayStart'));
$doctors = $data['aaData'];

$doctorSpecialityRepository = $this->getEntityManager()->getRepository('HealthBaseBundle:DoctorsSpecialities');

foreach ($doctors as &$doctor) {

$doctorSpecialities = $doctorSpecialityRepository->getDoctorSpecialities($doctor['id']);
$specialities = array();
foreach ($doctorSpecialities as $speciality) {
$specialities[] = $speciality['name'];
}

$doctor['speciality'] = implode(',', $specialities);
}

$data['aaData'] = $doctors;

return $data;
}

protected function mapSearchFields($filters)
{
$filterFields = array();

foreach ($filters as $searchKey => $searchValue) {
if (!is_null($searchValue) && strlen($searchValue)) {
switch ($searchKey) {
case 'name':
$filterFields[$searchKey] = array(
'searchKey' => 'entity.name',
'searchValue' => $searchValue,
'operation' => self::LIKE_OPERATION
);
break;
case 'phone':
$filterFields[$searchKey] = array(
'searchKey' => 'entity.phone',
'searchValue' => $searchValue,
'operation' => self::LIKE_OPERATION
);
break;
case 'email':
$filterFields[$searchKey] = array(
'searchKey' => 'entity.email',
'searchValue' => $searchValue,
'operation' => self::LIKE_OPERATION
);
break;
}
}
}

return $filterFields;
}

Pentru adăugarea unui doctor nou, se va apăsa butonul Adaugă.

Figura – Butonul de adăugare al unui doctor în baza de date

După apăsarea butonul de adăugare, se completează field-urile necesare pentru salvarea datelor unui doctor în program

Nume

Adresa de email

Nr cabinet

Nr de telefon

Figura – Adaugarea detelor unui doctor

Formularul de adăugare doctor este construit astfel:

class DoctorsType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$data =$options['data'];
$builder->add(
'name',
TextType::class,
array(
'label' => 'forms.doctors.fields.name',
'attr' => array(
)
)
)->add(
'emailAddress',
EmailType::class,
array(
'label' => 'forms.doctors.fields.emailaddress',
'attr' => array(
)
)
)->add(
'cabinet',
TextType::class,
array(
'label' => 'forms.doctors.fields.cabinet',
'attr' => array(
)
)
)
->add(
'phone',
TextType::class,
array(
'label' => 'forms.doctors.fields.phone',
'attr' => array(
)
)
)
->add(
'specialities',
EntityType::class,
array(
'class' => 'Health\BaseBundle\Entity\Specialities',
'multiple' => true,
'label' => 'forms.doctors.fields.specialities',
'attr' => array(
'class' => 'col-md-12 no-padding'
),
'data' => $data->getSpecialities(),
'required' => true
)
)
->add(
'username',
TextType::class,
array(
'label' => 'forms.doctors.fields.username',
'attr' => array(
'class' => 'col-md-12 no-padding'
),
'required' => true
)
)
->add(
'password',
PasswordType::class,
array(
'label' => 'forms.doctors.fields.password',
'attr' => array(
'class' => 'col-md-12 no-padding'
),
'required' => true
)
);
}

/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Health\BaseBundle\Entity\Doctors'
));
}
}

Se selectează din listă specializarea, se introduce un nume de utilizator și se setează o parolă unică.

Crearea și asocierea unui utilizator cu doctorul adăugat se realizează astfel:

public function newAction(Request $request)
{
/** @var UserService $userService */
$userService = $this->get(UserService::SERVICE_NAME);

if (!$userService->hasRequiredPermissions(Users::TYPE_ADMIN)) {
return $this->render('@DacsoftUi/common/access_denied.html.twig');
}

$doctor = new Doctors();
$form = $this->createForm('Health\BaseBundle\Form\DoctorsType', $doctor);
$form->handleRequest($request);

if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
try {
/** @var DoctorService $doctorService */
$doctorService = $this->get(DoctorService::SERVICE_NAME);
$doctorService->generateDoctorAccount($doctor);
$doctorService->addDoctorSpecialities($doctor);

$em->persist($doctor);
$em->flush();
$translator = $this->get('translator');
$this->get('session')->getFlashBag()->add('success', $translator->trans('message.add.content'));

return $this->redirectToRoute('doctors_index');
} catch (\Exception $e) {
$translator = $this->get('translator');
$this->get('session')->getFlashBag()->add('errors', $translator->trans($e->getMessage()));
}
}

return $this->render('@HealthBase/doctors/new.html.twig', array(
'doctor' => $doctor,
'form' => $form->createView(),
));
}

public function generateDoctorAccount(Doctors &$doctor)
{
$doctorUser = $doctor->getUser();

if ($doctorUser instanceof Users) {
return null;
}

$this->getUserService()->checkUsername($doctor->getUsername());
$this->getUserService()->checkEmailAddress($doctor->getEmailAddress());

$userAccount = new Users();
$userAccount
->setUsername($doctor->getUsername())
->setName($doctor->getName())
->setPassword($doctor->getPassword())
->setEmail($doctor->getEmailAddress())
->setUserType(3)
->setStatus(1);

$this->getEntityManager()->persist($userAccount);
$doctor->setUser($userAccount);
}

După toate aceste operațiuni, se apasă butonul Salvează iar datele doctorului respectiv vor fi adăugate în program și în baza de date

Submeniul Tipuri consultatii

Adminul poate vizualiza listă consultațiilor aferente fiecărui doctor. Filtrarea consultațiilor se face în funcție de numele și prenumele doctorului, de numele specializări și al consultației. După ce s-au completat câmpurile pentru filtrare se apasă butonul Caută iar în lista se vor afișa toate consultațiile care îndeplinesc cerințele.

Figura – Butonul de căutare al consultațiilor în listă

Figura – Afișarea consultațiilor

Figura – Butonul de adăugare al unei consultații în baza de date

Pentru adăugarea unei consultații noi se va apăsa butonul Adaugă iar apoi se vor urmării pașii de mai jos:

se alege numele doctorului

se alege tipul specializatii

se setează numele consultației

se setează un preț-acesta întotdeauna va fi în RON

se alege o durată estimată a consultației

se apasă butonul Salvează

Figura – Adăugarea unei noi consultații

Setari

Figura – Secțiunea Setari

Această secțiune cuprinde două submeniuri:

Specializări

Utilizatori interni

Specializări

În acest submeniu adminul poate adăuga o gamă largă a specializarilor doctorilor. Adăugarea se face apăsând butonul verde de adăugare și se completează numele specializarii iar apoi se Salvează prin apăsarea simplului buton verde cu acelasi nume.

Figura – Adăugarea unei noi specializări

Salvarea în baza de date a unei noi specializări este realizată cu următoarea secvență de cod:

/** @var UserService $userService */
$userService = $this->get(UserService::SERVICE_NAME);

if (!$userService->hasRequiredPermissions(Users::TYPE_ADMIN)) {
return $this->render('@DacsoftUi/common/access_denied.html.twig');
}

$speciality = new Specialities();
$form = $this->createForm('Health\BaseBundle\Form\SpecialitiesType', $speciality);
$form->handleRequest($request);

if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($speciality);
$em->flush();

$translator = $this->get('translator');
$this->get('session')->getFlashBag()->add('success', $translator->trans('message.add.content'));

return $this->redirectToRoute('specialities_index');
}

return $this->render('@HealthBase/specialities/new.html.twig', array(
'speciality' => $speciality,
'form' => $form->createView(),
));

Căutarea se face în funcție de numele specializarii, apăsând butonul roșu Caută, iar în listă se vor afișa toate specializările care îndeplinesc criteriile de căutare.

Figura – Lista specializărilor

Utilizatori interni

Acest submeniu permine vizualizarea tuturor utilizatorilor interni ai aplicației:

adminii

doctorii

laboratoarele de analize

Figura – Afișarea utilizatorilor interni

Căutarea se face în funcție de:

numele utilizatorului

username-ul

adresa de e-mail

tipul de utilizator (admin, doctor sau laborator)

statusul (activ sau inactiv)

După completarea câmpurilor dorite se apasă butonul Caută iar în listă se vor afișa doar acei utilizatori care îndeplinesc cerințele

Figura – Căutarea unui utilizator

Funcția de căutare este realizată de următorul cod:

protected function mapSearchFields($filters)
{
$filterFields = array();

foreach ($filters as $searchKey => $searchValue) {
if (!is_null($searchValue) && strlen($searchValue)) {
switch ($searchKey) {
case 'name':
$filterFields[$searchKey] = array(
'searchKey' => 'entity.name',
'searchValue' => $searchValue,
'operation' => self::LIKE_OPERATION
);
break;
case 'username':
$filterFields[$searchKey] = array(
'searchKey' => 'entity.username',
'searchValue' => $searchValue,
'operation' => self::LIKE_OPERATION
);
break;
case 'email':
$filterFields[$searchKey] = array(
'searchKey' => 'entity.email',
'searchValue' => $searchValue,
'operation' => self::LIKE_OPERATION
);
break;
case 'user_type':
$filterFields[$searchKey] = array(
'searchKey' => 'entity.userType',
'searchValue' => $searchValue,
'operation' => self::EQUAL_OPERATION
);
break;
case 'status':
$filterFields[$searchKey] = array(
'searchKey' => 'entity.status',
'searchValue' => $searchValue,
'operation' => self::EQUAL_OPERATION
);
break;
}
}
}

return $filterFields;
}

/**
* @param $filters
* @return array
* @throws \Doctrine\DBAL\DBALException
*/
public function getDataByFilters($filters)
{
$data = $this->getDataQueryByFilters($filters)
->getQuery()
->getArrayResult();

$stmt = $this->getEntityManager()->getConnection()->prepare("SELECT FOUND_ROWS()");
$stmt->execute();
$count = $stmt->fetchColumn();

return array($data, $count);
}

public function buildSelectQuery()
{
$query = $this->createQueryBuilder('entity');

return $query;
}

/**
* @param $filters
* @return \Doctrine\ORM\QueryBuilder
*/
public function getDataQueryByFilters($filters)
{
$query = $this->buildSelectQuery();
$filterFields = $this->mapSearchFields($filters);

foreach ($filterFields as $key => $details) {
switch ($details['operation']) {
case self::LIKE_OPERATION:
$query
->andWhere(sprintf('%s LIKE :%s', $details['searchKey'], $key))
->setParameter($key, '%' . $details['searchValue'] . '%');
break;
case self::LIKE_LEFT_OPERATION:
$query
->andWhere(sprintf('%s LIKE :%s', $details['searchKey'], $key))
->setParameter($key, '%' . $details['searchValue']);
break;
case self::LIKE_RIGHT_OPERATION:
$query
->andWhere(sprintf('%s LIKE :%s', $details['searchKey'], $key))
->setParameter($key, $details['searchValue'] . '%');
break;
case self::HIGHER_OPERATION:
$query
->andWhere(sprintf('%s > :%s', $details['searchKey'], $key))
->setParameter($key, $details['searchValue']);
break;
default:
$query
->andWhere(sprintf('%s = :%s', $details['searchKey'], $key))
->setParameter($key, $details['searchValue']);
}
}

return $query;
}

Adăugarea se face apăsând butonul verde, iar apoi se urmăresc pașii de mai jos:

se completează numele și prenumele utilizatorului

se completează adresa de e-mail

se alege numele de utilizator(username-ul)

se setează o parolă

se alege un tip de acces: admin sau laborator

Figura – Adăugarea unui nou utilizator

Modulul Medicului

Logarea

Logarea în aplicație în modulul de administrare se va face pe baza unui user și o parolă unică.

Figura – Logarea în aplicație ca medic

Meniu

Acest meniu cuprinde:

Programările mele

Consultațiile mele

Figura – Meniul din modulul doctorului

Submeniul Programările mele

În acest submeniu doctorul își poate vizualiza toate programările făcute.

Figura – Lista programărilor doctorului

Filtrarea se face în funcție de următoarele câmpuri:

Nume pacient

CNP

Număr de telefon

Statusul programării(Nouă, Finalizată, În progres, Anulată)

După completarea acestor câmpuri se va apăsa butonul de căutare iar în listă se vor afișa doar programările care corespund cerințelor dorite

Căutarea programărilor unui doctor este facută astfel:

public function myAppointmentsAjaxAction(Request $request)
{
$baseService = $this->get('dacsoft.base_service');
$repository = $this->getDoctrine()->getRepository('HealthBaseBundle:PatientsAppointments');

$response = $baseService->getAjaxList($request, $repository);

return new JsonResponse($response);
}

Figura – Căutarea unei programări

Pentru adăugarea unei noi programări, medicul trebuie să urmeze pașii de mai jos:

Se apasă butonul Adaugă

Se completează numele și prenumele pacientului

Se alege data programării

Se alege ora de început

Se alege oră de sfârșit a programării respective

Se apasă butonul salvează

După aceste operațiuni, programarea adăugată de doctor va apărea în lista de programări

Figura – Adăugarea unei noi programări

Doctorul își poate alege o programare și o poate vizualiza. După vizualizare, acesta are două opțiuni:

Începe programare – acest buton se apasă în momentul în care medicul dorește să înceapă programarea stabilită

Anulează programare – acest buton se apasă dacă medicul dorește să anuleze programarea.

Pentru acțiunile de Începe programare, Anuleaza programare sau Finalizează programare există o funcție comună care realizează acest lucru:

public function updateStatusAction($id, $status)
{
$userService = $this->get(UserService::SERVICE_NAME);

if (!$userService->hasRequiredPermissions(Users::TYPE_DOCTOR)) {
return $this->render('@DacsoftUi/common/access_denied.html.twig');
}

/** @var PatientsAppointments $patientsAppointment */
$patientsAppointment = $this->getRepository()->find($id);

if ($patientsAppointment instanceof PatientsAppointments) {
$patientsAppointment->setStatus($status);
$em = $this->getDoctrine()->getManager();
$em->persist($patientsAppointment);
$em->flush();

if ($status == 2) {
/** @var InvoiceService $invoiceService */
$invoiceService = $this->get(InvoiceService::SERVICE_NAME);
$invoiceService->generateInvoice($patientsAppointment->getId());
}
}

return $this->redirectToRoute('patientsappointments_doctor', array('id' => $id));
}

Pentru a vizualiza o programare se apasă butonul de acțiuni din partea dreaptă

Figura – Butonul de Acțiuni

În această interfață, medicul are detalii despre pecient și consultațiile care îi sunt asignate.

Figura – Vizualizarea programării

Interfața de gestionare a unei programări este construită cu ajutorul următorului cod:

{% extends 'DacsoftUiBundle:Default:base.html.twig' %}

{% form_theme consultationForm 'DacsoftUiBundle:Form:form.html.twig' %}

{% block breadcrumb %} {{ appointment.doctor.name }} {% endblock %}
{% block pageTitle %} Evalueaza pacient{% endblock %}

{% block body %}
<div class="row">
<div class="col-md-12">
{% if appointment.status == 2 or appointment.status == 3 %}
<div class="alert alert-block alert-error fade in">
<h4 class="alert-heading"><i class="icon-warning-sign"></i> Atentie!</h4>
<p> Aceasta programare este inchisa! Nu se mai pot efectua modificari </p>
<div class="button-set">
{% if appointment.invoice %}
<a class="btn btn-danger btn-cons" href="{{ url('invoices_view_pdf', {'invoiceId': appointment.invoice.id}) }}">Descarca factura</a>
{% endif %}
</div>
</div>
{% else %}
<div class="grid simple vertical green">
<div class="grid-title no-border">
<h4>Operatii</h4>
</div>
<div class="grid-body no-border">
<div class="pull-right">
{% if appointment.status == 1 %}
<a class="btn btn-primary btn-cons"
href="{{ url('patientsappointments_update_status' ,{'id': appointment.id, 'status': 4}) }}">
Incepe programare </a>
<a class="btn btn-danger btn-cons"
href="{{ url('patientsappointments_update_status' ,{'id': appointment.id, 'status': 3}) }}">
Anuleaza programare </a>
{% else %}
<a class="btn btn-primary btn-cons"
href="{{ url('patientsappointments_update_status' ,{'id': appointment.id, 'status': 2}) }}">
Finalizeaza programare </a>
<a class="btn btn-danger btn-cons"
href="{{ url('patientsappointments_update_status' ,{'id': appointment.id, 'status': 3}) }}">
Anuleaza programare </a>
<a class="btn btn-info btn-cons" href="{{ url('patientsappointments_new_by_doctor', {'doctorId': appointment.doctor.id, 'patientId': appointment.patient.id}) }}"> Adauga programare </a>

{% endif %}
</div>
</div>
</div>
{% endif %}

</div>
</div>

<div class="grid-body no-border"><br>
<div class="row">
<div class="col-md-6">
<div class="grid simple vertical red">
<div class="grid-title no-border">
<h4>{{ 'pages.patients.show.details.title' | trans }}</h4>
</div>
<div class="grid-body no-border">
<h2 class="all-caps">{{ appointment.patient.name }}</h2>
<br/>
<h5 class="all-caps">{{ "patient.sex" | trans }}: <span
class="semi-bold">{{ appointment.patient.sex }} </span></h5>
<h5 class="all-caps">{{ "patient.identification_code" | trans }}: <span
class="semi-bold">{{ appointment.patient.identificationCode }} </span></h5>
<h5 class="all-caps">{{ "patient.identity_card" | trans }}: <span
class="semi-bold">{{ appointment.patient.identityCardSeries }} {{ appointment.patient.identityCardNumber }} </span>
</h5>
<h5 class="all-caps">{{ "patient.phone" | trans }}: <span
class="semi-bold">{{ appointment.patient.phoneNumber }} </span></h5>
</div>
</div>
</div>

<div class="row">
<div class="col-md-6">
<div class="grid simple vertical blue disabled">
<div class="grid-title no-border">
<h4>Adauga consultatii</h4>
</div>
<div class="grid-body no-border">
{{ form_start(consultationForm) }}
{{ form_widget(consultationForm) }}
<div class="pull-right">
<br/>
{% if appointment.status == 4 %}
<button class="btn btn-success btn-small" type="submit"><i
class="icon-ok"></i>{{ 'buttons.add' | trans }} </button>
{% endif %}
</div>
{{ form_end(consultationForm) }}

</div>
</div>
</div>
</div>
</div>

<div class="row">
<div class="col-md-12">
<div class="grid simple vertical green">
<div class="grid-title no-border">
<h4>Consultatii programare</h4>
</div>
<div class="grid-body no-border">
<table class="table table-striped table-flip-scroll cf">
<thead class="cf">
<tr>

<th>Denumire consultatie</th>
<th>Cost</th>
<th>Observatii</th>
</tr>
</thead>
<tbody>
{% for consultation in consultations %}
<tr>
<td>
{{ consultation.doctorsConsultations.name }}
</td>
<td>
{{ consultation.doctorsConsultations.price }} RON
</td>
<td align="center">
{{ consultation.description }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

{% block javascripts %}
{% include '@DacsoftUi/common/formScripts.html.twig' %}
{% endblock %}

După începerea programării, doctorul vizualizează detaliile pacientului, tipul consultației, și costul consultațiilor asignate.

Figura – Programare începută

Dacă acesta dorește să finalizele programarea, se apăsa butonul de finalizare, anulare sau adaugă programare.

Figura – Buton Finalizare programare

Figura – Buton Anulează programare

Figura – Adaugă programare

După finalizarea unei programări, medicul nu mai poate face nici o modificare asupra acesteia.

Figura – Programare finalizată

După finalizarea programării, pecientului i se generează o factură iar aceasta se poate descărca apăsând butonul Descărcă factură

Figura – Factura pacientului

Generarea unei facturi este realizată de secvența de cod de mai jos:

/**
* @param PatientsAppointments $appointment
*/
protected function generateInvoiceHeader(PatientsAppointments $appointment)
{
$invoiceNumber = $this->getSetting('INVOICE_NUMBER');
$this->increaseInvoiceNumber($invoiceNumber);

$address = '';
if ($appointment->getPatient()->getAddresses()->count() >0 ){
/** @var PatientsAddresses $defaultAddress */
$defaultAddress = $appointment->getPatient()->getAddresses()->first();
$address = $defaultAddress->getFormatedAddress();
}

$invoice = new Invoices();
$invoice
->setPatient($appointment->getPatient())
->setPacientAppointments($appointment)
->setPatientName($appointment->getPatient()->getName())
->setPatientCode($appointment->getPatient()->getIdentificationCode())
->setPatientAddress($address)
->setInvoiceDate(new \DateTime())
->setInvoiceNumber($invoiceNumber)
->setInvoiceSeries($this->getSetting('INVOICE_SERIES'))
->setTotal(0)
->setTotalWithoutVat(0)
->setVat(0);

$this->getEntityManager()->persist($invoice);

return $invoice;
}

/**
* @param $invoiceNumber
*/
protected function increaseInvoiceNumber($invoiceNumber)
{
$invoiceNumeberLength = strlen($invoiceNumber);
$invoiceNumber = intval($invoiceNumber);
$invoiceNumber++;
$invoiceNumber = str_pad($invoiceNumber, $invoiceNumeberLength, '0', STR_PAD_LEFT);

$this->updateSetting('INVOICE_NUMBER',$invoiceNumber);
}

/**
* @param PatientsAppointments $appointment
* @param Invoices $invoice
*/
protected function generateInvoiceLines(PatientsAppointments $appointment, Invoices $invoice)
{
$orderTotal = 0;
$totalWithoutVat = 0;
$vatTotal = 0;

/** @var PatientsAppointmentsConsultations $consultation */
foreach ($appointment->getConsultations() as $consultation) {
$lineValue = $consultation->getDoctorsConsultations()->getPrice();
$lineVatValue = round($lineValue / (1 + floatval($this->getSetting('VAT_VALUE'))), 2);
$lineWithoutVatValue = round($lineValue – $lineVatValue, 2);

$orderTotal += $lineValue;
$totalWithoutVat += $lineWithoutVatValue;
$vatTotal += $lineVatValue;

$invoiceLine = new InvoicesLines();
$invoiceLine
->setQuantity(1)
->setDescription("Consultatie(Dr: ".$consultation->getDoctorsConsultations()->getDoctor()->getName()."): ".$consultation->getDoctorsConsultations()->getName())
->setUnit('B')
->setTotal($lineValue)
->setVatValue($lineVatValue)
->setValueWithoutVat($lineWithoutVatValue)
->setInvoice($invoice);

$this->getEntityManager()->persist($invoiceLine);
}

$invoice
->setTotal($orderTotal)
->setVat($vatTotal)
->setTotalWithoutVat($lineWithoutVatValue);

$this->getEntityManager()->persist($invoice);
}

/**
* @param $appointmentId
*/
public function generateInvoice($appointmentId)
{
/** @var PatientsAppointments $appointment */
$appointment = $this->getEntityManager()->getRepository('HealthBaseBundle:PatientsAppointments')->find($appointmentId);

if ($appointment instanceof PatientsAppointments) {
if ($appointment->getConsultations()->count() > 0) {
$invoice = $this->generateInvoiceHeader($appointment);
$this->generateInvoiceLines($appointment, $invoice);
$this->getEntityManager()->flush();
}
}
}

Submeniul Consultațiile mele

Această secțiune pune la dispoziția doctorului toate consultațiile care îi sunt adăugate.

Figura – Lista consultațiilor

Filtrarea se face după tipul consultației. După completarea acestui câmp, se apasă butonul adaugă iar în lista vor apărea doar consultațiile care indpelinesc cerințele de căutare.

Figura – Filtrarea consultațiilor

Pentru adăugarea unei consultații noi, doctorului trebuie să urmeze pașii de mai jos:

se apasă butonul adaugă

se completează numele consultației

se selectează specializatea

se setează un preț

se apasă butonul salvează

După ce s-au finalizat pașii de mai sus, consultația va apărea în listă de consultații a doctorului

Modulul de laborator

Logarea

Logarea în aplicație în modulul de administrare se va face pe baza unui user și o parolă unică.

Figura – Logarea în aplicație ca administrator de laborator

Meniu

Meniul cuprinde:

Analize programate

Tipuri de analize

Figura – Meniul laboratorului

Submeniul Analize programate

În acest submeniu, administratorul laboratorului poate filtra lista analizelor după următoarele câmpuri:

Cod programare

Denumire analiză

Nume pacient

Status analiză

După completarea acestor câmpuri, se apasă butonul roșu Caută

Figura – Filtrarea analizelor

Pentru vizualizarea unei analize, se va da click pe codul de programare iar apoi se pot observa detalii despre analiză programată:

Numele și prenumele pacientului

Detalii despre pacientul respectiv

Numele analizei

Figura – Vizualizarea analizei

Rezultatul analizei se poate încărca apăsând butonul Browse iar apoi Adaugă rezultat. De asemenea o analiză se poate anula apăsând butonul roșu din dreapta sus, Anulează analiza.

Interpretarea unei analize este realizată cu următoarea secvență de cod:

public function showAction(Request $request, $id)
{
/** @var UserService $userService */
$userService = $this->get(UserService::SERVICE_NAME);

if (!$userService->hasRequiredPermissions(Users::TYPE_LABORATOR)) {
return $this->render('@DacsoftUi/common/access_denied.html.twig');
}

$laboratoryAnalysisScheduleDetails = $this->getDoctrine()->getRepository('HealthBaseBundle:LaboratoryAnalysisScheduleDetails')->find($id);

$editForm = $this->createForm('Health\BaseBundle\Form\LaboratoryAnalysisScheduleDetailsByLaboratoryType', $laboratoryAnalysisScheduleDetails);
$editForm->handleRequest($request);

if ($editForm->isSubmitted() && $editForm->isValid()) {
$laboratoryService = $this->get('ihealth.laboratory_service');
$laboratoryService->setRequest($request);
$laboratoryService->setForm($editForm);
$laboratoryService->saveDocuments($laboratoryAnalysisScheduleDetails);

$laboratoryAnalysisScheduleDetails->setStatus(1);
$em = $this->getDoctrine()->getManager();
$em->persist($laboratoryAnalysisScheduleDetails);
$em->flush();

$translator = $this->get('translator');
$this->get('session')->getFlashBag()->add('modifiy', $translator->trans('message.modifiy.content'));

}

return $this->render(
'@HealthBase/laboratoryanalysisschedule/view.html.twig',
array(
'laboratoryAnalysisSchedule' => $laboratoryAnalysisScheduleDetails,
'form' => $editForm->createView()
)
);
}

{% block pageTitle %} Evalueaza analiza{% endblock %}
{% form_theme form 'DacsoftUiBundle:Form:form.html.twig' %}

{% block body %}
<div class="row">
<div class="col-md-12">
{% if laboratoryAnalysisSchedule.status != 0 %}
<div class="alert alert-block alert-error fade in">
<h4 class="alert-heading"><i class="icon-warning-sign"></i> Atentie!</h4>
<p> Aceasta analiza este inchisa! Nu se mai pot efectua modificari </p>

<div class="button-set">
<a class="btn btn-info btn-small" href = "{{ url('laboratoryanalysisschedule_index_lab') }}">Vezi toate analizele</a>
</div>
<br/>
</div>
{% else %}
<div class="grid simple vertical">
<div class="grid-title no-border">
<h4>Operatii</h4>
</div>
<div class="grid-body no-border">
<div class="pull-right">
<a class="btn btn-danger btn-cons"
href="{{ url('laboratoryanalysisschedule_update_status' ,{'id': laboratoryAnalysisSchedule.id, 'status': 2}) }}">
Anuleaza analiza </a>
</div>
</div>
</div>
{% endif %}

</div>
</div>

<div class="grid-body no-border"><br>
<div class="row">
<div class="col-md-6">
<div class="grid simple vertical blue disabled">
<div class="grid-title no-border">
<h4>Rezultate analiza</h4>
</div>
<div class="grid-body no-border">
<h3 class="all-caps">{{ laboratoryAnalysisSchedule.analysis.name }}</h3>
{% if laboratoryAnalysisSchedule.status == 0 %}
{{ form_start(form) }}
{{ form_widget(form) }}
<div class="pull-right">
<br/>

<button class="btn btn-success btn-small" type="submit"><i
class="icon-ok"></i>{{ 'buttons.close' | trans }} </button>

</div>
{{ form_end(form) }}
{% else %}
<h5 class="all-caps">Rezultat analiza: <span
class="semi-bold">{{ laboratoryAnalysisSchedule.result }} </span></h5>
<h5 class="all-caps">Document analiza: <span
class="semi-bold">
{% if laboratoryAnalysisSchedule.resultDocument %}
<a href="{{ static }}{{ laboratoryAnalysisSchedule.resultDocument }}" download="{{ laboratoryAnalysisSchedule.resultDocument }}">Descarca document</a>
{% else %}

{% endif %}
</span></h5>
<h5 class="all-caps">Status: {% if laboratoryAnalysisSchedule.status==1 %}
<span class="label label-success">Finalizata</span>
{% elseif laboratoryAnalysisSchedule.status==2 %}
<span class="label label-important">Anulata</span> {% endif %}
</h5>
{% endif %}

</div>
</div>
</div>

<div class="col-md-6">
<div class="grid simple vertical red">
<div class="grid-title no-border">
<h4>{{ 'pages.patients.show.details.title' | trans }}</h4>
</div>
<div class="grid-body no-border">
<h3 class="all-caps">{{ laboratoryAnalysisSchedule.laboratoryAnalysis.patient.name }}</h3>
<br/>
<h5 class="all-caps">{{ "patient.sex" | trans }}: <span
class="semi-bold">{{ laboratoryAnalysisSchedule.laboratoryAnalysis.patient.sex }} </span></h5>
<h5 class="all-caps">{{ "patient.identification_code" | trans }}: <span
class="semi-bold">{{ laboratoryAnalysisSchedule.laboratoryAnalysis.patient.identificationCode }} </span></h5>
<h5 class="all-caps">{{ "patient.identity_card" | trans }}: <span
class="semi-bold">{{ laboratoryAnalysisSchedule.laboratoryAnalysis.patient.identityCardSeries }} {{ laboratoryAnalysisSchedule.laboratoryAnalysis.patient.identityCardNumber }} </span>
</h5>
<h5 class="all-caps">{{ "patient.phone" | trans }}: <span
class="semi-bold">{{ laboratoryAnalysisSchedule.laboratoryAnalysis.patient.phoneNumber }} </span></h5>
</div>
</div>
</div>
</div>

</div>
{% endblock %}

{% block javascripts %}
{% include '@DacsoftUi/common/formScripts.html.twig' %}
{% endblock %}

Figura – Anulează analiza

Submeniul Tipuri analize

Adminul laboratorului are dreptul de a vizualiza lista tuturor analizelor adăugate în aplicație. Căutarea lor se va face în funcție de denumire. În lista se vor afișa toate analizele care îndeplinesc criteriile căutării.

Figura – Afișarea tuturor analizelor inserate în program

Adăugarea se va face apăsând butonul Adaugă, după care se va completea denumirea analizei și costul în lei al acesteia. După completarea acestor câmpuri, apăsarea butonului Salvează va permite salvarea în program a datelor.

Figura – Adăugarea analizelor

Termeni de utilizare

Autorii

Această aplicație a fost creată de Ionovici Raluca – Daniela, sub îndrumarea Dr. Ing. Marius Marian cu scopul de a îmbunătăți activitatea unei clinici medicale.

Licența de utilizare

Nu există restricții de utilizare. Documentul nu este constrâns de nicio licență.

Concluzii

Într-o perioada când realizarea aplicațiilor este o necesitate se remarcă o nevoie din ce în ce mai mare de programatori care să cunoască aceste limbaje de dezvoltare și a modului în care acestea se completează în vederea atingerii scopului final. Fie că este vorba despre o aplicație web acestea se completează în vederea atingerii scopului final

De aceea, pentru a oferi un grad de dinamism a datelor prezentate, o combinație de tehnologii trebuie folosite. Bazele de date oferă suportul pentru a salva și a obține informații într-un mod foarte ușor, javascript-urile sunt acele secvențe de cod care contribuie la crearea unor elemente unice în aplicație, iar limbajul PHP este ceea ce le unește pe ambele, creând o aplicație calitativă.

Lucrarea de față are scopul de prezentare a aplicației numită iHealth. Aplicația este prezentată printr-un exemplu elocvent, implicarea mai multor limbaje de programare pentru a atinge scopul final.

În concluzie, factorul cheie al aplicației a stat în menținerea unei idei simple cu un scop bine definit, cu un grad de interactivitate ridicat, gândită și lucrată într-un mod excepțional pentru că utilizatorii ei să fie mulțumiți.

Bibliografie

Introducere in Internet, Editura Teora, București, 1995- Popa S.

PHP and MySQL Web Development, Sams Publishing, 2001 – Luke Welling, Laura Thomson

Proiectarea bazelor de date relaționale, Editura Sitech ,1997-Giurgițeanu N.

Programarea în Web, Jamsa Press, 1996 – Kris Jamsa, Suleiman Lalani, Steve Weakley

Securitatea comerțului electronic, Editura All, 2001 – Patriciu V. V, Ene-Pietroșanu M., Bică I., Văduva C., Voicu N.

“Baze de date – Proiectare, implementare, gestionare”, T. Conolly, C. Begg, A. Strachman, Editura Teora, București, 2001

“Baze de date pentru începători”, J Patterson, Editura All, 2003

“Proceduri stocate in SQL Server, XML, HTML”, Editura Teora, 2003, traducerea I. Bedea, E. Sipos

“Teoria generală a bazelor de date”, I. Despi, G. Petrov, R. Reisz, A Stepan, Editura Mitron, Timișoara, 2000

Referințe web

jQuery

https://mysql.com/

https://php.net/

https://symphony.com/

https://w3schools.com/html/

https://w3schools.com/js/

Codul sursă

class BaseAjaxController extends Controller
{
protected $repository;

protected $entity;
/**
* @param Request $request
* @return JsonResponse
*/
public function listAjaxAction(Request $request)
{
$baseService = $this->get('dacsoft.base_service');
$response = $baseService->getAjaxList($request, $this->getRepository());

return new JsonResponse($response);
}

/**
* @param Request $request
* @return JsonResponse
*/
public function deleteAjaxAction(Request $request)
{
$objectId = $request->get('object');
$object = $this->getRepository()->find($objectId);

if (!BaseService::isNullObject($object)) {
if ($object instanceof Users) {
$object->setStatus(Users::STATUS_INACTIVE);
} else {
$this->getDoctrine()->getManager()->remove($object);
}
$this->getDoctrine()->getManager()->flush();
}

return $this->listAjaxAction($request);
}

/**
* @param Request $request
* @return JsonResponse
*/
public function activateAjaxAction(Request $request)
{
$objectId = $request->get('object');
$object = $this->getRepository()->find($objectId);

if (!BaseService::isNullObject($object)) {
$object->setStatus(1);
$this->getDoctrine()->getManager()->persist($object);
$this->getDoctrine()->getManager()->flush();
}

return $this->listAjaxAction($request);
}

/**
* @return mixed
*/
public function getRepository()
{
return $this->repository;
}

/**
* @param mixed $repository
*/
public function setRepository($repository)
{
$this->repository = $repository;
}

/**
* @return mixed
*/
public function getEntity()
{
return $this->entity;
}

/**
* @param mixed $entity
*/
public function setEntity($entity)
{
$this->entity = $entity;
}
}

/**
* Specialities
*
* @ORM\Table(name="specialities")
* @ORM\Entity(repositoryClass="Health\BaseBundle\Repository\SpecialitiesRepository")
* @ORM\HasLifecycleCallbacks()
*/
class Specialities
{
/**
* @var string
*
* @ORM\Column(name="speciality_name", type="text", length=65535, nullable=false)
*/
private $specialityName;

/**
* @var integer
*
* @ORM\Column(name="status", type="smallint", nullable=false)
*/
private $status;

/**
* @var \DateTime
*
* @ORM\Column(name="created", type="datetime", nullable=false)
*/
private $created;

/**
* @var \DateTime
*
* @ORM\Column(name="modified", type="datetime", nullable=false)
*/
private $modified;

/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;

/**
* Set specialityName
*
* @param string $specialityName
*
* @return Specialities
*/
public function setSpecialityName($specialityName)
{
$this->specialityName = $specialityName;

return $this;
}

/**
* Get specialityName
*
* @return string
*/
public function getSpecialityName()
{
return $this->specialityName;
}

/**
* Set status
*
* @param integer $status
*
* @return Specialities
*/
public function setStatus($status)
{
$this->status = $status;

return $this;
}

/**
* Get status
*
* @return integer
*/
public function getStatus()
{
return $this->status;
}

/**
* Set created
*
* @param \DateTime $created
*
* @return Specialities
*/
public function setCreated($created)
{
$this->created = $created;

return $this;
}

/**
* Get created
*
* @return \DateTime
*/
public function getCreated()
{
return $this->created;
}

/**
* Set modified
*
* @param \DateTime $modified
*
* @return Specialities
*/
public function setModified($modified)
{
$this->modified = $modified;

return $this;
}

/**
* Get modified
*
* @return \DateTime
*/
public function getModified()
{
return $this->modified;
}

/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}

/**
* @ORM\PrePersist
*/
public function prePersist()
{
if ($this->getCreated() === null) {
$this->setCreated(new \DateTime('now'));
}

if ($this->getModified() === null) {
$this->setModified(new \DateTime('now'));
}

if ($this->getStatus() === null) {
$this->setStatus(1);
}
}

public function __toString()
{
return $this->getSpecialityName();
}
}

/**
* ApplicationSettings
*
* @ORM\Table(name="application_settings", uniqueConstraints={@ORM\UniqueConstraint(name="settings_name", columns={"settings_name"})})
* @ORM\Entity(repositoryClass="Health\BaseBundle\Repository\ApplicationSettingsRepository")
* @ORM\HasLifecycleCallbacks()
*/
class ApplicationSettings
{
/**
* @var string
*
* @ORM\Column(name="settings_name", type="string", length=255, nullable=false)
*/
private $settingsName;

/**
* @var string
*
* @ORM\Column(name="settings_value", type="string", length=255, nullable=false)
*/
private $settingsValue;

/**
* @var integer
*
* @ORM\Column(name="status", type="smallint", nullable=false)
*/
private $status;

/**
* @var \DateTime
*
* @ORM\Column(name="added", type="datetime", nullable=false)
*/
private $added;

/**
* @var \DateTime
*
* @ORM\Column(name="modified", type="datetime", nullable=false)
*/
private $modified;

/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;

/**
* Set settingsName
*
* @param string $settingsName
*
* @return ApplicationSettings
*/
public function setSettingsName($settingsName)
{
$this->settingsName = $settingsName;

return $this;
}

/**
* Get settingsName
*
* @return string
*/
public function getSettingsName()
{
return $this->settingsName;
}

/**
* Set settingsValue
*
* @param string $settingsValue
*
* @return ApplicationSettings
*/
public function setSettingsValue($settingsValue)
{
$this->settingsValue = $settingsValue;

return $this;
}

/**
* Get settingsValue
*
* @return string
*/
public function getSettingsValue()
{
return $this->settingsValue;
}

/**
* Set status
*
* @param integer $status
*
* @return ApplicationSettings
*/
public function setStatus($status)
{
$this->status = $status;

return $this;
}

/**
* Get status
*
* @return integer
*/
public function getStatus()
{
return $this->status;
}

/**
* Set added
*
* @param \DateTime $added
*
* @return ApplicationSettings
*/
public function setAdded($added)
{
$this->added = $added;

return $this;
}

/**
* Get added
*
* @return \DateTime
*/
public function getAdded()
{
return $this->added;
}

/**
* Set modified
*
* @param \DateTime $modified
*
* @return ApplicationSettings
*/
public function setModified($modified)
{
$this->modified = $modified;

return $this;
}

/**
* Get modified
*
* @return \DateTime
*/
public function getModified()
{
return $this->modified;
}

/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}

/**
* @ORM\PrePersist
*/
public function prePersist()
{
if ($this->getAdded() === null) {
$this->setAdded(new \DateTime('now'));
}

if ($this->getModified() === null) {
$this->setModified(new \DateTime('now'));
}

if ($this->getStatus() === null) {
$this->setStatus(1);
}
}
}

class PatientsFidelityCardsType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add(
'patient',
EntityType::class,
array(
'class' => 'Health\BaseBundle\Entity\Patients',
'label' => 'forms.patientsfidelitycards.fields.patient',
'attr' => array(
'class' => 'col-md-12 no-padding'
)
)
)
->add(
'cardNumber',
TextType::class,
array(
'label' => 'forms.patientsfidelitycards.fields.cardNumber',
'attr' => array(
)
)
)
->add(
'cardSeries',
TextType::class,
array(
'label' => 'forms.patientsfidelitycards.fields.cardSeries',
'attr' => array(
)
)
);
}

/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Health\BaseBundle\Entity\PatientsFidelityCards'
));
}
}

class EntityBaseRepository extends EntityRepository
{
const EQUAL_OPERATION = 'equal';

const LIKE_OPERATION = 'like';

const LIKE_RIGHT_OPERATION = 'like_right';

const LIKE_LEFT_OPERATION = 'like_left';

const HIGHER_OPERATION = '>';

/**
* @param $filters
* @return array
*/
protected function mapSearchFields($filters)
{
$filterFields = array();

foreach ($filters as $searchKey => $searchValue) {
if (!is_null($searchValue) && strlen($searchValue)) {
}
}

return $filterFields;
}

/**
* @param $filters
* @return array
* @throws \Doctrine\DBAL\DBALException
*/
public function getDataByFilters($filters)
{
$data = $this->getDataQueryByFilters($filters)
->getQuery()
->getArrayResult();

$stmt = $this->getEntityManager()->getConnection()->prepare("SELECT FOUND_ROWS()");
$stmt->execute();
$count = $stmt->fetchColumn();

return array($data, $count);
}

public function buildSelectQuery()
{
$query = $this->createQueryBuilder('entity');

return $query;
}

/**
* @param $filters
* @return \Doctrine\ORM\QueryBuilder
*/
public function getDataQueryByFilters($filters)
{
$query = $this->buildSelectQuery();
$filterFields = $this->mapSearchFields($filters);

foreach ($filterFields as $key => $details) {
switch ($details['operation']) {
case self::LIKE_OPERATION:
$query
->andWhere(sprintf('%s LIKE :%s', $details['searchKey'], $key))
->setParameter($key, '%' . $details['searchValue'] . '%');
break;
case self::LIKE_LEFT_OPERATION:
$query
->andWhere(sprintf('%s LIKE :%s', $details['searchKey'], $key))
->setParameter($key, '%' . $details['searchValue']);
break;
case self::LIKE_RIGHT_OPERATION:
$query
->andWhere(sprintf('%s LIKE :%s', $details['searchKey'], $key))
->setParameter($key, $details['searchValue'] . '%');
break;
case self::HIGHER_OPERATION:
$query
->andWhere(sprintf('%s > :%s', $details['searchKey'], $key))
->setParameter($key, $details['searchValue']);
break;
default:
$query
->andWhere(sprintf('%s = :%s', $details['searchKey'], $key))
->setParameter($key, $details['searchValue']);
}
}

return $query;
}
}

/**
* Class UsersRepository
* @package Health\BaseBundle\Repository
*/
class UsersRepository extends EntityBaseRepository
{
/**
* @param $filters
* @return array
*/
protected function mapSearchFields($filters)
{
$filterFields = array();

foreach ($filters as $searchKey => $searchValue) {
if (!is_null($searchValue) && strlen($searchValue)) {
switch ($searchKey) {
case 'name':
$filterFields[$searchKey] = array(
'searchKey' => 'entity.name',
'searchValue' => $searchValue,
'operation' => self::LIKE_OPERATION
);
break;
case 'username':
$filterFields[$searchKey] = array(
'searchKey' => 'entity.username',
'searchValue' => $searchValue,
'operation' => self::LIKE_OPERATION
);
break;
case 'email':
$filterFields[$searchKey] = array(
'searchKey' => 'entity.email',
'searchValue' => $searchValue,
'operation' => self::LIKE_OPERATION
);
break;
case 'user_type':
$filterFields[$searchKey] = array(
'searchKey' => 'entity.userType',
'searchValue' => $searchValue,
'operation' => self::EQUAL_OPERATION
);
break;
case 'status':
$filterFields[$searchKey] = array(
'searchKey' => 'entity.status',
'searchValue' => $searchValue,
'operation' => self::EQUAL_OPERATION
);
break;
}
}
}

return $filterFields;
}
}

/**
* Class BaseService
* @package Health\BaseBundle\Services
*/
class BaseService
{
const SERVICE_NAME = 'ihealth.base_service';

/** @var EntityManager */
protected $entityManager;

protected $translator;

protected $templating;

protected $mailer;

protected $session;

/**
* @param int $length
* @return string
*/
public function generateRandomString($length = 10)
{
$characters = '0123456789abcdefghijklmnopqrstuwxyzABCDEFGHIJKLMNOPQRSTUWXYZ';
$charactersLength = strlen($characters);

$randomString = '';
for ($i = 0; $i < $length; $i++){
$randomString .= $characters[rand(0, $charactersLength -1)];
}

return $randomString;
}

/**
* @param Request $request
* @param EntityBaseRepository $repository
* @return array
*/
public function getAjaxList(Request $request, $repository)
{
$filters = $request->query->all();

list($data,$recordCount) = $repository
->getDataByFilters($filters);

return $this->formatData($data, $recordCount, $request->get('iDisplayLength'), $request->get('iDisplayStart'));
}

/**
* @param Request $request
* @param EntityBaseRepository $repository
* @return array
*/
public function getAjaxListDoctors(Request $request, $repository)
{
$filters = $request->query->all();

list($data,$recordCount) = $repository
->getDataByFilters($filters);

$data = $this->formatData($data, $recordCount, $request->get('iDisplayLength'), $request->get('iDisplayStart'));
$doctors = $data['aaData'];

$doctorSpecialityRepository = $this->getEntityManager()->getRepository('HealthBaseBundle:DoctorsSpecialities');

foreach ($doctors as &$doctor) {

$doctorSpecialities = $doctorSpecialityRepository->getDoctorSpecialities($doctor['id']);
$specialities = array();
foreach ($doctorSpecialities as $speciality) {
$specialities[] = $speciality['name'];
}

$doctor['speciality'] = implode(',', $specialities);
}

$data['aaData'] = $doctors;

return $data;
}

public function formatData($data, $recordCount, $rows = 100, $offset = 1, $error = '')
{
$response = array(
"iTotalRecords" => $recordCount,
"iTotalDisplayRecords" => $recordCount,
'errorMessage' => $error
);

if (!empty($error)) {
$response['errorMessage'] = $error;
}

if ($offset < 0) {
$offset = 0;
}

$data = array_slice($data, $offset, $rows);
$response['aaData'] = $data;

return $response;
}

/**
* @param $entity
* @return bool
* @throws \Exception
*/
public static function isNullObject($entity)
{
if (is_null($entity)) {
return true;
}

if (!is_object($entity)) {
throw new \Exception('Parameter passed is not an object.');
}

try {
if ($entity instanceof Proxy && !$entity->__isInitialized()) {
try {
$entity->__load();
} catch (\Exception $e) {
// Doctrine will have marked the object as initialized, after loading fails
// Reset the flag before return
$entity->__isInitialized__ = false;

return true;
}
}

return false;
} catch (\Exception $e) {
return true;
}
}

/**
* @param $settingName
* @return string
*/
public function getSetting($settingName)
{
$settings = $this->getEntityManager()->getRepository('HealthBaseBundle:ApplicationSettings')->findOneBy(
array(
'settingsName' => $settingName,
'status' => 1
)
);

if ($settings instanceof ApplicationSettings){
return $settings->getSettingsValue();
}

return '';
}

/**
* @param $settingName
* @return string
*/
public function updateSetting($settingName, $settingValue)
{
$settings = $this->getEntityManager()->getRepository('HealthBaseBundle:ApplicationSettings')->findOneBy(
array(
'settingsName' => $settingName,
'status' => 1
)
);

if ($settings instanceof ApplicationSettings) {
$settings->setSettingsValue($settingValue);
$this->getEntityManager()->persist($settings);
$this->getEntityManager()->flush($settings);
}
}

public function getCompanySettings()
{
return array(
'name' => $this->getSetting('COMPANY_NAME'),
'address' => $this->getSetting('COMPANY_ADDRESS'),
'cif' => $this->getSetting('COMPANY_CODE'),
'reg_com' => $this->getSetting('COMPANY_REGISTRATION'),
'phone' => $this->getSetting('COMPANY_PHONE'),
'email' => $this->getSetting('COMPANY_EMAIL'),
'www' => $this->getSetting('COMPANY_WWW')
);

}

/**
* @param PatientsAppointments $appointment
*/
public function checkAppointment($appointment)
{
$appointmentRepo = $this->getEntityManager()->getRepository('HealthBaseBundle:PatientsAppointments');

$doctorAppointements = $appointmentRepo->getDoctorAppointmets(
$appointment->getDoctor()->getId(),
$appointment->getDate(),
$appointment->getStartHour()->format('H:i:s'),
$appointment->getEndHour()->format('H:i:s')
);

if (count($doctorAppointements)) {
throw new \Exception('Acest medic are deja o programare in intervalul selectat');
}

$patientAppointments = $appointmentRepo->gePatientAppointmets(
$appointment->getPatient()->getId(),
$appointment->getDate(),
$appointment->getStartHour()->format('H:i:s'),
$appointment->getEndHour()->format('H:i:s')
);

if (count($patientAppointments)) {
throw new \Exception('Acest pacient are deja o programare in intervalul selectat');
}
}

/**
* @return EntityManager
*/
public function getEntityManager()
{
return $this->entityManager;
}

/**
* @param EntityManager $entityManager
*/
public function setEntityManager($entityManager)
{
$this->entityManager = $entityManager;
}

/**
* @return mixed
*/
public function getTranslator()
{
return $this->translator;
}

/**
* @param mixed $translator
*/
public function setTranslator($translator)
{
$this->translator = $translator;
}

/**
* @return mixed
*/
public function getTemplating()
{
return $this->templating;
}

/**
* @param mixed $templating
*/
public function setTemplating($templating)
{
$this->templating = $templating;
}

/**
* @return mixed
*/
public function getMailer()
{
return $this->mailer;
}

/**
* @param mixed $mailer
*/
public function setMailer($mailer)
{
$this->mailer = $mailer;
}

/**
* @return mixed
*/
public function getSession()
{
return $this->session;
}

/**
* @param mixed $session
*/
public function setSession($session)
{
$this->session = $session;
}
}

class LaboratoryAnalysisService
{
/** @var Form $form */
protected $form = null;

/** @var ContainerInterface $container */
protected $container;

/**
* @var EntityManager
*/
protected $entityManager;

/**
* @var Request
*/
protected $request;

/**
* @param $container
*/
public function setContainer($container)
{
$this->container = $container;
}

/**
* @return ContainerInterface
*/
public function getContainer()
{
return $this->container;
}

/**
* @return Form
*/
public function getForm()
{
return $this->form;
}

/**
* @param Form $form
*/
public function setForm(Form $form)
{
$this->form = $form;
}

/**
* @param UploadedFile $file
* @return string
*/
private function createFileName(UploadedFile $file)
{
$fileExtension = $file->getClientOriginalExtension();

return 'analysis_result' . '_' . time() . '.' . $fileExtension;
}

/**
* @return mixed
*/
protected function generateFilePath()
{
$path = $this->getContainer()->getParameter('upload_path');
if (!file_exists($path)) {
$ret = mkdir($path, 0777, true);
if (!$ret) {
throw new \RuntimeException('Could not create target directory to move temporary file into.');
}
}

return $path;
}

/**
* @param LaboratoryAnalysisScheduleDetails $object
* @return LaboratoryAnalysisScheduleDetails
*/
protected function processUploadedFile(LaboratoryAnalysisScheduleDetails $object)
{
/** @var UploadedFile $file */
$file = $object->getDocumentFile();
$whereToMove = $this->generateFilePath();
$fileName = $this->createFileName($file);

$object->setResultDocument($fileName);
$file->move($whereToMove, $fileName);
$this->getEntityManager()->persist($object);
return $object;

}

/**
* @param LaboratoryAnalysisScheduleDetails $entity
*/
public function saveDocuments(LaboratoryAnalysisScheduleDetails $entity)
{

/** @var LaboratoryAnalysisSchedule $entity */
if ($entity->getDocumentFile() instanceof UploadedFile) {
$this->processUploadedFile($entity);
}

$this->getEntityManager()->flush();

}

/**
* Save the entity
*
* @return array
*/
public function handleRequest()
{

$this->saveDocuments($this->getForm()->getData());

}

/**
* @return EntityManager
*/
public function getEntityManager()
{
return $this->entityManager;
}

/**
* @param EntityManager $entityManager
*/
public function setEntityManager($entityManager)
{
$this->entityManager = $entityManager;
}

/**
* @return Request
*/
public function getRequest()
{
return $this->request;
}

/**
* @param Request $request
*/
public function setRequest($request)
{
$this->request = $request;
}
}

CD / DVD

INDEX

A

Adăugare doctor 49

Adăugarea pacienților 30

Adăugarea unei consultații 54, 73

Adăugarea unei noi programări 39

Adăugarea unui card 34

Adminii 56

Analize programate 75

Anulează programare 63

Apache Portable Routine(APR) 9

Application_settings 14

B

Baza de date 13

Bibliografie 84

C

Căutare a doctorilor 47

căutare a programărilor 36

Consultațiile mele 73

Contrucția meniului 24

Cuprinsul x

D

Descrierea aplicației 11

Doctorii 56

Doctors 14

Doctors_consultations 15

F

Factură 70

Finalizele programarea 69

G

Generarea unei facturi 70

I

Începe programare 63

Interpretorul PHP 4

Invoices 16

Invoices_lines 16

L

Laboratoarele de analize 56

Laboratory_analysis 16

Laboratory_analysis_schedule 17

Laboratory_analysis_schedule_details 17

Limbajul HTML 8

Lista figurilor xii

Lista tabelelor xiv

Listarea pacienților 27

M

Medicina modernă 11

Microsoft SQL Server 2

Modulul Administrator 12

Modulul de laborator 74

Modulul Laborator 12

Modulul Medic 12

Modulul Medicului 61

Motivația 1

MySQL 2

O

Oracle 2

P

Pacienți 26

Patients 17

Patients_addresses 18

Patients_appointments 18

Patients_appointments_consultations 19

Patients_fidelity_cards 19

PHP 4

Programa 35

Programări analize 43

Programările mele 61

S

Scopul 1

Secțiunea Doctori 46

Serverul web Apache 9

Setari 54

Software 12

Specialities 15

Specializări 55

SQL 2

Standardiza 14

T

Tipuri analize 43, 80

U

Users 19

Utilizatori interni 56

V

Variabilele globale 7

Variabilele statice 7

Vizualizarea unei analize 75

Similar Posts