Differences

This shows you the differences between two versions of the page.

Link to this comparison view

poo-ca-cd:teme:2025:b73f56dc-17a1-42ac-bd7e-d57f3caaf9fd:tema-2 [2025/10/02 09:21]
valentin.carauleanu [Restricții]
poo-ca-cd:teme:2025:b73f56dc-17a1-42ac-bd7e-d57f3caaf9fd:tema-2 [2025/10/02 12:07] (current)
valentin.carauleanu [Customer Impact]
Line 103: Line 103:
 <note tip> <note tip>
 Câmpul **description** este opțional. </​note>​ Câmpul **description** este opțional. </​note>​
 +
 +==== Rezumat ====
 +{{:​poo-ca-cd:​teme:​2025:​b73f56dc-17a1-42ac-bd7e-d57f3caaf9fd:​types.png?​800|}}
 +
 +
  
 ==== 1. BUG  ==== ==== 1. BUG  ====
Line 550: Line 555:
 </​code>​ </​code>​
 </​spoiler>​ </​spoiler>​
 +\\
  
 3. Un **Reporter** nu poate comenta dacă ticket-ul are status **CLOSED**. În cazul în care se încearcă comentarea unui ticket cu status **CLOSED**, comanda este respinsă: 3. Un **Reporter** nu poate comenta dacă ticket-ul are status **CLOSED**. În cazul în care se încearcă comentarea unui ticket cu status **CLOSED**, comanda este respinsă:
Line 563: Line 569:
 </​code>​ </​code>​
 </​spoiler>​ </​spoiler>​
 +\\
 4. Conținutul comentariului trebuie să aibă minim **10 caractere**. Dacă este mai mic, comanda este respinsă: 4. Conținutul comentariului trebuie să aibă minim **10 caractere**. Dacă este mai mic, comanda este respinsă:
  
Line 576: Line 582:
 </​code>​ </​code>​
 </​spoiler>​ </​spoiler>​
 +\\
 5. Un **Developer** poate comenta doar pe ticketele care îi sunt atribuite. Dacă un developer încearcă să comenteze un ticket care nu îi este atribuit, comanda este respinsă: 5. Un **Developer** poate comenta doar pe ticketele care îi sunt atribuite. Dacă un developer încearcă să comenteze un ticket care nu îi este atribuit, comanda este respinsă:
  
Line 589: Line 595:
 </​code>​ </​code>​
 </​spoiler>​ </​spoiler>​
 +\\
 6. Un **Reporter** poate comenta doar pe ticketele pe care le-a raportat. Dacă un reporter încearcă să comenteze un ticket pe care nu l-a raportat, comanda este respinsă: 6. Un **Reporter** poate comenta doar pe ticketele pe care le-a raportat. Dacă un reporter încearcă să comenteze un ticket pe care nu l-a raportat, comanda este respinsă:
 +\\
  
 <spoiler Output eroare> <spoiler Output eroare>
Line 825: Line 832:
  
 <note tip>  ​ <note tip>  ​
-* Odată atribuit, statusul unui ticket devine **IN_PROGRESS**. ​  +  ​* Odată atribuit, statusul unui ticket devine **IN_PROGRESS**. ​  
-* Se garantează că ID-ul ticket-ului există.  ​+  * Se garantează că ID-ul ticket-ului există.  ​
 </​note>  ​ </​note>  ​
  
