\section{Proiectarea sistemului informatic}

Această secțiune cuprinde proiectarea bazei de date și descrierea obiectelor aplicației: identificarea entităților și a relațiilor, dicționarul datelor, modelul relațional și normalizarea, apoi tabelele, ecranele, interogările și rapoartele implementate în Microsoft Access.

\subsection{Descrierea entităților și a relațiilor}

Pentru modelarea bazei de date au fost definite cinci entități: \textbf{CLIENT}, \textbf{ANGAJAT}, \textbf{PRODUS}, \textbf{COMANDA} și \textbf{DETALIU\_COMANDA}. Primele patru sunt entități „de bază'' (clienții, personalul, meniul și comenzile), iar a cincea, \textbf{DETALIU\_COMANDA}, este o entitate de legătură care descompune relația de tip „mulți-la-mulți'' dintre comenzi și produse. Relațiile dintre entități sunt:

\begin{itemize}[leftmargin=1.4em,itemsep=2pt]
  \item \textbf{CLIENT -- COMANDA (1:N)}: un client poate plasa mai multe comenzi, însă o comandă aparține unui singur client;
  \item \textbf{ANGAJAT -- COMANDA (1:N)}: un chelner poate prelua mai multe comenzi, dar o comandă este preluată de un singur angajat;
  \item \textbf{COMANDA -- DETALIU\_COMANDA (1:N)}: o comandă conține una sau mai multe linii (produse comandate);
  \item \textbf{PRODUS -- DETALIU\_COMANDA (1:N)}: un produs poate apărea pe liniile mai multor comenzi.
\end{itemize}

Prin combinarea ultimelor două relații, legătura logică dintre \textbf{COMANDA} și \textbf{PRODUS} este una de tip \emph{mulți-la-mulți} (M:N), rezolvată corect prin entitatea intermediară \textbf{DETALIU\_COMANDA}. Modelul conceptual (entitate–relație) este redat în Fig.~\ref{fig:ermodel}.

\begin{figure}[H]\centering
\begin{tikzpicture}[
  font=\footnotesize,
  ent/.style={draw,rounded corners=2pt,align=center,fill=gray!8,minimum height=11mm,minimum width=27mm,inner sep=3pt},
  rel/.style={midway,fill=white,inner sep=1.5pt,font=\scriptsize},
  ln/.style={draw}]
  \node[ent] (client) {\textbf{CLIENT}\\\underline{ID\_Client}};
  \node[ent,right=34mm of client] (angajat) {\textbf{ANGAJAT}\\\underline{ID\_Angajat}};
  \coordinate (mid) at ($(client)!0.5!(angajat)$);
  \node[ent,below=18mm of mid] (comanda) {\textbf{COMANDA}\\\underline{ID\_Comanda}};
  \node[ent,below=18mm of comanda] (detaliu) {\textbf{DETALIU\_COMANDA}\\\underline{ID\_Detaliu}};
  \node[ent,right=34mm of detaliu] (produs) {\textbf{PRODUS}\\\underline{ID\_Produs}};
  \draw[ln] (client) -- node[rel,near start]{1} node[rel,near end]{N} (comanda);
  \draw[ln] (angajat) -- node[rel,near start]{1} node[rel,near end]{N} (comanda);
  \draw[ln] (comanda) -- node[rel,near start]{1} node[rel,near end]{N} (detaliu);
  \draw[ln] (produs) -- node[rel,near start]{1} node[rel,near end]{N} (detaliu);
\end{tikzpicture}
\caption{Modelul conceptual entitate–relație al aplicației}
\label{fig:ermodel}
\end{figure}

\subsection{Dicționarul datelor}

Dicționarul datelor inventariază atributele folosite de aplicație. Pentru fiecare se precizează tabela, tipul de date din Microsoft Access și o scurtă descriere (Tabelul~\ref{tab:dictionar}). Cheile primare sunt marcate cu \emph{(PK)}, iar cheile externe cu \emph{(FK)}.

