Skip to content

Feature/exam queue#33

Open
LetMeSoloSir wants to merge 7 commits into
mainfrom
feature/exam-queue
Open

Feature/exam queue#33
LetMeSoloSir wants to merge 7 commits into
mainfrom
feature/exam-queue

Conversation

@LetMeSoloSir

Copy link
Copy Markdown
Collaborator

No description provided.

@RedAvocado22

Copy link
Copy Markdown
Owner

Code Review — Blocking issues before merge

🔴 Bug 1 — Flyway version conflict (startup will fail)

V11__add_exam_queue.sql conflicts with V11__update_appointment_date.sql already on main. After merge, two V11 files in db/migration/ → Flyway refuses to start. Rename to V14__add_exam_queue.sql.


🔴 Bug 2 — @Transactional on doProcess() is ignored (self-invocation)

In AddToQueueService:

@Override
@Transactional
protected QueueInfoResponse doProcess(AddToQueueRequest request) {

doProcess() is called internally from BaseService.execute() via this.doProcess() — Spring's AOP proxy never intercepts it, so @Transactional has no effect. The countByDateWithLock (FOR UPDATE) and save() run in separate auto-committed transactions, making the pessimistic lock completely useless. Two concurrent requests can both read count = 0 and both assign position = 1.

Fix: override execute() with @Transactional, same pattern as the other services:

@Override
@Transactional
public QueueInfoResponse execute(AddToQueueRequest request) {
    return super.execute(request);
}

Same issue applies to UpdateQueueService and DeleteQueueService — mutations without a wrapping transaction.


🔴 Bug 3 — AddToQueueRequest exposes JPA entity directly

private PatientInfo patient; // JPA entity in request body

The client sends a full PatientInfo JSON object. The service then uses request.getPatient() directly to build QueueInfo — the patient data stored in the queue comes from the HTTP request, not from the database.

Change to private UUID patientId, then resolve the entity in the service:

PatientInfo patient = patientQueryService.getReferenceById(request.getPatientId());
QueueInfo.builder().patient(patient)...

🔴 Bug 4 — POST /exam-queue has no @PreAuthorize

GET, PATCH, DELETE all have @PreAuthorize("hasAnyRole('RECEPTIONIST', 'ADMIN')"). POST does not — anyone can add patients to the queue unauthenticated.


Design issue — Queue is disconnected from the appointment system

This is the bigger problem. QueueInfo only links to patient — no appointment_id, no doctor, no schedule_id.

What this means in practice:

  • Hospital has 10 doctors working the same shift → all their patients go into a single global queue
  • GET /exam-queue returns everyone's patients mixed together — a doctor sees patients that aren't theirs
  • A patient can be added to the queue without any appointment existing — completely bypasses the appointment system we already built

How it should work:

The queue is the physical check-in layer on top of the appointment system. When a patient arrives, the receptionist finds their appointment for today and adds them to that doctor's queue.

QueueInfo should reference appointment_id (FK → appointment). From the appointment you already have: patient, doctor, date, shift — no need to store date separately. GET /exam-queue for a DOCTOR role filters by doctorId from JWT, not a global date dump.

Correct flow:

Patient arrives → Receptionist finds today's appointment → 
Add to queue (linked to appointment_id) → Doctor calls: WAITING → IN_PROGRESS → DONE

State machine is also missing validation — currently UpdateQueueService allows any transition: DONE → WAITING, CANCELLED → IN_PROGRESS, etc. Need to define valid transitions and enforce them.


Please redesign QueueInfo with appointment_id FK before merging. Happy to discuss the schema if needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants