Table of Contents

Tema 2 - Bug Tracker Pro

Obiective

Descriere

După ce ați încercat, fără succes, să obțineți un job la startup-ul lui Gigelino, ați decis să vă lansați propria aplicație. Întâmplarea a făcut să atrageți atenția unor investitori dispuși să vă finanțeze, însă cu o condiție clară: produsul final trebuie să fie stabil, lipsit de bug-uri majore și să primească feedback pozitiv de la utilizatorii beta.

Pentru a răspunde acestei provocări, veți implementa un sistem de ticket tracking care să vă ajute să:

Dezvoltarea va fi împărțită în două etape principale:

  1. testare și raportare tickete
  2. rezolvare acestora de către echipa de ingineri

Obiectivul vostru este să asigurați o gestionare eficientă a bug-urilor, prioritizarea corectă a sarcinilor și o monitorizare constantă a progresului, astfel încât să prezentați investitorilor un produs final solid și de încredere.

Atenție! Timpul este limitat, iar investitorii nu sunt dispuși să aștepte la nesfârșit.

Deadline-ul pentru livrarea produsului este specificat în scheletul oferit.

Workflow

Dezvoltarea aplicației urmează un ciclu iterativ, alcătuit din următoarele etape:

  1. Perioada de testare: reporterii deschid tickete pentru problemele identificate.
  2. Perioada de dezvoltare: managerii creează milestone-uri, iar developerii își asignează tickete și le rezolvă.
  3. Verificarea stabilității aplicației: se generează un raport de stabilitate și se evaluează progresul.
    1. Dacă produsul este stabil, proiectul se încheie cu succes.
    2. Dacă nu, ciclul este reluat.

Acest workflow se repetă până când produsul atinge un nivel acceptabil de stabilitate sau investitorii decid să își retragă finanțarea.

Astfel, procesul de dezvoltare poate fi modelat sub forma unui automat finit:

Etapele Workflow-ului

1. Perioada de Testare

2. Perioada de Dezvoltare

3. Verificarea Stabilității

Tickete

Aplicația gestionează mai multe tipuri de tickete. Toate tipurile împărtășesc un set comun de câmpuri opționale, care pot fi utilizate dacă sunt relevante pentru context.

Câmpuri comune

Câmp Descriere Tip
id Identificator unic al ticket-ului int
type Tipul ticket-ului string
title Titlu scurt string
businessPriority Nivel de prioritate în cadrul aplicației enum(LOW, MEDIUM, HIGH, CRITICAL)
status Statusul curent al ticketului enum(OPEN, IN_PROGRESS, RESOLVED, CLOSED)
expertiseArea Domeniul de expertiză necesar enum(FRONTEND, BACKEND, DEVOPS, DESIGN, DB)
description Descriere detaliată a problemei sau cererii string

Câmpul description este opțional.

Rezumat

1. BUG

Un BUG reprezintă o problemă tehnică apărută în aplicație.

Câmpuri obligatorii

Câmp Descriere Tip
expectedBehavior Comportamentul așteptat string
actualBehavior Comportamentul observat string
frequency Frecvența apariției enum(RARE, OCCASIONAL, FREQUENT, ALWAYS)
severity Severitatea bug-ului (cât de mult afectează aplicația) enum(MINOR, MODERATE, SEVERE)

Câmpuri opționale

Câmp Descriere Tip
environment Mediu de operare String
errorCode Cod de eroare returnat de aplicație int

Atenție! Doar un ticket de tip BUG poate fi raportat ANONIM.

2. FEATURE_REQUEST

Un ticket de tip FEATURE_REQUEST propune o nouă funcționalitate sau extinderea uneia existente.

Câmpuri obligatorii specifice

Câmp Descriere Valori posibile
businessValue Impact estimat asupra afacerii enum(S, M, L, XL)
customerDemand Cererea clienților pentru această funcționalitate enum(LOW, MEDIUM, HIGH, VERY_HIGH)

3. UI_FEEDBACK

Un ticket de tip UI_FEEDBACK colectează sugestii privind experiența de utilizare.

Câmpuri obligatorii specifice

Câmp Descriere Tip
uiElementId Identificatorul elementului de UI string
businessValue Impact estimat asupra utilizatorilor sau business-ului enum (S, M, L, XL)
usabilityScore Scor de utilizabilitate (scala de la 1 la 10) int

Câmpuri opționale specifice

Câmp Descriere Tip
screenshotUrl Link către o captură de ecran string
suggestedFix Sugestie de îmbunătățire pentru UI string


Sugestie: Fiecare tip de ticket definit în aplicație conține atât câmpuri obligatorii, cât și câmpuri opționale. De aceea, instanțierea și construirea obiectelor trebuie gândită și proiectată cu atenție.

Utilizatori

Aplicația definește trei tipuri de utilizatori, fiecare având roluri și atribute specifice:

Reporter

Reporterul are rolul de a raporta tickete în perioadele de testare, pe baza feedback-ului primit de la clienți și a testării interne. De asemenea, poate primi notificări legate de statusul ticketelor raportate.

Input reporter

Input reporter

[
  {
    "username": "reporter_one",
    "role": "REPORTER",
    "email": "reporter_one@gmail.com"
  },
  {
    "username": "reporter_two",
    "role": "REPORTER",
    "email": "reporter_two@gmail.com"
  }
]

Developer

Developerul se ocupă de rezolvarea ticketelor raportate și poate primi notificări legate de activitatea acestora.

Not all devs are made equal.. De aceea, în funcție de experiența profesională, există 3 niveluri de senioritate care determină accesul acestora la tickete:

Acces la tickete în funcție de senioritate:

Mai mult! Fiecare developer are o specializare:

Acces în funcție de specializare:

Input developer

Input developer

[
  {
    "username": "dev_three",
    "role": "DEVELOPER",
    "email": "dev_three@bugtracker.com", 
    "hireDate": "2022-07-22", 
    "seniority": "JUNIOR",
    "expertiseArea": "FRONTEND"
  },
  {
    "username": "dev_four",
    "role": "DEVELOPER",
    "email": "dev_four@bugtracker.com",
    "hireDate": "2019-11-05",
    "seniority": "MID",
    "expertiseArea": "FULLSTACK"
  }

Sugestie: Toți developerii execută aceleași comenzi, dar senioritatea și expertiza determină dacă o acțiune este permisă. Think of Separation of Concerns.

Manager

Managerul coordonează propria echipa de developeri, creează și gestionează milestone-uri și menține o listă de subordonați reprezentată prin username-urile developerilor pe care îi are în echipă.

Input manager

Input manager

[
  {
    "username": "gabriel_manager",
    "role": "MANAGER",
    "email": "gabriel@bugtracker.com", 
    "hireDate": "2002-02-28", 
    "subordinates": ["dev_one", "dev_two", "dev_three"]
  },
  {
    "username": "cleopatra_manager",
    "role": "MANAGER",
    "email": "cleopatra@bugtracker.com",
    "hireDate": "2003-03-15",
    "subordinates": ["dev_four", "dev_five"]
  }
]

Milestones

Un milestone reprezintă o etapă majoră în dezvoltarea proiectului. Acesta este stabilit de un manager la finalul unei perioade de testare și conține un set de tickete care trebuie rezolvate într-un interval de timp predefinit.

Doar developerii care fac parte din echipa managerului respectiv pot fi atribuiți acelui milestone.

Atributele unui milestone

Mentiuni speciale

1. La fiecare 3 zile după crearea milestone-ului, prioritatea ticketelor din acel milestone crește automat cu o treaptă (ex: LOWMEDIUM, MEDIUMHIGH etc.).

2. Cu o zi calendaristică înainte de dueDate, toate ticketele rămase active în milestone:

  1. devin automat de prioritate CRITICAL
  2. toți developerii atribuiți primesc o notificare.

3. Un milestone poate bloca alte milestone-uri. Dacă un milestone se află în stare de blocare:

  1. bug-urile din milestone-ul blocat nu pot fi rezolvate sau atribuite
  2. regulile de la punctele 1 și 2 nu se aplică (prioritatea ticketelor nu crește, iar acestea nu devin CRITICAL).

4. Dacă un milestone este deblocat cu o zi calendaristică înainte de dueDate, regula de la punctul 2 se aplică.

5. Dacă un milestone este deblocat după dueDate:

  1. toate ticketele rămase devin automat CRITICAL
  2. se trimite o notificare specială developerilor asignați.

Vom defini următoarele convenții:

daysBetween = date2 − date1 + 1, pentru a include ambele zile. O zi calendaristică înainte de YYYY-MM-DD înseamnă întotdeauna ziua anterioară calendaristică.

Exemple: Pentru intervalul 2023-05-01 → 2023-05-10, daysBetween = 10 Dacă dueDate = 2023-05-10, ziua calendaristică anterioară este 2023-05-09

Notificări

Întreaga aplicație este bazată pe un sistem de notificări. Orice acțiune semnificativă (ex: adăugare comentariu, schimbare status ticket, atribuire ticket, creare milestone) va genera o notificare către utilizatorii vizați.

Formatele notificărilor

Formatele notificărilor

Acțiune Cine primește Format notificare
Adăugare comentariu de către Reporter Developerul căruia îi este atribuit ticketul New comment on ticket <id> by reporter <reporter_name>: <comment_content>
Adăugare comentariu de către Developer Reporterul ticketului (dacă nu este anonim) New comment on your ticket <id> by developer <developer_name>: <comment_content>
Ticket trecut la CLOSED, ultimul dintr-un milestone blocant Toți developerii atribuiți milestone-urilor blocate Milestone <milestone_name> is now unblocked as ticket <id> has been CLOSED.
Generare raport de performanță Developerul vizat Your performance score for the month <month_as_lowercase_english_name> is <score>.
Crearea unui Milestone Toți developerii atribuiți milestone-ului New milestone <milestone_name> has been created with due date <due_date>.
Milestone ajuns la o zi de dueDate Toți developerii atribuiți milestone-ului Milestone <milestone_name> is due tomorrow. All unresolved tickete are now CRITICAL.
Milestone deblocat după dueDate Toți developerii atribuiți milestone-ului Milestone <milestone_name> was unblocked after due date. All active tickete are now CRITICAL.

Sugestie: Pentru a gestiona notificările într-un mod scalabil, gândiți-vă la o soluție în care utilizatorii să fie automat informați.

Metrici de Stabilitate a Aplicației

Pe lângă rapoartele de performanță, aplicația generează și rapoarte pe baza unor metrici specifice, calculate în funcție de tipul fiecărui ticket. Fiecare metrică are o formulă dedicată în funcție de tipul de ticket.

Cele 3 metrici cu care vom lucra sunt: Customer Impact, Resolution Efficiency, Ticket Risk.

Convenții de scor (click pentru a deschide)

Convenții de scor (click pentru a deschide)

frequency:
  RARE        = 1
  OCCASIONAL  = 2
  FREQUENT    = 3
  ALWAYS      = 4

businessPriority:
  LOW         = 1
  MEDIUM      = 2
  HIGH        = 3
  CRITICAL    = 4

severityFactor:
  MINOR       = 1
  MODERATE    = 2
  SEVERE      = 3

businessValue:
  S           = 1
  M           = 3
  L           = 6
  XL          = 10

customerDemand:
  LOW         = 1
  MEDIUM      = 3
  HIGH        = 6
  VERY_HIGH   = 10

Pași generali de calcul

1. Pentru fiecare ticket eligibil se calculează scorul brut (baseScore), în funcție de formula asociată.

2. Se face media scorurilor pentru o categorie.

3. Se normalizează rezultatul pe intervalul 0–100.

Cod: Medie pe categorie

Cod: Medie pe categorie

public double calculateAverageImpact(List<Double> scores) {
    return scores.stream().mapToDouble(Double::doubleValue).average().orElse(0.0);
}

Cod: Normalizare rezultat

Cod: Normalizare rezultat

public double calculateImpactFinal(double baseScore, double maxValue) {
    return Math.min(100.0, (baseScore * 100.0) / maxValue);
}

Sugestie: Structura codului ar trebui să permită adăugarea unor metrici noi, fără a altera clasele deja existente.

Code should be open for extension, but closed for modification.

Mai multe detalii, veți găsi la comenzile specifice fiecărei metrici.

Comenzi

Pe parcursul execuției, va trebui să gestionați diverse erori.

Ordinea în care apar în enunț este și ordinea în care trebuie verificate. Astfel, excepția menționată prima va avea întotdeauna prioritate de tratare față de cele care apar mai jos.

1. Utilizator inexistent

Dacă un utilizator trimite o comandă, dar nu există în sistem, comanda este invalidă și trebuie afișată o eroare corespunzătoare.

Output eroare

Output eroare

{
  "command": "command_name",
  "username": "user_name",
  "timestamp": "YYYY-MM-DD",
  "error": "The user <user_name> does not exist."
}

2. Comandă nepermisă pentru rol

Dacă utilizatorul nu are rolul necesar pentru a rula o comandă, aceasta este refuzată cu mesaj de eroare clar.

Output eroare

Output eroare

{
  "command": "command_name",
  "username": "user_name",
  "timestamp": "YYYY-MM-DD",
  "error": "The user does not have permission to execute this command: required role <role_name> <-> user role <user_role>."
}

3. Ordinea tratării

Aceste excepții sunt verificate înainte de orice validări specifice fiecărei comenzi.

Acum putem trece la comenzile aplicatiei.

lostInvestors

Disponibilă pentru: Manager

Descriere: Investitorii și-au pierdut răbdarea și au renunțat la finanțare. Aplicația se închide și nu mai sunt procesate comenzi după acest moment.

Input

Input

{
  "command": "lostInvestors",
  "username": "gabriel_manager",
  "timestamp": "2025-10-20"
}

Nu există output.

reportTicket

Disponibilă pentru: Reporter

Descriere: Reportarea este permisă doar în perioada de testare. Pentru mai multe detalii, consultă secțiunea Perioada de Testare.

Restricții:

1. ID-urile sunt alocate incremental de sistem, începând de la 0.

2. Se garantează că formatul de input este corect (fără câmpuri invalide sau lipsă).

3. Statusul inițial al unui ticket este întotdeauna OPEN.

Raportare într-o perioadă incorectă

Raportare într-o perioadă incorectă

{
"command": "reportTicket",
"username": "user_name",
"timestamp": "YYYY-MM-DD",
"error": "Tickets can only be reported during testing phases."
} 

4 Raportarea anonimă:

Raport anonim invalid

Raport anonim invalid

{
"command": "reportTicket",
"username": "user_name",
"timestamp": "YYYY-MM-DD",
"error": "Anonymous reports are only allowed for tickets of type BUG."
} 


Format Input:

Exemplu input complet

Exemplu input complet

{
"command": "reportTicket",
"timestamp": "2025-09-10",
"type": "BUG",
"username": "reporter_one",
"reportedBy": "cleopatra",
"params": {
"title": "Crash on settings page",
"description": "App crashes when accessing settings.",
"businessPriority": "HIGH",
"frequency": "FREQUENT",
"expertiseArea": "BACKEND",
"reportedBy": "cleopatra",
"expectedBehavior": "Settings page should load without crashing.",
"actualBehavior": "App crashes immediately.",
"environment": "Windows"
}
} 


Nu există output.

addComment

Disponibilă pentru: Reporter, Developer

Descriere: Adaugă un comentariu la un ticket.

Restricții

1. Dacă ticket-ul nu există (ID inexistent), comanda este ignorată.

2. Un ticket anonim nu poate primi comentarii. Dacă se încearcă adăugarea unui comentariu la un ticket anonim, comanda este respinsă:

Output eroare

Output eroare

{
  "command": "addComment",
  "username": "user_name",
  "timestamp": "YYYY-MM-DD",
  "error": "Comments are not allowed on anonymous tickets."
}


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ă:

Output eroare

Output eroare

{
  "command": "addComment",
  "username": "user_name",
  "timestamp": "YYYY-MM-DD",
  "error": "Reporters cannot comment on CLOSED tickets."
}


4. Conținutul comentariului trebuie să aibă minim 10 caractere. Dacă este mai mic, comanda este respinsă:

Output eroare

Output eroare

{
  "command": "addComment",
  "username": "user_name",
  "timestamp": "YYYY-MM-DD",
  "error": "Comment must be at least 10 characters long."
}


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ă:

Output eroare

Output eroare

{
  "command": "addComment",
  "username": "user_name",
  "timestamp": "YYYY-MM-DD",
  "error": "Ticket <id> is not assigned to the developer <developer_name>."
}


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ă:

Output eroare

Output eroare

{
  "command": "addComment",
  "username": "user_name",
  "timestamp": "YYYY-MM-DD",
  "error": "Reporter <reporter_name> cannot comment on ticket <id>."
}

Format comentariu

{
  "author": "username_of_commenter",
  "content": "string",
  "createdAt": "date_given_by_command_timestamp"
}


Exemplu Input:

Exemplu input complet

Exemplu input complet

{
"command": "addComment",
"username": "dev_one",
"ticketID": 0,
"comment": "I am looking into this issue.",
"timestamp": "2025-09-10"
} 


Nu există output.

undoAddComment

Disponibilă pentru: Reporter, Developer

Descriere: Șterge ultimul comentariu adăugat de utilizator la un ticket.

Restricții

1. Dacă ticket-ul nu există (ID inexistent), comanda este ignorată.

2. Dacă se încearcă ștergerea unui comentariu de la un ticket anonim, comanda este respinsă:

Output eroare

Output eroare

{
  "command": "undoAddComment",
  "username": "user_name",
  "timestamp": "YYYY-MM-DD",
  "error": "Comments are not allowed on anonymous tickets."
}

3. Dacă utilizatorul nu are comentarii la ticket-ul respectiv, comanda este ignorată.

4. Notificarea trimisă la crearea comentariului nu este ștearsă.


Exemplu Input:

Exemplu input complet

Exemplu input complet

{
"command": "undoAddComment",
"username": "dev_one",
"ticketID": 0,
"timestamp": "2025-09-10"
} 


Nu există output.

createMilestone

Disponibilă pentru: Manager

Descriere: Setează un nou milestone.

Restricții

1. Un ticket poate aparține unui singur milestone la un moment dat. În cazul în care un ticket este deja atribuit unui alt milestone, comanda createMilestone este respinsă:

Output eroare

Output eroare

{
  "command": "createMilestone",
  "username": "user_name",
  "timestamp": "YYYY-MM-DD",
  "error": "Tickets id already assigned to milestone <milestone_name>."
}

Dacă se încearcă crearea unui milestone cu mai multe tickete din alt milestone, comanda va eșua la primul ticket invalid.

  • Se garantează că formatul de input al milestone-ului este corect. (Fără câmpuri invalide sau lipsă câmpuri obligatorii). Nu vor exista milestone-uri cu același nume.
  • Se garantează că orice milestone va avea o perioadă de soluționare de cel puțin 5 zile.
  • Se garantează că nu se va încerca crearea unui milestone în perioada de testare.


Exemplu Input:

Exemplu input complet

Exemplu input complet

{
"command": "createMilestone",
"username": "gabriel_manager",
"timestamp": "2025-09-15",
"name": "v1.0",
"dueDate": "2025-10-01",
"blockingFor": ["v2.0"],
"tickets": [0, 1, 2],
"assignedDevs": ["dev_one", "dev_two"]
} 


Nu există output.

startTestingPhase

Disponibilă pentru: Manager

Descriere: Începe o nouă perioadă de testare, permițând reporterilor să creeze tickete noi și să redeschidă tickete închise.

Restricții

1. O nouă perioadă de testare poate începe doar dacă nu mai există milestone-uri active (cu tickete nerezolvate). În cazul în care se încearcă începerea unei noi perioade de testare cu milestone-uri active, comanda este respinsă:

Output eroare

Output eroare

{
  "command": "startTestingPhase",
  "username": "user_name",
  "timestamp": "YYYY-MM-DD",
  "error": "Cannot start a new testing phase."
}

* Se garantează că nu se va încerca începerea unei perioade de testare dacă una este deja activă.


Exemplu Input:

Exemplu input complet

Exemplu input complet

{
"command": "startTestingPhase",
"username": "gabriel_manager",
"timestamp": "2025-10-05"
} 


Nu există output.

assignTicket

Disponibilă pentru: Developer

Descriere: Un developer își poate atribui un ticket conform regulilor de expertiză, senioritate și milestone.

Restricții

1. Un Developer își poate atribui tickete doar din aria lui de expertiză. În cazul în care un developer încearcă să își atribuie un ticket din altă arie de expertiză, comanda este respinsă:

Output eroare

Output eroare

{
  "command": "assignTicket",
  "username": "user_name",
  "timestamp": "YYYY-MM-DD",
  "error": "Developer <developer_name> cannot assign ticket <id> due to expertise area. Required: <required_area1>, <required_area2>; Current: <current_area>."
}

2. Un Developer își poate atribui singur doar tickete accesibile nivelului său de senioritate. În cazul în care un developer încearcă să își atribuie un ticket care nu îi este permis, comanda este respinsă:

Output eroare

Output eroare

{
  "command": "assignTicket",
  "username": "user_name",
  "timestamp": "YYYY-MM-DD",
  "error": "Developer <developer_name> cannot assign ticket <id> due to seniority level. Required: <required_level>, <required_level>; Current: <current_level>."
}

3. Un ticket poate fi atribuit doar dacă este în status OPEN. Dacă un developer încearcă să își atribuie un ticket cu alt status, comanda este respinsă:

Output eroare

Output eroare

{
  "command": "assignTicket",
  "username": "user_name",
  "timestamp": "YYYY-MM-DD",
  "error": "Only OPEN tickets can be assigned."
}

4. Dacă un developer încearcă să își atribuie un ticket dintr-un milestone la care nu este repartizat, comanda este respinsă:

Output eroare

Output eroare

{
  "command": "assignTicket",
  "username": "user_name",
  "timestamp": "YYYY-MM-DD",
  "error": "Developer <developer_name> is not assigned to milestone <milestone_name>."
}

5. Un developer nu își poate atribui tickete dintr-un milestone blocat (vezi detalii la secțiunea Milestone). Dacă încearcă să își atribuie un ticket dintr-un milestone blocat, comanda este respinsă:

Output eroare

Output eroare

{
  "command": "assignTicket",
  "username": "user_name",
  "timestamp": "YYYY-MM-DD",
  "error": "Cannot assign ticket <id> from blocked milestone <milestone_name>."
}

  • Odată atribuit, statusul unui ticket devine IN_PROGRESS.
  • Se garantează că ID-ul ticket-ului există.


Exemplu Input:

Exemplu input complet

Exemplu input complet

{
"command": "assignTicket",
"username": "dev_one",
"ticketID": 0,
"timestamp": "2025-09-21"
} 


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ă:

Output eroare

Output eroare

{
  "command": "undoAssign",
  "username": "user_name",
  "timestamp": "YYYY-MM-DD",
  "error": "Only IN_PROGRESS tickets can be unassigned."
}

  • 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.


Exemplu Input:

Exemplu input complet

Exemplu input complet

{
"command": "undoAssign",
"username": "dev_one",
"ticketID": 0,
"timestamp": "2025-09-22"
} 


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ă:

Output eroare

Output eroare

{
  "command": "changeStatus",
  "username": "user_name",
  "timestamp": "YYYY-MM-DD",
  "error": "Ticket <id> is not assigned to developer <developer_name>."
}

  • Sunt permise doar următoarele tranziții de status: IN_PROGRESS → RESOLVED → CLOSED. Nu vor exista excepții în teste.


Exemplu Input:

Exemplu input complet

Exemplu input complet

{
"command": "changeStatus",
"username": "dev_one",
"ticketID": 0,
"timestamp": "2025-09-23"
} 


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ă:

Output eroare

Output eroare

{
  "command": "undoChangeStatus",
  "username": "user_name",
  "timestamp": "YYYY-MM-DD",
  "error": "Ticket <id> is not assigned to developer <developer_name>."
}

  • 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.


Exemplu Input:

Exemplu input complet

Exemplu input complet

{
"command": "undoChangeStatus",
"username": "dev_one",
"ticketID": 0,
"timestamp": "2025-09-24"
} 


Nu există output.

viewAssignedTickets

Disponibilă pentru: Developer

Descriere: Afișează toate ticketele atribuite developerului curent.

  • Sortarea se face după businessPriority (CRITICAL > HIGH > MEDIUM > LOW), apoi după createdAt crescător, apoi după id crescător.


Exemplu Input:

Exemplu input complet

Exemplu input complet

{
"command": "viewAssignedTickets",
"username": "dev_one",
"timestamp": "2025-09-25"
} 


Exemplu Output:

Exemplu output complet

Exemplu output complet

{
"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": []
}
]
} 

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).

  • Rezultatele sunt sortate după createdAt (de la cele mai vechi la cele mai noi), iar în caz de egalitate după id crescător.


Exemplu Input:

Exemplu input complet

Exemplu input complet

{
"command": "viewTickets",
"username": "manager_one",
"timestamp": "2025-09-25"
} 


Exemplu Output:

Exemplu output complet

Exemplu output complet

{
"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": []
}
]
} 

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.

  • Milestone-urile sunt afișate crescător după dueDate, iar în caz de egalitate lexicografic crescător după `name`.

  • 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.

completionPercentage

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.

daysUntilDue

daysUntilDue


Numărul de zile rămase până la dueDate. Dacă dueDate este în trecut, valoarea este 0. Formulă: dueDate - currentDay + 1

overdueBy

overdueBy


Numărul de zile cu care dueDate a fost depășit. Dacă dueDate este în viitor, valoarea este 0.

repartition

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ă).


status

status


Poate avea două valori:

  • ACTIVE – dacă există tickete nerezolvate în milestone
  • COMPLETED – dacă toate ticketele sunt CLOSED



Exemplu Input:

Exemplu input complet

Exemplu input complet

{
"command": "viewMilestones",
"username": "username",
"timestamp": "2025-09-25"
} 


Exemplu Output:

Exemplu output complet

Exemplu output complet

{
"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": []
}
]
}
]
} 

viewNotifications

Disponibilă pentru: Developer, Reporter

Descriere: Afișează toate notificările primite de utilizator.

Restricții

  • 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.


Exemplu Input:

Exemplu input complet

Exemplu input complet

{
"command": "viewNotifications",
"username": "user_name",
"timestamp": "2025-09-25"
} 


Exemplu Output:

Exemplu output complet

Exemplu output complet

{
"command": "viewNotifications",
"username": "user_name",
"timestamp": "2025-09-25",
"notifications": [
"<Notification 1>",
"<Notification 2>",
"<Notification 3>"
]
} 


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.

  • 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.

Acțiuni posibile

Exemplu JSON

Exemplu JSON

{
  "action": "ASSIGNED",
  "by": "developer_name",
  "timestamp": "YYYY-MM-DD"
}


Exemplu JSON

Exemplu JSON

{
  "action": "DE-ASSIGNED",
  "by": "developer_name",
  "timestamp": "YYYY-MM-DD"
}


Exemplu JSON

Exemplu JSON

{
  "action": "STATUS_CHANGED",
  "from": "OLD_STATUS",
  "to": "NEW_STATUS",
  "by": "developer_name",
  "timestamp": "YYYY-MM-DD"
}


Exemplu JSON

Exemplu JSON

{
  "action": "ADDED_TO_MILESTONE",
  "milestone": "milestone_name",
  "by": "manager_name",
  "timestamp": "YYYY-MM-DD"
}


Exemplu Input:

Exemplu input complet

Exemplu input complet

{
"command": "viewTicketHistory",
"username": "dev_one",
"timestamp": "2025-09-25"
} 


Exemplu Output:

Exemplu output complet

Exemplu output complet

{
"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": []
}
]
} 


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ă:

Output eroare

Output eroare

{
  "command": "search",
  "username": "user_name",
  "timestamp": "YYYY-MM-DD",
  "error": "Invalid filter <filter_name> for role <role>."
}


Reguli generale

Atenție! Dacă sunt introduse mai multe filtre invalide, comanda va eșua la primul filtru invalid.

Filtre Developer

Filtre manager

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

Atenție! Dacă availableForAssignment = true, comanda returnează doar ticketele ce pot fi repartizate developerului curent (în funcție de senioritate, expertiză și milestone)

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.


Exemplu Input – Developer:

Exemplu input complet

Exemplu input complet

{
"command": "search",
"username": "dev_one",
"timestamp": "2025-09-26",
"filters": {
"searchType": "TICKET",
"businessPriority": "HIGH",
"type": "BUG",
"createdAfter": "2025-09-01",
"availableForAssignment": true
}
} 


Exemplu Output – Developer:

Exemplu output complet

Exemplu output complet

{
"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": ""
}
]
} 


