This is an old revision of the document!
Tema 2 - Bug Tracker Pro
Obiective
Implementarea a cel puțin 4 design pattern-uri.
Crearea unui cod care respectă principiile de bază POO: Abstracție, Încapsulare, Moștenire, Polimorfism.
Respectarea principiilor SOLID.
Familiarizarea studenților cu JUnit și rularea testelor unitare.
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ă:
înregistrați tickete noi,
raportați problemele apărute,
urmăriți progresul și să le rezolvați.
Dezvoltarea va fi împărțită în două etape principale:
testare și raportare tickete
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:
Perioada de testare: reporterii deschid tickete pentru problemele identificate.
Perioada de dezvoltare: managerii creează milestone-uri, iar developerii își asignează tickete și le rezolvă.
Verificarea stabilității aplicației: se generează un raport de stabilitate și se evaluează progresul.
Dacă produsul este stabil, proiectul se încheie cu succes.
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
La inițierea aplicației, perioada de testare începe automat.
Utilizatorii pot raporta tickete noi, pe baza testării produsului și a feedback-ului primit de la clienți.
Developerii nu pot rezolva tickete în această etapă.
Perioada de testare are o durată fixă de 15 zile.
2. Perioada de Dezvoltare
După încheierea perioadei de testare, începe perioada de dezvoltare.
Managerii creează milestone-uri și își coordonează echipa.
Developerii își pot asocia tickete din milestone-uri și pot începe lucrul la acestea.
3. Verificarea Stabilității
Managerii pot genera rapoarte pentru monitorizarea progresului.
Dacă raportul de stabilitate este satisfăcător, produsul este considerat stabil și pregătit pentru prezentarea către investitori.
Dacă raportul indică probleme, ciclul continuă cu o nouă perioadă de testare și dezvoltare.
Această etapă poate fi skipped, trecându-se direct la perioada de testare, dacă un manager execută comanda: startTestingPhase
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.
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.
[
{
"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:
JUNIOR: poate prelua tickete cu prioritate LOW, MEDIUM; tipuri: BUG, UI_FEEDBACK
MID: acces JUNIOR + tickete cu prioritate HIGH, inclusiv FEATURE_REQUEST
SENIOR: acces MID + tickete CRITICAL
Mai mult! Fiecare developer are o specializare:
Acces în funcție de specializare:
FRONTEND Developer: tickete din FRONTEND, DESIGN
BACKEND Developer: tickete din BACKEND, DB
FULLSTACK Developer: tickete din toate zonele: FRONTEND, BACKEND, DEVOPS, DESIGN, DB
DEVOPS Engineer: tickete din DEVOPS
UI/UX Designer: tickete din DESIGN
Database Admin: tickete din DB
[
{
"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ă.
[
{
"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
name – numele milestone-ului (unic).
blockingFor – listă de nume ale milestone-urilor care sunt blocate de acest milestone.
dueDate – data limită pentru atingerea milestone-ului.
tickets – listă de ID-uri ale ticketelor asociate milestone-ului.
assignedDevs – listă cu username-urile developerilor repartizați.
Mentiuni speciale
1. La fiecare 3 zile după crearea milestone-ului, prioritatea ticketelor din acel milestone crește automat cu o treaptă
(ex: LOW → MEDIUM, MEDIUM → HIGH etc.).
2. Cu o zi calendaristică înainte de dueDate, toate ticketele rămase active în milestone:
devin automat de prioritate CRITICAL
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:
bug-urile din milestone-ul blocat nu pot fi rezolvate sau atribuite
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:
toate ticketele rămase devin automat CRITICAL
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.
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.
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.
{
"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.
{
"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.
{
"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ă:
{
"command": "reportTicket",
"username": "user_name",
"timestamp": "YYYY-MM-DD",
"error": "Anonymous reports are only allowed for tickets of type BUG."
}
Format Input:
{
"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.
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ă:
{
"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ă:
{
"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ă:
{
"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ă:
{
"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ă:
{
"command": "addComment",
"username": "user_name",
"timestamp": "YYYY-MM-DD",
"error": "Reporter <reporter_name> cannot comment on ticket <id>."
}
{
"author": "username_of_commenter",
"content": "string",
"createdAt": "date_given_by_command_timestamp"
}
Exemplu Input:
{
"command": "addComment",
"username": "dev_one",
"ticketID": 0,
"comment": "I am looking into this issue.",
"timestamp": "2025-09-10"
}
Nu există output.
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ă:
{
"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:
{
"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ă:
{
"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.
Exemplu Input:
{
"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ă:
{
"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:
{
"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ă:
{
"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ă:
{
"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ă:
{
"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ă:
{
"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ă:
{
"command": "assignTicket",
"username": "user_name",
"timestamp": "YYYY-MM-DD",
"error": "Cannot assign ticket <id> from blocked milestone <milestone_name>."
}
Exemplu Input:
{
"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ă:
{
"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:
{
"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ă:
{
"command": "changeStatus",
"username": "user_name",
"timestamp": "YYYY-MM-DD",
"error": "Ticket <id> is not assigned to developer <developer_name>."
}
Exemplu Input:
{
"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ă:
{
"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. Mai multe detalii în secțiunea [View Ticket History](#viewtickethistory).
</note>
Exemplu Input:
{
"command": "undoChangeStatus",
"username": "dev_one",
"ticketID": 0,
"timestamp": "2025-09-24"
}
Nu există output.