\begin{center}
\renewcommand{\arraystretch}{1.2}
\begin{longtable}{@{}c >{\ttfamily}l l l >{\raggedright\arraybackslash}p{6.0cm}@{}}
\caption{Dicționarul datelor}\label{tab:dictionar}\\
\toprule
\textbf{Nr.} & \textbf{\normalfont Atribut} & \textbf{Tabela} & \textbf{Tip date} & \textbf{Descriere} \\
\midrule
\endfirsthead
\multicolumn{5}{l}{\small\itshape continuare Tabelul \thetable}\\
\toprule
\textbf{Nr.} & \textbf{\normalfont Atribut} & \textbf{Tabela} & \textbf{Tip date} & \textbf{Descriere} \\
\midrule
\endhead
\bottomrule
\endfoot
1  & ID\_Client      & CLIENT  & Număr (PK) & Identificator unic al clientului \\
2  & Nume            & CLIENT  & Text       & Numele de familie al clientului \\
3  & Prenume         & CLIENT  & Text       & Prenumele clientului \\
4  & Telefon         & CLIENT  & Text       & Numărul de telefon al clientului \\
5  & Email           & CLIENT  & Text       & Adresa de e-mail a clientului \\
6  & Oras            & CLIENT  & Text       & Orașul de domiciliu \\
7  & ID\_Angajat     & ANGAJAT & Număr (PK) & Marca (identificatorul) angajatului \\
8  & Nume            & ANGAJAT & Text       & Numele de familie al angajatului \\
9  & Prenume         & ANGAJAT & Text       & Prenumele angajatului \\
10 & Functie         & ANGAJAT & Text       & Funcția (chelner, bucătar, casier, manager) \\
11 & Telefon         & ANGAJAT & Text       & Numărul de telefon al angajatului \\
12 & Data\_Angajare  & ANGAJAT & Dată/oră   & Data angajării \\
13 & Salariu         & ANGAJAT & Monedă     & Salariul lunar brut \\
14 & ID\_Produs      & PRODUS  & Număr (PK) & Identificator unic al produsului \\
15 & Denumire        & PRODUS  & Text       & Denumirea produsului din meniu \\
16 & Categorie       & PRODUS  & Text       & Categoria (supă, fel principal, desert\dots) \\
17 & Pret            & PRODUS  & Monedă     & Prețul de listă, în lei \\
18 & Disponibil      & PRODUS  & Da/Nu      & Indică dacă produsul este disponibil \\
19 & ID\_Comanda     & COMANDA & Număr (PK) & Identificator unic al comenzii \\
20 & ID\_Client      & COMANDA & Număr (FK) & Clientul care a plasat comanda \\
21 & ID\_Angajat     & COMANDA & Număr (FK) & Chelnerul care a preluat comanda \\
22 & Data\_Comanda   & COMANDA & Dată/oră   & Data plasării comenzii \\
23 & Stare           & COMANDA & Text       & Starea comenzii (În preparare, Servită\dots) \\
24 & Metoda\_Plata   & COMANDA & Text       & Metoda de plată (card, numerar) \\
25 & ID\_Detaliu     & DETALIU\_COMANDA & Număr (PK) & Identificator unic al liniei de comandă \\
26 & ID\_Comanda     & DETALIU\_COMANDA & Număr (FK) & Comanda din care face parte linia \\
27 & ID\_Produs      & DETALIU\_COMANDA & Număr (FK) & Produsul comandat \\
28 & Cantitate       & DETALIU\_COMANDA & Număr      & Cantitatea comandată \\
29 & Pret\_Unitar    & DETALIU\_COMANDA & Monedă     & Prețul unitar la momentul comenzii \\
\end{longtable}
\end{center}

\subsection{Modelul relațional al datelor}

Analiza dependențelor funcționale și eliminarea atributelor redundante au condus la următoarea structură relațională a bazei de date. Cheile primare sunt subliniate, iar cheile externe sunt precedate de simbolul „\#'':

\begin{quote}
\footnotesize\ttfamily
CLIENT (\pk{ID\_Client}, Nume, Prenume, Telefon, Email, Oras)\\[2pt]
ANGAJAT (\pk{ID\_Angajat}, Nume, Prenume, Functie, Telefon, Data\_Angajare, Salariu)\\[2pt]
PRODUS (\pk{ID\_Produs}, Denumire, Categorie, Pret, Disponibil)\\[2pt]
COMANDA (\pk{ID\_Comanda}, \fk{ID\_Client}, \fk{ID\_Angajat}, Data\_Comanda, Stare, Metoda\_Plata)\\[2pt]
DETALIU\_COMANDA (\pk{ID\_Detaliu}, \fk{ID\_Comanda}, \fk{ID\_Produs}, Cantitate, Pret\_Unitar)
\end{quote}