Line 840: Line 847:
 **Nu există output.** **Nu există output.**
  
 +===== undoAssignTicket =====
 +
 +**Disponibilă pentru:** **Developer**
 +
 +**Descriere:​**
 +Developer-ul realizează că nu poate rezolva un ticket și decide să renunțe, pentru a fi reatribuit de altcineva.
 +
 +==== Restricții ====
 +
 +1. Un ticket poate fi „de-asignat” doar dacă are statusul **IN_PROGRESS**. În cazul în care un developer încearcă să renunțe la un ticket cu alt status, comanda este respinsă:
 +
 +<spoiler Output eroare>  ​
 +<code json>
 +{
 +  "​command":​ "​undoAssign",​
 +  "​username":​ "​user_name",​
 +  "​timestamp":​ "​YYYY-MM-DD",​
 +  "​error":​ "Only IN_PROGRESS tickets can be unassigned."​
 +}
 +</​code>  ​
 +</​spoiler>  ​
 +
 +<note tip>  ​
 +  * Se garantează că ID-ul ticket-ului pentru care se încearcă „de-asignarea” există.  ​
 +  * Se garantează că ticket-ul este atribuit developerului care inițiază comanda.  ​
 +  * În urma „de-asignării”,​ statusul ticket-ului revine la **OPEN**.
 +  * Operația rămâne în istoric. Pentru detalii suplimentare,​ vezi sectiunea **viewTicketHistory**.
 +</​note>  ​
 +
 +\\
 +**Exemplu Input:** <spoiler Exemplu input complet> <code json>
 +{
 +"​command":​ "​undoAssign",​
 +"​username":​ "​dev_one",​
 +"​ticketID":​ 0,
 +"​timestamp":​ "​2025-09-22"​
 +} </​code>​ </​spoiler>​
 +\\
 +**Nu există output.**
 +
 +===== changeStatus =====
 +
 +**Disponibilă pentru:** **Developer**
 +
 +**Descriere:​**
 +Permite unui developer să modifice statusul unui ticket atribuit lui.
 +
 +==== Restricții ====
 +
 +1. Ticketul trebuie să fie atribuit developerului care face schimbarea. În cazul în care un developer încearcă să schimbe statusul unui ticket care nu îi este atribuit, comanda este respinsă:
 +
 +<spoiler Output eroare>  ​
 +<code json>
 +{
 +  "​command":​ "​changeStatus",​
 +  "​username":​ "​user_name",​
 +  "​timestamp":​ "​YYYY-MM-DD",​
 +  "​error":​ "​Ticket <id> is not assigned to developer <​developer_name>​."​
 +}
 +</​code>  ​
 +</​spoiler>  ​
 +
 +<note tip>  ​
 +  * Sunt permise doar următoarele tranziții de status: **IN_PROGRESS → RESOLVED → CLOSED**. Nu vor exista excepții în teste. ​
 +  </​note>  ​
 +
 +\\
 +**Exemplu Input:** <spoiler Exemplu input complet> <code json>
 +{
 +"​command":​ "​changeStatus",​
 +"​username":​ "​dev_one",​
 +"​ticketID":​ 0,
 +"​timestamp":​ "​2025-09-23"​
 +} </​code>​ </​spoiler>​
 +\\
 +**Nu există output.**
 +
 +===== undoChangeStatus =====
 +
 +**Disponibilă pentru:** **Developer**
 +
 +**Descriere:​**
 +Developer-ul realizează că a făcut o greșeală și decide să reîntoarcă un ticket la statusul anterior.
 +
 +==== Restricții ====
 +
 +1. Ticketul trebuie să fie atribuit developerului care face schimbarea. În cazul în care un developer încearcă să reîntoarcă statusul unui ticket care nu îi este atribuit, comanda este respinsă:
 +
 +<spoiler Output eroare>  ​
 +<code json>
 +{
 +  "​command":​ "​undoChangeStatus",​
 +  "​username":​ "​user_name",​
 +  "​timestamp":​ "​YYYY-MM-DD",​
 +  "​error":​ "​Ticket <id> is not assigned to developer <​developer_name>​."​
 +}
 +</​code>  ​
 +</​spoiler>  ​
 +
 +<note tip>  ​
 +
 +  * Sunt permise doar următoarele tranziții de status: **RESOLVED → IN_PROGRESS**,​ **CLOSED → RESOLVED**. Nu vor exista excepții în teste. ​
 + 
 +  * Operația rămâne în istoric.
 +  </​note>  ​
 +
 +\\
 +**Exemplu Input:** <spoiler Exemplu input complet> <code json>
 +{
 +"​command":​ "​undoChangeStatus",​
 +"​username":​ "​dev_one",​
 +"​ticketID":​ 0,
 +"​timestamp":​ "​2025-09-24"​
 +} </​code>​ </​spoiler>​
 +\\
 +**Nu există output.**
 +
 +===== viewAssignedTickets =====
 +
 +**Disponibilă pentru:** **Developer**
 +
 +**Descriere:​** Afișează toate ticketele atribuite developerului curent.
 +
 +<note tip>
 +  * Sortarea se face după **businessPriority** (CRITICAL > HIGH > MEDIUM > LOW), apoi după **createdAt** crescător, apoi după **id** crescător.
 +</​note>​
 +
 +
 +\\
 +**Exemplu Input:** <spoiler Exemplu input complet> <code json>
 +{
 +"​command":​ "​viewAssignedTickets",​
 +"​username":​ "​dev_one",​
 +"​timestamp":​ "​2025-09-25"​
 +} </​code>​ </​spoiler>​
 +
 +\\
 +**Exemplu Output:** <spoiler Exemplu output complet> <code json>
 +{
 +"​command":​ "​viewAssignedTickets",​
 +"​username":​ "​dev_one",​
 +"​timestamp":​ "​2025-09-25",​
 +"​assignedTickets":​ [
 +{
 +"​id":​ 0,
 +"​type":​ "​BUG",​
 +"​title":​ "Crash on settings page",
 +"​businessPriority":​ "​HIGH",​
 +"​status":​ "​IN_PROGRESS",​
 +"​createdAt":​ "​2025-09-10",​
 +"​assignedAt":​ "",​
 +"​reportedBy":​ "​cleopatra",​
 +"​comments":​ [
 +{
 +"​author":​ "​dev_one",​
 +"​content":​ "I am looking into this issue.",​
 +"​createdAt":​ "​2025-09-10"​
 +},
 +{
 +"​author":​ "​reporter_one",​
 +"​content":​ "​Please prioritize this bug.",
 +"​createdAt":​ "​2025-09-11"​
 +}
 +]
 +},
 +{
 +"​id":​ 2,
 +"​type":​ "​FEATURE_REQUEST",​
 +"​title":​ "Add dark mode",
 +"​businessPriority":​ "​MEDIUM",​
 +"​status":​ "​RESOLVED",​
 +"​createdAt":​ "​2025-09-12",​
 +"​assignedAt":​ "",​
 +"​reportedBy":​ "​user123",​
 +"​comments":​ []
 +}
 +]
 +} </​code>​ </​spoiler>​
 +
 +===== viewTickets =====
 +
 +**Disponibilă pentru:** **Developer**,​ **Manager**,​ **Reporter**
 +
 +**Descriere:​**
 +Afișează ticketele din sistem în funcție de rolul utilizatorului curent.
 +
 +==== Restricții ====
 +1. **Developer**:​ vede toate ticketele cu status **OPEN** din milestone-urile la care este repartizat (indiferent dacă și le poate atribui).
 +  ​
 +2. **Manager**:​ vede toate ticketele din sistem.  ​
 +
 +3. **Reporter**:​ vede doar ticketele raportate de el (ticketele anonime sunt excluse).  ​
 +
 +<note tip> ​
 + 
 +  * Rezultatele sunt sortate după **createdAt** (de la cele mai vechi la cele mai noi), iar în caz de egalitate după **id** crescător.
 +
 +</​note>  ​
 +
 +\\
 +**Exemplu Input:** <spoiler Exemplu input complet> <code json>
 +{
 +"​command":​ "​viewTickets",​
 +"​username":​ "​manager_one",​
 +"​timestamp":​ "​2025-09-25"​
 +} </​code>​ </​spoiler>​
 +
 +\\
 +**Exemplu Output:** <spoiler Exemplu output complet> <code json>
 +{
 +"​command":​ "​viewTickets",​
 +"​username":​ "​dev_one",​
 +"​timestamp":​ "​2025-09-25",​
 +"​tickets":​ [
 +{
 +"​id":​ 0,
 +"​type":​ "​BUG",​
 +"​title":​ "Crash on settings page",
 +"​businessPriority":​ "​HIGH",​
 +"​status":​ "​IN_PROGRESS",​
 +"​createdAt":​ "​2025-09-10",​
 +"​solvedAt":​ "",​
 +"​assignedAt":​ "​2025-09-21",​
 +"​assignedTo":​ "​dev_one",​
 +"​reportedBy":​ "​cleopatra",​
 +"​comments":​ [
 +{
 +"​author":​ "​dev_one",​
 +"​content":​ "I am looking into this issue.",​
 +"​createdAt":​ "​2025-09-10"​
 +},
 +{
 +"​author":​ "​manager_gabriel",​
 +"​content":​ "​Please prioritize this bug.",
 +"​createdAt":​ "​2025-09-11"​
 +}
 +]
 +},
 +{
 +"​id":​ 3,
 +"​type":​ "​BUG",​
 +"​title":​ "UI glitch on dashboard",​
 +"​businessPriority":​ "​LOW",​
 +"​status":​ "​OPEN",​
 +"​createdAt":​ "​2025-09-20",​
 +"​solvedAt":​ "",​
 +"​reportedBy":​ "",​
 +"​comments":​ []
 +}
 +]
 +} </​code>​ </​spoiler>​
 +
 +===== viewMilestones =====
 +
 +**Disponibilă pentru:** **Manager**,​ **Developer**
 +
 +**Descriere:​** Afișează milestone-urile din sistem în funcție de rolul utilizatorului curent.
 +
 +==== Restricții ====
 +1. **Manager**:​ vede toate milestone-urile create de el.
 +
 +2. **Developer**:​ vede toate milestone-urile la care este atribuit.
 +
 +
 +<note tip>
 +  * Milestone-urile sunt afișate crescător după **dueDate**,​ iar în caz de egalitate lexicografic crescător după `name`.  ​
 +</​note>​
 +  ​
 +<note warning> ​
 +  * Când un milestone devine inactiv (ultimul ticket devine CLOSED), **overdueBy** și **daysUntilDue** rămân blocate.
 +
 +  * Exemplu: un milestone are **dueDate** pe 20 oct. Pe 18 oct ultimul ticket este închis. Comanda **viewMilestones** de pe 21 octombrie va afișa **daysUntilDue = 3** și **overdueBy = 0**. 
 +</​note>​
 +
 +<spoiler **completionPercentage**>​
 +\\
 +Calculat ca raportul dintre numărul de tickete **CLOSED** și numărul total de tickete din milestone.  ​
 +Valoare de tip **Double**, afișată cu **2 zecimale**.
 +\\
 +</​spoiler>​
 +
 +<spoiler **daysUntilDue**>​
 +\\
 +Numărul de zile rămase până la **dueDate**.  ​
 +Dacă **dueDate** este în trecut, valoarea este **0**.  ​
 +**Formulă:​** **dueDate - currentDay + 1**
 +\\
 +</​spoiler>​
 +
 +
 +<spoiler **overdueBy**>​
 +\\
 +Numărul de zile cu care **dueDate** a fost depășit.  ​
 +Dacă **dueDate** este în viitor, valoarea este **0**.
 +\\
 +</​spoiler>​
 +
 +
 +<spoiler **repartition**>​
 +\\
 +Listă de obiecte ce conțin:
 +  * numele developerilor responsabili pentru milestone  ​
 +  * ID-urile ticketelor atribuite fiecăruia
 +
 +Lista este:
 +  * sortată **descrescător** după numărul de tickete atribuite  ​
 +  * în caz de egalitate, după **username** (ordine alfabetică).
 +\\
 +</​spoiler>​
 +
 +<spoiler **status**>​
 +\\
 +Poate avea două valori:
 +  * **ACTIVE** – dacă există tickete nerezolvate în milestone  ​
 +  * **COMPLETED** – dacă **toate** ticketele sunt **CLOSED**
 +\\
 +</​spoiler>​
 +
 +
 +\\
 +**Exemplu Input:** <spoiler Exemplu input complet> <code json>
 +{
 +"​command":​ "​viewMilestones",​
 +"​username":​ "​username",​
 +"​timestamp":​ "​2025-09-25"​
 +} </​code>​ </​spoiler>​
 +
 +\\
 +**Exemplu Output:** <spoiler Exemplu output complet> <code json>
 +{
 +"​command":​ "​viewMilestones",​
 +"​username":​ "​pm_lead",​
 +"​timestamp":​ "​2025-09-25",​
 +"​milestones":​ [
 +{
 +"​name":​ "​v1.0",​
 +"​blockingFor":​ ["​v2.0"​],​
 +"​dueDate":​ "​2025-10-01",​
 +"​createdAt":​ "​2025-09-15",​
 +"​tickets":​ [0, 1, 2],
 +"​assignedDevs":​ ["​dev_one",​ "​dev_two"​],​
 +"​createdBy":​ "​gabriel_manager",​
 +"​status":​ "​ACTIVE",​
 +"​isBlocked":​ false,
 +"​daysUntilDue":​ 6,
 +"​overdueBy":​ 0,
 +"​openTickets":​ [0, 1, 2],
 +"​closedTickets":​ [],
 +"​completionPercentage":​ 0.00,
 +"​repartition":​ [
 +{
 +"​developer":​ "​dev_one",​
 +"​assignedTickets":​ [1]
 +},
 +{
 +"​developer":​ "​dev_two",​
 +"​assignedTickets":​ [2]
 +},
 +{
 +"​developer":​ "​dev_three",​
 +"​assignedTickets":​ []
 +}
 +]
 +}
 +]
 +} </​code>​ </​spoiler>​
 +
 +===== viewNotifications =====
 +
 +**Disponibilă pentru:** **Developer**,​ **Reporter**
 +
 +**Descriere:​**
 +Afișează toate notificările primite de utilizator.
 +
 +==== Restricții ====
 +
 +<note tip>  ​
 +  * Notificările sunt afișate în ordinea primirii (**cele mai vechi primele**). În caz de egalitate, în ordine lexicografică după conținut.
 +
 +  * După vizualizare,​ notificările sunt șterse din sistem.  ​
 +</​note>  ​
 +
 +\\
 +**Exemplu Input:** <spoiler Exemplu input complet> <code json>
 +{
 +"​command":​ "​viewNotifications",​
 +"​username":​ "​user_name",​
 +"​timestamp":​ "​2025-09-25"​
 +} </​code>​ </​spoiler>​
 +
 +\\
 +**Exemplu Output:** <spoiler Exemplu output complet> <code json>
 +{
 +"​command":​ "​viewNotifications",​
 +"​username":​ "​user_name",​
 +"​timestamp":​ "​2025-09-25",​
 +"​notifications":​ [
 +"<​Notification 1>",​
 +"<​Notification 2>",​
 +"<​Notification 3>"
 +]
 +} </​code>​ </​spoiler>​
 +
 +\\
 +
 +===== viewTicketHistory =====
 +
 +**Disponibilă pentru:** **Developer**,​ **Manager**
 +
 +**Descriere:​** Un user vede istoricul ticketelor.
 +
 +
 +==== Restricții ====
 +1. Un **Developer** poate vedea istoricul ticketelor pe care le-a avut atribuite (inclusiv cele rezolvate) și parcursul lor (**status changes**, **comments**).
 +
 +2. Un **Manager** poate vedea istoricul ticketelor care au fost în milestone-urile pe care le-a creat, pentru toți developerii implicați.
 +
 +<note tip>  ​
 +  * Rezultatele sunt sortate după data **createdAt**,​ cele mai vechi fiind afișate primele, iar în caz de egalitate după **id**.  ​
 +  * 
 +  * Acțiunile apar în ordinea în care au fost efectuate.  ​
 +</​note>  ​
 +
 +=== Acțiuni posibile ===
 +
 +  * **ASSIGNED** – ticket-ul a fost atribuit unui developer.
 +
 +<spoiler Exemplu JSON>
 +<code json>
 +{
 +  "​action":​ "​ASSIGNED",​
 +  "​by":​ "​developer_name",​
 +  "​timestamp":​ "​YYYY-MM-DD"​
 +}
 +</​code>​
 +</​spoiler>​
 +\\
 +
 +  * **DE-ASSIGNED** – developer-ul a renunțat la ticket.
 +
 +<spoiler Exemplu JSON>
 +<code json>
 +{
 +  "​action":​ "​DE-ASSIGNED",​
 +  "​by":​ "​developer_name",​
 +  "​timestamp":​ "​YYYY-MM-DD"​
 +}
 +</​code>​
 +</​spoiler>​
 +\\
 +
 +  * **STATUS_CHANGED** – status-ul ticket-ului a fost schimbat.
 +
 +<spoiler Exemplu JSON>
 +<code json>
 +{
 +  "​action":​ "​STATUS_CHANGED",​
 +  "​from":​ "​OLD_STATUS",​
 +  "​to":​ "​NEW_STATUS",​
 +  "​by":​ "​developer_name",​
 +  "​timestamp":​ "​YYYY-MM-DD"​
 +}
 +</​code>​
 +</​spoiler>​
 +\\
 +
 +  * **ADDED_TO_MILESTONE** – ticket-ul a fost adăugat într-un milestone.
 +
 +<spoiler Exemplu JSON>
 +<code json>
 +{
 +  "​action":​ "​ADDED_TO_MILESTONE",​
 +  "​milestone":​ "​milestone_name",​
 +  "​by":​ "​manager_name",​
 +  "​timestamp":​ "​YYYY-MM-DD"​
 +}
 +</​code>​
 +</​spoiler>​
 +
 +==== ====
 +\\
 +**Exemplu Input:** <spoiler Exemplu input complet> <code json>
 +{
 +"​command":​ "​viewTicketHistory",​
 +"​username":​ "​dev_one",​
 +"​timestamp":​ "​2025-09-25"​
 +} </​code>​ </​spoiler>​
 +
 +\\
 +**Exemplu Output:** <spoiler Exemplu output complet> <code json>
 +{
 +"​command":​ "​viewTicketHistory",​
 +"​username":​ "​dev_one",​
 +"​timestamp":​ "​2025-09-25",​
 +"​ticketHistory":​ [
 +{
 +"​id":​ 0,
 +"​title":​ "​Ticket 1",
 +"​status":​ "​CLOSED",​
 +"​actions":​ [
 +{
 +"​action":​ "​ASSIGNED",​
 +"​by":​ "​dev_one",​
 +"​timestamp":​ "​2025-09-15"​
 +},
 +{
 +"​action":​ "​STATUS_CHANGED",​
 +"​from":​ "​OPEN",​
 +"​to":​ "​IN_PROGRESS",​
 +"​by":​ "​dev_one",​
 +"​timestamp":​ "​2025-09-15"​
 +},
 +{
 +"​action":​ "​STATUS_CHANGED",​
 +"​from":​ "​IN_PROGRESS",​
 +"​to":​ "​RESOLVED",​
 +"​by":​ "​dev_one",​
 +"​timestamp":​ "​2025-09-18"​
 +},
 +{
 +"​action":​ "​STATUS_CHANGED",​
 +"​from":​ "​RESOLVED",​
 +"​to":​ "​CLOSED",​
 +"​by":​ "​dev_one",​
 +"​timestamp":​ "​2025-09-20"​
 +}
 +],
 +"​comments":​ [
 +{
 +"​author":​ "​dev_one",​
 +"​timestamp":​ "​2025-09-20",​
 +"​message":​ "Fixed the issue."​
 +}
 +]
 +},
 +{
 +"​id":​ 1,
 +"​title":​ "​Ticket 2",
 +"​status":​ "​IN_PROGRESS",​
 +"​actions":​ [
 +{
 +"​action":​ "​ASSIGNED",​
 +"​by":​ "​dev_one",​
 +"​timestamp":​ "​2025-09-22"​
 +},
 +{
 +"​action":​ "​STATUS_CHANGED",​
 +"​from":​ "​OPEN",​
 +"​to":​ "​IN_PROGRESS",​
 +"​by":​ "​dev_one",​
 +"​timestamp":​ "​2025-09-22"​
 +},
 +{
 +"​action":​ "​DE-ASSIGNED",​
 +"​by":​ "​dev_one",​
 +"​timestamp":​ "​2025-09-23"​
 +}
 +],
 +"​comments":​ []
 +}
 +]
 +} </​code>​ </​spoiler>​
 +\\
 +
 +===== search =====
 +
 +
 +**Disponibilă pentru:** **Developer**,​ **Manager**
 +
 +**Descriere:​**
 +Permite căutarea avansată a ticketelor (sau developerilor,​ în cazul managerilor) pe baza unor criterii de filtrare.
 +
 +==== Restricții ====
 +
 +1. Dacă un filtru este invalid pentru rolul utilizatorului,​ comanda este respinsă:
 +
 +<spoiler Output eroare>  ​
 +<code json>
 +{
 +  "​command":​ "​search",​
 +  "​username":​ "​user_name",​
 +  "​timestamp":​ "​YYYY-MM-DD",​
 +  "​error":​ "​Invalid filter <​filter_name>​ for role <​role>​."​
 +}
 +</​code>  ​
 +</​spoiler>  ​
 +\\
 +==== Reguli generale ====
 +  * Rezultatele sunt sortate după createdAt (cele mai vechi primele), apoi după id
 +  * Dacă un filtru nu este specificat → nu se aplică filtrare pe acel câmp
 +  * Dacă nu este specificat niciun filtru → comanda este echivalentă cu viewTickets
 +  * Dacă nu există rezultate → se returnează o listă goală
 +
 +<note warning> ​
 +**Atenție!**
 +Dacă sunt introduse mai multe filtre invalide, comanda va eșua la **primul filtru invalid**.  ​
 +</​note>  ​
 +
 +==== Filtre Developer ====
 +  * Poate căuta: **doar tickete cu status OPEN** din milestone-urile la care este repartizat
 +  * Filtre disponibile:​
 +    * businessPriority
 +    * type
 +    * createdAt
 +    * createdBefore
 +    * createdAfter
 +    * availableForAssignment
 +
 +==== Filtre manager ====
 +  * Poate căuta: **toate ticketele din sistem** și **developerii din subordine**
 +  * Filtre disponibile:​
 +    * toate filtrele Developer
 +    * keywords
 +    * expertiseArea
 +    * seniority
 +    * performanceScoreAbove
 +    * performanceScoreBelow
 +
 +<note warning>
 +**Atenție!**
 +  * keywords este case-insensitive și caută potrivirea parțială sau completă în câmpurile text.
 +
 +  * Nu se aplică pentru câmpuri cu valori predefinite (enums).
 +  ​
 +  * În output, **matchingWords** arată cuvintele cheie găsite ca potrivire pentru keywords
 +
 +</​note>​
 +
 +
 +<note warning>
 +**Atenție!** Dacă **availableForAssignment** = **true**, comanda returnează doar ticketele ce pot fi repartizate developerului curent (în funcție de senioritate,​ expertiză și milestone)
 +</​note>​
 +
 +
 +<note tip>
 +**Tip:**
 +Implementarea căutării trebuie să urmeze **Open-Closed Principle**,​ permițând adăugarea de noi strategii de filtrare fără modificarea codului existent. </​note>​
 +
 +\\
 +**Exemplu Input – Developer:​** <spoiler Exemplu input complet> <code json>
 +{
 +"​command":​ "​search",​
 +"​username":​ "​dev_one",​
 +"​timestamp":​ "​2025-09-26",​
 +"​filters":​ {
 +"​searchType":​ "​TICKET",​
 +"​businessPriority":​ "​HIGH",​
 +"​type":​ "​BUG",​
 +"​createdAfter":​ "​2025-09-01",​
 +"​availableForAssignment":​ true
 +}
 +} </​code>​ </​spoiler>​
 +
 +\\
 +**Exemplu Output – Developer:​** <spoiler Exemplu output complet> <code json>
 +{
 +"​command":​ "​search",​
 +"​username":​ "​dev_one",​
 +"​timestamp":​ "​2025-09-26",​
 +"​searchType":​ "​TICKET",​
 +"​results":​ [
 +{
 +"​id":​ 0,
 +"​type":​ "​BUG",​
 +"​title":​ "Crash on settings page",
 +"​businessPriority":​ "​HIGH",​
 +"​status":​ "​OPEN",​
 +"​createdAt":​ "​2025-09-10",​
 +"​solvedAt":​ "",​
 +"​reportedBy":​ "​cleopatra"​
 +},
 +{
 +"​id":​ 3,
 +"​type":​ "​BUG",​
 +"​title":​ "Data sync failure",​
 +"​businessPriority":​ "​HIGH",​
 +"​status":​ "​OPEN",​
 +"​createdAt":​ "​2025-09-15",​
 +"​solvedAt":​ "",​
 +"​reportedBy":​ ""​
 +}
 +]
 +} </​code>​ </​spoiler>​
 +
 +\\
 +**Exemplu Input – Manager (tickets):​** <spoiler Exemplu input complet> <code json>
 +{
 +"​command":​ "​search",​
 +"​username":​ "​gabriel_manager",​
 +"​timestamp":​ "​2025-09-26",​
 +"​filters":​ {
 +"​searchType":​ "​TICKET",​
 +"​keywords":​ ["​pay",​ "​bug"​],​
 +"​businessPriority":​ "​HIGH",​
 +"​type":​ "​BUG",​
 +"​createdAfter":​ "​2025-09-01"​
 +}
 +} </​code>​ </​spoiler>​
 +
 +\\
 +**Exemplu Output – Manager (tickets):​** <spoiler Exemplu output complet> <code json>
 +{
 +"​command":​ "​search",​
 +"​username":​ "​gabriel_manager",​
 +"​timestamp":​ "​2025-09-26",​
 +"​searchType":​ "​TICKET",​
 +"​results":​ [
 +{
 +"​id":​ 5,
 +"​type":​ "​BUG",​
 +"​title":​ "​Payment gateway error",​
 +"​businessPriority":​ "​HIGH",​
 +"​status":​ "​OPEN",​
 +"​createdAt":​ "​2025-09-12",​
 +"​solvedAt":​ "",​
 +"​reportedBy":​ "​user456",​
 +"​matchingWords":​ ["​payment",​ "​bug"​]
 +}
 +]
 +} </​code>​ </​spoiler>​
 +
 +\\
 +**Exemplu Input – Manager (developers):​** <spoiler Exemplu input complet> <code json>
 +{
 +"​command":​ "​search",​
 +"​username":​ "​gabriel_manager",​
 +"​timestamp":​ "​2025-09-26",​
 +"​filters":​ {
 +"​searchType":​ "​DEVELOPER",​
 +"​expertiseArea":​ "​BACKEND",​
 +"​seniority":​ "​MID",​
 +"​performanceScoreAbove":​ number
 +}
 +} </​code>​ </​spoiler>​
 +
 +\\
 +**Exemplu Output – Manager (developers):​** <spoiler Exemplu output complet> <code json>
 +{
 +"​command":​ "​search",​
 +"​username":​ "​gabriel_manager",​
 +"​timestamp":​ "​2025-09-26",​
 +"​searchType":​ "​DEVELOPER",​
 +"​results":​ [
 +{
 +"​username":​ "​dev_two",​
 +"​expertiseArea":​ "​BACKEND",​
 +"​seniority":​ "​MID",​
 +"​performanceScore":​ number,
 +"​hireDate":​ "​2024-05-10"​
 +}
 +]
 +} </​code>​ </​spoiler>​
 +\\
 +===== generatePerformanceReport =====
 +
 +**Disponibilă pentru:** **Manager**
 +
 +**Descriere:​** Generează raportul lunar de performanță pentru toți developerii din subordinea managerului. În raport sunt incluse toate ticketele rezolvate (status **CLOSED**) în luna anterioară datei curente (preluată din **timestamp**).
 +
 +==== Calculare raport ====
 +
 +Scorul de performanță se calculează diferit pentru fiecare nivel de **seniority**.
 +
 +<spoiler Bonusuri nivel de senioritate>​
 +  * **JUNIOR** → +5  ​
 +  * **MID** → +15  ​
 +  * **SENIOR** → +30  ​
 +</​spoiler>​
 +\\
 +
 +=== Junior Performance ===
 +
 +<spoiler Formula>
 +\\
 +  * juniorPerformance = max(0, 0.5 * closedTickets - ticketDiversityFactor) + seniorityBonus
 +\\
 +</​spoiler>​
 +\\
 +Vom defini **ticketDiversityFactor** ca fiind coeficientul de variație dintre deviația standard și media aritmetică.
 +
 +<spoiler Detalii calcul>
 +  * **averageResolvedTicketType**  ​
 +    <​code>​(bugTickets + featureTickets + uiTickets) / 3</​code>​
 +  * **standardDeviation**  ​
 +    <​code>​sqrt(((bugTickets - avg)^2 + (featureTickets - avg)^2 + (uiTickets - avg)^2) / 3)</​code>​
 +  * **ticketDiversityFactor**  ​
 +    <​code>​standardDeviation / averageResolvedTicketType</​code>​
 +</​spoiler>​
 +
 +
 +
 +=== Mid Performance ===
 +
 +<spoiler Formula>
 +\\
 +  * midPerformance = max(0, 0.5 * closedTickets + 0.7 * highPriorityTickets - 0.3 * averageResolutionTime) + seniorityBonus
 +\\
 +</​spoiler>​
 +\\
 +<spoiler Detalii calcul Mid Performance>​
 +\\
 +  * closedTickets = numărul total de tickete rezolvate
 +  * highPriorityTickets = numărul de tickete rezolvate cu prioritate HIGH sau CRITICAL
 +  * averageResolutionTime = media timpilor de rezolvare (zile)
 +\\
 +</​spoiler>​
 +
 +
 +=== Senior Performance ===
 +
 +<spoiler Formula>
 +  * seniorPerformance = max(0, 0.5 * closedTickets + 1.0 * highPriorityTickets - 0.5 * averageResolutionTime) + seniorityBonus
 +</​spoiler>​
 +\\
 +<spoiler Detalii calcul Senior Performance>​
 +\\
 +  * closedTickets = numărul total de tickete rezolvate
 +  * highPriorityTickets = numărul de tickete rezolvate cu prioritate HIGH sau CRITICAL
 +  * averageResolutionTime = media timpilor de rezolvare (zile)
 +  * Impactul ticketelor cu prioritate ridicată și timpul de rezolvare contează mai mult
 +  * Formula penalizează timpi mari de rezolvare și răsplătește rezolvarea ticketelor importante
 +\\
 +</​spoiler>​
 +
 +
 +=== Metode utile ===
 +Puteti folosi următoarele metode în soluția temei:
 +
 +<spoiler Java code>
 +<code java>
 +public static double averageResolvedTicketType(int bug, int feature, int ui) {
 +    return (bug + feature + ui) / 3.0;
 +}
 +
 +public static double standardDeviation(int bug, int feature, int ui) {
 +    double mean = averageResolvedTicketType(bug,​ feature, ui);
 +    double variance = (Math.pow(bug - mean, 2) + Math.pow(feature - mean, 2) + Math.pow(ui - mean, 2)) / 3.0;
 +    return Math.sqrt(variance);​
 +}
 +
 +public static double ticketDiversityFactor(int bug, int feature, int ui) {
 +    double mean = averageResolvedTicketType(bug,​ feature, ui);
 +
 +    // dacă nu există tickete, diversitatea este 0
 +    if (mean == 0.0) {
 +        return 0.0;
 +    }
 +
 +    double std = standardDeviation(bug,​ feature, ui);
 +    return std / mean;
 +}
 +</​code>​
 +</​spoiler>​
 +
 +\\
 +**Exemplu Input:**
 +<spoiler Exemplu input complet>
 +<code json>
 +{
 +  "​command":​ "​generatePerformanceReport",​
 +  "​username":​ "​gabriel_manager",​
 +  "​timestamp":​ "​2025-09-01"​
 +}
 +</​code>​
 +</​spoiler>​
 +
 +\\
 +**Exemplu Output:**
 +<spoiler Exemplu output complet>
 +<code json>
 +{
 +  "​command":​ "​generatePerformanceReport",​
 +  "​username":​ "​gabriel_manager",​
 +  "​timestamp":​ "​2025-09-01",​
 +  "​report":​ [
 +    {
 +      "​username":​ "​dev_one",​
 +      "​closedTickets":​ 5,
 +      "​averageResolutionTime":​ 4.2,
 +      "​ticketTypes":​ {
 +        "​BUG":​ 3,
 +        "​FEATURE_REQUEST":​ 1,
 +        "​UI_FEEDBACK":​ 1
 +      },
 +      "​ticketPriorities":​ {
 +        "​LOW":​ 1,
 +        "​MEDIUM":​ 2,
 +        "​HIGH":​ 1,
 +        "​CRITICAL":​ 1
 +      },
 +      "​performanceScore":​ 88.56,
 +      "​seniority":​ "​SENIOR"​
 +    },
 +    {
 +      "​username":​ "​dev_two",​
 +      "​closedTickets":​ 3,
 +      "​averageResolutionTime":​ 5.0,
 +      "​ticketTypes":​ {
 +        "​BUG":​ 2,
 +        "​FEATURE_REQUEST":​ 1
 +      },
 +      "​ticketPriorities":​ {
 +        "​LOW":​ 1,
 +        "​MEDIUM":​ 1,
 +        "​HIGH":​ 1
 +      },
 +      "​performanceScore":​ 75.00,
 +      "​seniority":​ "​MID"​
 +    }
 +  ]
 +}
 +</​code>​
 +</​spoiler>​
 +\\
 +
 +
 +===== Ticket Risk =====
 +
 +**Disponibilă pentru:** **Manager**
 +
 +
 +**Descriere:​** Generează un raport pe baza metricii **ticket risk**.
 +
 +**Comanda: generateTicketRiskReport**
 +
 +<note tip>
 +Raportul este creat pe baza **tuturor** ticketelor **OPEN** si **IN_PROGRESS** din sistem, indiferent de managerul care a generat raportul.
 +</​note>​
 +
 +**Calculare:​**
 +\\
 +<spoiler BUG>
 +**Formula:​**  ​
 +**frequency × severityFactor**  ​
 +
 +**Valoare maximă:** 12  ​
 +
 +**Exemplu de calcul:​**  ​
 +<​code>​
 +frequency = ALWAYS (4)  ​
 +severityFactor = SEVERE (3)
 +
 +Risc brut = 4 × 3 = 12  ​
 +Risc final = (12 × 100) / 12 = 100.00
 +</​code>​
 +</​spoiler>​
 +
 +<spoiler FEATURE_REQUEST>​
 +**Formula:​**  ​
 +**businessValue + customerDemand**  ​
 +
 +**Valoare maximă:** 20  ​
 +
 +**Exemplu de calcul:​**  ​
 +<​code>​
 +businessValue = XL (10)  ​
 +customerDemand = HIGH (6)
 +
 +Risc brut = 10 + 6 = 16  ​
 +Risc final = (16 × 100) / 20 = 80.00
 +</​code>​
 +</​spoiler>​
 +
 +<spoiler UI_FEEDBACK>​
 +**Formula:​**  ​
 +**(11 − usabilityScore) × businessValue**  ​
 +
 +**Valoare maximă:** 100  ​
 +
 +**Exemplu de calcul:​**  ​
 +<​code>​
 +usabilityScore = 2  ​
 +businessValue = XL (10)
 +
 +Risc brut = (11 − 2) × 10 = 90  ​
 +Risc final = (90 × 100) / 100 = 90.00
 +</​code>​
 +</​spoiler>​
 +
 +\\
 +În urma raportului, fiecare categorie va avea un **calificativ**:​
 +\\
 +<spoiler Calificative risc>
 +\\
 +^ Interval Risc ^ Calificativ ​    ^
 +| 0 – 24         | **NEGLIJABIL** ​  |
 +| 25 – 49        | **MEDIU** ​       |
 +| 50 – 74        | **SEMNIFICATIV** |
 +| 75 – 100       | **MAJOR** ​       |
 +</​spoiler>​
 +
 +===== =====
 +\\
 +**Exemplu Input:** <spoiler Exemplu input complet> <code json>
 +{
 +"​command":​ "​generateTicketRiskReport",​
 +"​username":​ "​gabriel_manager",​
 +"​timestamp":​ "​2025-09-30"​
 +} </​code>​ </​spoiler>​
 +
 +\\
 +**Exemplu Output:** <spoiler Exemplu output complet> <code json>
 +{
 +"​command":​ "​generateTicketRiskReport",​
 +"​username":​ "​gabriel_manager",​
 +"​timestamp":​ "​2025-09-30",​
 +"​report":​ {
 +"​totalTickets":​ 20,
 +"​ticketsByType":​ {
 +"​BUG":​ 10,
 +"​FEATURE_REQUEST":​ 6,
 +"​UI_FEEDBACK":​ 4
 +},
 +"​ticketsByPriority":​ {
 +"​LOW":​ 5,
 +"​MEDIUM":​ 7,
 +"​HIGH":​ 6,
 +"​CRITICAL":​ 2
 +},
 +"​riskByType":​ {
 +"​BUG":​ "​NEGLIJABIL",​
 +"​FEATURE_REQUEST":​ "​MEDIU",​
 +"​UI_FEEDBACK":​ "​SEMNIFICATIV"​
 +}
 +}
 +} </​code>​ </​spoiler>​
 +\\
 +===== Resolution Efficiency =====
 +
 +**Disponibilă pentru: Manager**
 +
 +**Descriere:​** Evaluează cât de eficientă este echipa în a rezolva tickete. Se vor considera doar tickete în stările **RESOLVED** și **CLOSED**.
 +
 +**Comanda:​**:​ **generateResolutionEfficiencyReport**
 +
 +<note tip>
 +Raportul este creat pe baza **tuturor ticketelor** **CLOSED** si **RESOLVED** din sistem, indiferent de managerul care a generat raportul.
 +</​note>​
 +
 +<spoiler BUG>
 +**Formula:​**  ​
 +
 +(bugFrequency + severityFactor) × 10 / daysToResolve
 +
 +
 +**Valoare maximă:** 70  ​
 +
 +**Exemplu de calcul:​**  ​
 +<​code>​
 +frequency = FREQUENT (3)
 +severityFactor = MODERATE (2)
 +daysToResolve = 2
 +
 +Scor eficiență = (3 + 2) × 10 / 2 = 25
 +Eficiență finală = (25 × 100) / 70 = 35.71
 +</​code>​
 +</​spoiler>​
 +
 +
 +<spoiler FEATURE_REQUEST>​
 +**Formula:​** ​
 +
 +(businessValue + customerDemand) / daysToResolve
 +
 +
 +**Valoare maximă:** 20  ​
 +
 +**Exemplu de calcul:​**  ​
 +<​code>​
 +businessValue = L (6)
 +customerDemand = HIGH (6)
 +daysToResolve = 2
 +
 +Scor eficiență = (6 + 6) / 2 = 6.00
 +Eficiență finală = (6 × 100) / 20 = 30.00
 +</​code>​
 +</​spoiler>​
 +
 +
 +<spoiler UI_FEEDBACK>​
 +**Formula:​**  ​
 +
 +(usabilityScore + businessValue) / 2
 +
 +
 +**Valoare maximă:** 20  ​
 +
 +**Exemplu de calcul:​**  ​
 +<​code>​
 +usabilityScore = 9
 +businessValue = XL (10)
 +
 +Scor eficiență = (9 + 10) / 2 = 9.5
 +Eficiență finală = (9.5 × 100) / 20 = 47.50
 +</​code>​
 +</​spoiler>​
 +\\
 +<note warning>  ​
 +**Atenție!** ​
 +**daysToResolve** = numărul de zile dintre **assignedAt** și data la care ticket-ul a fost marcat ultima dată ca **RESOLVED** sau **CLOSED**. ​
 +</​note>  ​
 +
 +===== =====
 +**Exemplu Input:​** ​
 +<spoiler Exemplu input complet>
 +<code json>
 +{
 +  "​command":​ "​generateResolutionEfficiencyReport",​
 +  "​username":​ "​gabriel_manager",​
 +  "​timestamp":​ "​2025-09-30"​
 +}
 +</​code>​
 +</​spoiler>​
 +\\
 +
 +**Exemplu Output:​** ​
 +<spoiler Exemplu output complet>
 +<code json>
 +{
 +  "​command":​ "​generateResolutionEfficiencyReport",​
 +  "​username":​ "​gabriel_manager",​
 +  "​timestamp":​ "​2025-09-30",​
 +  "​report":​ {
 +    "​totalTickets":​ 20,
 +    "​ticketsByType":​ {
 +      "​BUG":​ 10,
 +      "​FEATURE_REQUEST":​ 6,
 +      "​UI_FEEDBACK":​ 4
 +    },
 +    "​ticketsByPriority":​ {
 +      "​LOW":​ 5,
 +      "​MEDIUM":​ 7,
 +      "​HIGH":​ 6,
 +      "​CRITICAL":​ 2
 +    },
 +    "​efficiencyByType":​ {
 +      "​BUG":​ 65.50,
 +      "​FEATURE_REQUEST":​ 55.30,
 +      "​UI_FEEDBACK":​ 40.25
 +    }
 +  }
 +}
 +</​code>​
 +</​spoiler>​
 +\\
 +===== Customer Impact =====
 +
 +**Disponibilă pentru: Manager**
 +
 +**Descriere:​** Estimează **impactul asupra clienților** al ticketelor.
 +
 +**Comanda:​** **generateCustomerImpactReport**
 +
 +<note tip>
 +Raportul este creat pe baza **tuturor ticketelor** aflate în stările **OPEN** și **IN_PROGRESS**,​ indiferent de managerul care a generat raportul.
 +</​note>​
 +
 +
 +<spoiler BUG>
 +**Formula:​**  ​
 +
 +frequency × businessPriority × severityFactor  ​
 +
 +**Valoare maximă:** 48  ​
 +
 +**Exemplu de calcul:​**  ​
 +<​code>​
 +frequency = ALWAYS (4)  ​
 +businessPriority = CRITICAL (4)  ​
 +severityFactor = SEVERE (3)
 +
 +Impact brut = 4 × 4 × 3 = 48  ​
 +Impact final = (48 × 100) / 48 = 100.00
 +</​code>​
 +</​spoiler>​
 +
 +
 +<spoiler FEATURE_REQUEST>​
 +**Formula:​**  ​
 +
 +businessValue × customerDemand  ​
 +
 +**Valoare maximă:** 100  ​
 +
 +**Exemplu de calcul:​**  ​
 +<​code>​
 +businessValue = M (3)  ​
 +customerDemand = HIGH (6)
 +
 +Impact brut = 3 × 6 = 18  ​
 +Impact final = (18 × 100) / 100 = 18.00
 +</​code>​
 +</​spoiler>​
 +
 +
 +<spoiler UI_FEEDBACK>​
 +**Formula:​**  ​
 +
 +businessValue × usabilityScore  ​
 +
 +**Valoare maximă:** 100  ​
 +
 +**Exemplu de calcul:​**  ​
 +<​code>​
 +businessValue = L (6)  ​
 +usabilityScore = 9
 +
 +Impact brut = 6 × 9 = 54  ​
 +Impact final = (54 × 100) / 100 = 54.00
 +</​code>​
 +</​spoiler>​
 +\\
 +
 +===== =====
 +**Exemplu Input:​** ​
 +<spoiler Exemplu input complet>
 +<code json>
 +{
 +  "​command":​ "​generateCustomerImpactReport",​
 +  "​username":​ "​gabriel_manager",​
 +  "​timestamp":​ "​2025-09-30"​
 +}
 +</​code>​
 +</​spoiler>​
 +\\
 +
 +**Exemplu Output:​** ​
 +<spoiler Exemplu output complet>
 +<code json>
 +{
 +  "​command":​ "​generateCustomerImpactReport",​
 +  "​username":​ "​gabriel_manager",​
 +  "​timestamp":​ "​2025-09-30",​
 +  "​report":​ {
 +    "​totalTickets":​ 20,
 +    "​ticketsByType":​ {
 +      "​BUG":​ 10,
 +      "​FEATURE_REQUEST":​ 6,
 +      "​UI_FEEDBACK":​ 4
 +    },
 +    "​ticketsByPriority":​ {
 +      "​LOW":​ 5,
 +      "​MEDIUM":​ 7,
 +      "​HIGH":​ 6,
 +      "​CRITICAL":​ 2
 +    },
 +    "​customerImpactByType":​ {
 +      "​BUG":​ 75.55,
 +      "​FEATURE_REQUEST":​ 60.05,
 +      "​UI_FEEDBACK":​ 45.02
 +    }
 +  }
 +}
 +</​code>​
 +</​spoiler>​
 +\\
  
poo-ca-cd/teme/2025/b73f56dc-17a1-42ac-bd7e-d57f3caaf9fd/tema-2.1759386092.txt.gz · Last modified: 2025/10/02 09:21 by valentin.carauleanu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0