Exemplu Input – Manager (tickets):

Exemplu input complet

Exemplu input complet

{
"command": "search",
"username": "gabriel_manager",
"timestamp": "2025-09-26",
"filters": {
"searchType": "TICKET",
"keywords": ["pay", "bug"],
"businessPriority": "HIGH",
"type": "BUG",
"createdAfter": "2025-09-01"
}
} 


Exemplu Output – Manager (tickets):

Exemplu output complet

Exemplu output complet

{
"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"]
}
]
} 


Exemplu Input – Manager (developers):

Exemplu input complet

Exemplu input complet

{
"command": "search",
"username": "gabriel_manager",
"timestamp": "2025-09-26",
"filters": {
"searchType": "DEVELOPER",
"expertiseArea": "BACKEND",
"seniority": "MID",
"performanceScoreAbove": number
}
} 


Exemplu Output – Manager (developers):

Exemplu output complet

Exemplu output complet

{
"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"
}
]
} 


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.

Bonusuri nivel de senioritate

Bonusuri nivel de senioritate

  • JUNIOR → +5
  • MID → +15
  • SENIOR → +30


Junior Performance

Formula

Formula


  • juniorPerformance = max(0, 0.5 * closedTickets - ticketDiversityFactor) + seniorityBonus



Vom defini ticketDiversityFactor ca fiind coeficientul de variație dintre deviația standard și media aritmetică.