În tabela \texttt{COMANDA}, atributele \texttt{ID\_Client} și \texttt{ID\_Angajat} sunt chei externe care realizează legătura cu tabelele \texttt{CLIENT}, respectiv \texttt{ANGAJAT}. În tabela de legătură \texttt{DETALIU\_COMANDA}, cheile externe \texttt{ID\_Comanda} și \texttt{ID\_Produs} asociază fiecare linie unei comenzi și unui produs, rezolvând relația M:N dintre comenzi și produse.

\subsection{Normalizarea datelor}

Structura relațională propusă respectă regulile primelor trei forme normale (3NF):

\begin{itemize}[leftmargin=1.4em,itemsep=2pt]
  \item \textbf{Forma normală 1 (1NF)} — toate atributele conțin valori atomice (numele și prenumele sunt separate, fiecare linie de comandă conține un singur produs cu o singură cantitate); nu există grupuri repetitive în cadrul unei înregistrări;
  \item \textbf{Forma normală 2 (2NF)} — fiecare tabelă are o cheie primară unică, iar toate atributele non-cheie depind complet de aceasta. În special, descompunerea comenzii în \texttt{COMANDA} (antet) și \texttt{DETALIU\_COMANDA} (linii) elimină dependențele parțiale care ar apărea dacă produsele ar fi stocate direct în comandă;
  \item \textbf{Forma normală 3 (3NF)} — nu există dependențe tranzitive între atributele non-cheie. Datele descriptive ale clientului, ale angajatului și ale produsului sunt păstrate o singură dată, în tabelele proprii, iar comenzile le referențiază prin chei externe.
\end{itemize}

\begin{sloppypar}
O decizie de proiectare importantă este păstrarea atributului \texttt{Pret\_Unitar} în tabela \texttt{DETALIU\_COMANDA}, deși prețul există și în \texttt{PRODUS}. Aceasta nu reprezintă o redundanță, ci o necesitate funcțională: prețul din meniu se poate modifica în timp, iar valoarea comenzilor deja încasate trebuie să rămână neschimbată. Astfel, \texttt{Pret\_Unitar} înregistrează prețul \emph{istoric}, de la momentul comenzii.
\end{sloppypar}

\subsection{Descrierea tabelelor bazei de date}

Aplicația conține cinci tabele, redate în \emph{Anexa~1}, care stochează datele necesare gestiunii activității restaurantului:

\begin{itemize}[leftmargin=1.4em,itemsep=2pt]
  \item \textbf{CLIENT} — conține datele de identificare și de contact ale clienților restaurantului;
  \item \textbf{ANGAJAT} — conține datele personalului (nume, funcție, contact, data angajării, salariu), inclusiv chelnerii care preiau comenzile;
  \item \textbf{PRODUS} — reprezintă meniul restaurantului: denumirea, categoria, prețul de listă și disponibilitatea fiecărui produs;
  \item \textbf{COMANDA} — antetul comenzilor: clientul, chelnerul, data, starea și metoda de plată;
  \item \textbf{DETALIU\_COMANDA} — liniile comenzilor, fiecare cu produsul, cantitatea și prețul unitar; este tabela de legătură care detaliază conținutul fiecărei comenzi.
\end{itemize}

\subsection{Diagrama entitate–relație realizată în Access}

În Microsoft Access, relațiile dintre tabele au fost definite în fereastra \emph{Relationships}, cu integritate referențială activată. Diagrama rezultată (redată mai jos) confirmă modelul conceptual: cele patru relații de tip 1:N pornesc din tabelele de bază către \texttt{COMANDA} și \texttt{DETALIU\_COMANDA}.

\captura{rel_access}{Diagrama relațiilor dintre tabele în Microsoft Access}{0.9}

\subsection{Descrierea ecranelor}

Lista ecranelor (formularelor) este redată în \emph{Anexa~2}; ele permit introducerea, actualizarea și vizualizarea datelor gestionate de sistem. Aplicația conține cinci ecrane:

\begin{enumerate}[leftmargin=1.6em,itemsep=2pt]
  \item \textbf{Ecran Clienți} (\texttt{frmClient}) — formular pentru adăugarea și editarea clienților;
  \item \textbf{Ecran Angajați} (\texttt{frmAngajat}) — formular de evidență a personalului;
  \item \textbf{Ecran Meniu / Produse} (\texttt{frmProdus}) — formular pentru gestiunea produselor din meniu și a disponibilității lor;
  \item \textbf{Ecran Comenzi} (\texttt{frmComanda}) — formularul principal de lucru; include două liste derulante (\emph{combo box}) conectate la tabelele \texttt{CLIENT} și \texttt{ANGAJAT}, precum și un subformular pentru introducerea liniilor de comandă (produs și cantitate);
  \item \textbf{Meniu principal} (\texttt{frmMeniuPrincipal}) — formular de tip \emph{switchboard}, cu butoane de comandă pentru deschiderea rapidă a celorlalte ecrane și a rapoartelor.