Detalii calcul

Detalii calcul

  • averageResolvedTicketType
(bugTickets + featureTickets + uiTickets) / 3
  • standardDeviation
sqrt(((bugTickets - avg)^2 + (featureTickets - avg)^2 + (uiTickets - avg)^2) / 3)
  • ticketDiversityFactor
standardDeviation / averageResolvedTicketType

Mid Performance

Formula

Formula


  • midPerformance = max(0, 0.5 * closedTickets + 0.7 * highPriorityTickets - 0.3 * averageResolutionTime) + seniorityBonus



Detalii calcul Mid Performance

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)


Senior Performance

Formula

Formula

  • seniorPerformance = max(0, 0.5 * closedTickets + 1.0 * highPriorityTickets - 0.5 * averageResolutionTime) + seniorityBonus


Detalii calcul Senior Performance

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


Metode utile

Puteti folosi următoarele metode în soluția temei:

Java code

Java code

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;
}


Exemplu Input:

Exemplu input complet

Exemplu input complet

{
  "command": "generatePerformanceReport",
  "username": "gabriel_manager",
  "timestamp": "2025-09-01"
}


Exemplu Output:

Exemplu output complet

Exemplu output complet

{
  "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"
    }
  ]
}


Ticket Risk

Disponibilă pentru: Manager

Descriere: Generează un raport pe baza metricii ticket risk.

Comanda: generateTicketRiskReport

Raportul este creat pe baza tuturor ticketelor OPEN si IN_PROGRESS din sistem, indiferent de managerul care a generat raportul.

Calculare:

BUG

BUG

Formula: frequency × severityFactor

Valoare maximă: 12

Exemplu de calcul:

frequency = ALWAYS (4)  
severityFactor = SEVERE (3)

Risc brut = 4 × 3 = 12  
Risc final = (12 × 100) / 12 = 100.00

FEATURE_REQUEST

FEATURE_REQUEST

Formula: businessValue + customerDemand

Valoare maximă: 20

Exemplu de calcul:

businessValue = XL (10)  
customerDemand = HIGH (6)

Risc brut = 10 + 6 = 16  
Risc final = (16 × 100) / 20 = 80.00

UI_FEEDBACK

UI_FEEDBACK

Formula: (11 − usabilityScore) × businessValue

Valoare maximă: 100

Exemplu de calcul:

usabilityScore = 2  
businessValue = XL (10)

Risc brut = (11 − 2) × 10 = 90  
Risc final = (90 × 100) / 100 = 90.00


În urma raportului, fiecare categorie va avea un calificativ:

Calificative risc

Calificative risc


Interval Risc Calificativ
0 – 24 NEGLIJABIL
25 – 49 MEDIU
50 – 74 SEMNIFICATIV
75 – 100 MAJOR


Exemplu Input:

Exemplu input complet

Exemplu input complet

{
"command": "generateTicketRiskReport",
"username": "gabriel_manager",
"timestamp": "2025-09-30"
} 


Exemplu Output:

Exemplu output complet

Exemplu output complet

{
"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"
}
}
} 


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

Raportul este creat pe baza tuturor ticketelor CLOSED si RESOLVED din sistem, indiferent de managerul care a generat raportul.

BUG

BUG

Formula:

(bugFrequency + severityFactor) × 10 / daysToResolve

Valoare maximă: 70

Exemplu de calcul:

frequency = FREQUENT (3)
severityFactor = MODERATE (2)
daysToResolve = 2

Scor eficiență = (3 + 2) × 10 / 2 = 25
Eficiență finală = (25 × 100) / 70 = 35.71

FEATURE_REQUEST

FEATURE_REQUEST

Formula:

(businessValue + customerDemand) / daysToResolve

Valoare maximă: 20

Exemplu de calcul:

businessValue = L (6)
customerDemand = HIGH (6)
daysToResolve = 2

Scor eficiență = (6 + 6) / 2 = 6.00
Eficiență finală = (6 × 100) / 20 = 30.00

UI_FEEDBACK

UI_FEEDBACK

Formula:

(usabilityScore + businessValue) / 2

Valoare maximă: 20

Exemplu de calcul:

usabilityScore = 9
businessValue = XL (10)

Scor eficiență = (9 + 10) / 2 = 9.5
Eficiență finală = (9.5 × 100) / 20 = 47.50


Atenție! daysToResolve = numărul de zile dintre assignedAt și data la care ticket-ul a fost marcat ultima dată ca RESOLVED sau CLOSED.

Exemplu Input:

Exemplu input complet

Exemplu input complet

{
  "command": "generateResolutionEfficiencyReport",
  "username": "gabriel_manager",
  "timestamp": "2025-09-30"
}


Exemplu Output:

Exemplu output complet

Exemplu output complet

{
  "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
    }
  }
}


Customer Impact

Disponibilă pentru: Manager

Descriere: Estimează impactul asupra clienților al ticketelor.

Comanda: generateCustomerImpactReport

Raportul este creat pe baza tuturor ticketelor aflate în stările OPEN și IN_PROGRESS, indiferent de managerul care a generat raportul.

BUG

BUG

Formula:

frequency × businessPriority × severityFactor

Valoare maximă: 48

Exemplu de calcul:

frequency = ALWAYS (4)  
businessPriority = CRITICAL (4)  
severityFactor = SEVERE (3)

Impact brut = 4 × 4 × 3 = 48  
Impact final = (48 × 100) / 48 = 100.00

FEATURE_REQUEST

FEATURE_REQUEST

Formula:

businessValue × customerDemand

Valoare maximă: 100

Exemplu de calcul:

businessValue = M (3)  
customerDemand = HIGH (6)

Impact brut = 3 × 6 = 18  
Impact final = (18 × 100) / 100 = 18.00

UI_FEEDBACK

UI_FEEDBACK

Formula:

businessValue × usabilityScore

Valoare maximă: 100

Exemplu de calcul:

businessValue = L (6)  
usabilityScore = 9

Impact brut = 6 × 9 = 54  
Impact final = (54 × 100) / 100 = 54.00


Exemplu Input:

Exemplu input complet

Exemplu input complet

{
  "command": "generateCustomerImpactReport",
  "username": "gabriel_manager",
  "timestamp": "2025-09-30"
}


Exemplu Output:

Exemplu output complet

Exemplu output complet

{
  "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
    }
  }
}