\end{enumerate}

\subsection{Descrierea interogărilor}

Lista interogărilor este prezentată în \emph{Anexa~3}. Aplicația conține cinci interogări:

\leadin{Interogarea 1 — Comenzi în derulare.} Afișează comenzile aflate în pregătire (neservite).
\begin{minted}{sql}
SELECT ID_Comanda, ID_Client, Data_Comanda, Stare, Metoda_Plata
FROM COMANDA
WHERE Stare = "In preparare"
ORDER BY Data_Comanda;
\end{minted}

\leadin{Interogarea 2 — Comenzi cu valoare ridicată.} Calculează valoarea fiecărei comenzi (din liniile sale) și reține doar comenzile care depășesc 100 lei.
\begin{minted}{sql}
SELECT COMANDA.ID_Comanda, COMANDA.ID_Client,
       Format(SUM(DETALIU_COMANDA.Cantitate*DETALIU_COMANDA.Pret_Unitar),"#,##0"" lei""") AS Valoare_Comanda
FROM COMANDA INNER JOIN DETALIU_COMANDA
     ON COMANDA.ID_Comanda = DETALIU_COMANDA.ID_Comanda
GROUP BY COMANDA.ID_Comanda, COMANDA.ID_Client
HAVING SUM(DETALIU_COMANDA.Cantitate*DETALIU_COMANDA.Pret_Unitar) >= 100
ORDER BY SUM(DETALIU_COMANDA.Cantitate*DETALIU_COMANDA.Pret_Unitar) DESC;
\end{minted}

\leadin{Interogarea 3 — Vânzări pe angajat.} Pentru fiecare chelner, numără comenzile preluate și însumează încasările aduse (interogare cu join pe trei tabele și grupare).
\begin{minted}{sql}
SELECT ANGAJAT.Nume, ANGAJAT.Prenume,
       COUNT(*) AS Numar_Comenzi, Format(SUM(V.Valoare_Comanda),"#,##0"" lei""") AS Valoare_Totala
FROM ANGAJAT INNER JOIN
  (SELECT COMANDA.ID_Angajat, COMANDA.ID_Comanda,
          SUM(DETALIU_COMANDA.Cantitate*DETALIU_COMANDA.Pret_Unitar) AS Valoare_Comanda
   FROM COMANDA INNER JOIN DETALIU_COMANDA
        ON COMANDA.ID_Comanda = DETALIU_COMANDA.ID_Comanda
   GROUP BY COMANDA.ID_Angajat, COMANDA.ID_Comanda) AS V
  ON ANGAJAT.ID_Angajat = V.ID_Angajat
GROUP BY ANGAJAT.Nume, ANGAJAT.Prenume
ORDER BY SUM(V.Valoare_Comanda) DESC;
\end{minted}

\leadin{Interogarea 4 — Top produse.} Clasează produsele din meniu după cantitatea vândută și încasările generate.
\begin{minted}{sql}
SELECT PRODUS.Denumire, PRODUS.Categorie,
       SUM(DETALIU_COMANDA.Cantitate) AS Bucati_Vandute,
       Format(SUM(DETALIU_COMANDA.Cantitate*DETALIU_COMANDA.Pret_Unitar),"#,##0"" lei""") AS Incasari
FROM PRODUS INNER JOIN DETALIU_COMANDA
     ON PRODUS.ID_Produs = DETALIU_COMANDA.ID_Produs
GROUP BY PRODUS.Denumire, PRODUS.Categorie
ORDER BY SUM(DETALIU_COMANDA.Cantitate) DESC;
\end{minted}

\leadin{Interogarea 5 — Valoare pe client.} Pentru fiecare client, numără comenzile și însumează suma cheltuită.
\begin{minted}{sql}
SELECT CLIENT.Nume, CLIENT.Prenume, CLIENT.Oras,
       COUNT(*) AS Numar_Comenzi, Format(SUM(V.Valoare_Comanda),"#,##0"" lei""") AS Total_Cheltuit
FROM CLIENT INNER JOIN
  (SELECT COMANDA.ID_Client, COMANDA.ID_Comanda,
          SUM(DETALIU_COMANDA.Cantitate*DETALIU_COMANDA.Pret_Unitar) AS Valoare_Comanda
   FROM COMANDA INNER JOIN DETALIU_COMANDA
        ON COMANDA.ID_Comanda = DETALIU_COMANDA.ID_Comanda
   GROUP BY COMANDA.ID_Client, COMANDA.ID_Comanda) AS V
  ON CLIENT.ID_Client = V.ID_Client
GROUP BY CLIENT.Nume, CLIENT.Prenume, CLIENT.Oras
ORDER BY SUM(V.Valoare_Comanda) DESC;
\end{minted}

\subsection{Descrierea rapoartelor}

Lista rapoartelor este prezentată în \emph{Anexa~4}. Aplicația conține cinci rapoarte:

\begin{enumerate}[leftmargin=1.6em,itemsep=2pt]
  \item \textbf{Raport Meniu} (\texttt{rptMeniu}) — listează produsele din meniu, ordonate pe categorii, cu prețul și disponibilitatea fiecăruia;
  \item \textbf{Raport Registru Clienți} (\texttt{rptClienti}) — generat din tabela \texttt{CLIENT}, oferă lista completă cu datele de contact ale clienților;
  \item \textbf{Raport Comenzi Active} (\texttt{rptComenziActive}) — bazat pe Interogarea~1, listează comenzile aflate în derulare;
  \item \textbf{Raport Performanță Angajați} (\texttt{rptPerformantaAngajati}) — bazat pe Interogarea~3, prezintă numărul de comenzi și încasările fiecărui chelner, cu un total general în subsol;
  \item \textbf{Raport Vânzări pe Client} (\texttt{rptVanzariClient}) — bazat pe Interogarea~5, sintetizează sumele cheltuite de fiecare client și oferă totalul general al încasărilor.
\end{enumerate}

\subsection{Schema aplicației}

Obiectele aplicației sunt accesate dintr-un meniu principal (\emph{switchboard}), din care se deschid cele patru ecrane de date și cele cinci rapoarte. Structura de navigare este redată în Fig.~\ref{fig:schema_app}.

\begin{figure}[H]\centering
\begin{tikzpicture}[
  font=\footnotesize,
  root/.style={draw,rounded corners=2pt,fill=gray!15,align=center,minimum width=42mm,minimum height=10mm,inner sep=3pt},
  grp/.style={draw,rounded corners=2pt,fill=gray!10,align=center,minimum width=24mm,minimum height=7mm,inner sep=2pt,font=\bfseries},
  leaf/.style={draw,rounded corners=1pt,fill=white,anchor=west,minimum width=30mm,minimum height=6mm,inner xsep=5pt,font=\ttfamily\footnotesize},
  ln/.style={draw,-}]
  % root + group headers
  \node[root] (sw) at (4.7,1.7) {\textbf{Meniu principal}\\(frmMeniuPrincipal)};
  \node[grp] (forms) at (1.0,0) {Ecrane};
  \node[grp] (reps)  at (8.0,0) {Rapoarte};
  \draw[ln] (sw.south) -- (forms.north);
  \draw[ln] (sw.south) -- (reps.north);
  % ecrane (left): vertical bus + horizontal stubs => no crossing lines.
  % Leaves are west-anchored (natural width) so long names never overflow.
  \node[leaf] (f1) at (1.4,-1.05) {frmClient};
  \node[leaf] (f2) at (1.4,-1.85) {frmAngajat};
  \node[leaf] (f3) at (1.4,-2.65) {frmProdus};
  \node[leaf] (f4) at (1.4,-3.45) {frmComanda};
  \draw[ln] (forms.south) -- (1.0,-3.45);
  \foreach \n in {f1,f2,f3,f4} \draw[ln] (1.0,0 |- \n.west) -- (\n.west);
  % rapoarte (right)
  \node[leaf] (r1) at (8.4,-1.05) {rptMeniu};
  \node[leaf] (r2) at (8.4,-1.85) {rptClienti};
  \node[leaf] (r3) at (8.4,-2.65) {rptComenziActive};
  \node[leaf] (r4) at (8.4,-3.45) {rptPerformantaAngajati};
  \node[leaf] (r5) at (8.4,-4.25) {rptVanzariClient};
  \draw[ln] (reps.south) -- (8.0,-4.25);
  \foreach \n in {r1,r2,r3,r4,r5} \draw[ln] (8.0,0 |- \n.west) -- (\n.west);
\end{tikzpicture}
\caption{Schema de navigare a aplicației}
\label{fig:schema_app}
\end{figure}
