Przejdź do treści

Prediagnoza — przebieg integracji

Wszystkie ścieżki poniżej są względne wobec /partner/v1/prediagnosis. Uwierzytelnienie jak w pozostałych endpointach: x-client-id, x-api-key, x-user-id.

Zasada ogólna

Prediagnoza to ankieta złożona ze slajdów, po jednym pytaniu na slajd. Wszystkie slajdy powstają z góry przy starcie i są połączone w łańcuch przez next_slide_id i prev_slide_id — nawigacja polega na przechodzeniu tym łańcuchem, a nie na numerowaniu kroków po swojej stronie.

Każda odpowiedź zapisuje się natychmiast, więc ankietę można przerwać i wrócić do niej później — pod warunkiem zachowania jej identyfikatora; patrz niżej. Na końcu osobne wywołanie wylicza wynik: listę prawdopodobnych chorób i poziom pilności (triage).

Krok 1 — rozpoczęcie

Dwa warianty, zależnie od tego, czy ankieta dotyczy zapisanego zwierzaka.

GET /start              — bez zwierzaka, pełna ankieta
GET /start/{petId}      — dla zapisanego zwierzaka

Oba zwracają pierwszy slajd do wyświetlenia.

Każde wywołanie zakłada nową ankietę

start nie wznawia niczego — za każdym razem powstaje nowa prediagnoza, z nowym id i od pierwszego slajdu. Nie ma też endpointu zwracającego listę ankiet zwierzaka.

Dlatego id z pierwszej odpowiedzi trzeba zapisać po swojej stronie, razem z identyfikatorem użytkownika i zwierzaka. Bez niego przerwanej ankiety nie da się odzyskać, a wznowienie odbywa się przez GET /last-slide/{prediagnosisId}.

Wariant ze zwierzakiem pomija część pytań — ale tylko warunkowo

Przy /start/{petId} dane z profilu zwierzaka (gatunek, wiek, budowa, kastracja, płeć, rasa, imię) są wpisywane w odpowiednie slajdy automatycznie. Dalej zależy to od kompletności profilu:

  • wszystkie siedem pól uzupełnione → ankieta zaczyna się od pytań medycznych, z pominięciem części o zwierzaku, bez możliwości cofnięcia się do niej
  • brakuje choćby jednego pola → ankieta zaczyna się od początku, z częścią odpowiedzi już wypełnionych

Warto o tym pamiętać przy zwierzakach zakładanych przez API — jeśli przy tworzeniu pominięto np. budowę, użytkownik zobaczy pełną ankietę mimo istniejącego profilu.

Struktura slajdu

Odpowiedź każdego endpointu nawigacyjnego ma ten sam kształt. Najważniejsze pola:

Pole Znaczenie
slide_id identyfikator slajdu — to jego odsyła się przy odpowiadaniu
id identyfikator prediagnozy (nie slajdu); tego samego użyjesz przy wyniku
question.type rodzaj pytania, decyduje o znaczeniu odpowiedzi
question.format sposób prezentacji, decyduje o formacie odpowiedzi
question.heading treść pytania w języku żądania
answers lista opcji do wyboru: { id, label } plus opcjonalnie image, description, order, group
answer dotychczasowa odpowiedź, już zdekodowana; pusty łańcuch "", gdy slajd nie był jeszcze odpowiedziany
progress postęp ankiety, 0–1
next_slide_id, prev_slide_id sąsiednie slajdy; null oznacza koniec łańcucha
next_achievable, prev_achievable czy w danym kierunku wolno przejść
body_area tylko dla pytań BODY_AREA: sylwetka i klikalne punkty

Brak odpowiedzi to "", nie nullanswer ?? wartośćDomyślna nigdy się nie uruchomi, więc slajd trzeba sprawdzać przez samą prawdziwość wartości (answer || wartośćDomyślna).

Uwaga na slide_id kontra id. To dwa różne identyfikatory w jednej odpowiedzi: slide_id odsyła się przy odpowiadaniu, id służy do pobrania wyniku.

question.type przyjmuje: NAME, SPECIES, RACE, GENDER, CASTRATION, AGE, BUILD, BODY_AREA, BEHAVIOUR, SYMPTOMS, SYMPTOMS_DETAIL, REGULAR.

question.format przyjmuje: LARGE_RADIO, MEDIUM_RADIO, SMALL_RADIO, CHECKBOX, TEXT, SLIDER, SELECT, SELECT_MULTI.

Krok 2 — odpowiadanie

POST /next-slide
{ "id": "<slide_id>", "answer": "<odpowiedź>" }

W polu id idzie slide_id bieżącego slajdu, a nie identyfikator prediagnozy.

Format odpowiedzi zależy od question.format

  • SELECT_MULTIJSON-string z tablicą identyfikatorów: "answer": "[\"id-1\",\"id-2\"]"
  • pozostałe formaty → zwykła wartość: identyfikator wybranej opcji, tekst albo liczba

Odpowiedź zwraca kolejny slajd albo — po ostatnim pytaniu — sygnał zakończenia:

{ "finished": true }

Krok 3 — cofanie się

GET /prev-slide/{slideId}

Przekazuje się prev_slide_id z bieżącego slajdu.

Serwis może cofnąć się o więcej niż jeden slajd — jeśli poprzednie pytanie o objawy szczegółowe nie ma żadnych opcji, jest pomijane. Analogiczne pomijanie działa w przód. Dlatego po każdym przejściu należy czytać slide_id ze zwróconego slajdu, a nie zakładać, że dostało się dokładnie ten, o który się prosiło.

Objawy

Opcje do wyboru przychodzą razem ze slajdem, w polu answers — nie trzeba ich dowoływać.

Do wyszukiwania w trakcie ankiety służy:

GET /filter-symptoms/{prediagnosisId}?search=kaszel&is_detail=false
  • is_detail=false — główna lista objawów (pytanie SYMPTOMS)
  • is_detail=true — objawy szczegółowe (pytanie SYMPTOMS_DETAIL)

Ustawiaj zgodnie z typem pytania na bieżącym slajdzie.

Kontekst — okolica ciała, zachowanie, kastracja, płeć — jest brany z wcześniejszych odpowiedzi w tej samej ankiecie, więc nie przekazuje się go w zapytaniu.

Zwracane pozycje mają kształt { value, label }, gdzie value to identyfikator objawu. To ten sam identyfikator, który trafia do tablicy w answer.

Krok 4 — wynik

GET /results/{prediagnosisId}

Wywołać jeden raz, po otrzymaniu { "finished": true }.

To nie jest zwykły odczyt: endpoint kończy ankietę i przelicza wynik — wyznacza listę chorób, ustala triage, oznacza prediagnozę jako zakończoną i generuje nowy kod dostępu. Każde ponowne wywołanie liczy wszystko od nowa.

Odpowiedź:

{
  "id": "…",
  "pet_id": "…",
  "pin": "482913",
  "triage": { "severity": "MEDIUM", "name": "…", "color": "…", "image_src": "…" },
  "diseases": [
    { "percentage": 0.42, "severity": "MEDIUM",
      "disease": { "DiseasesContent": [ { "name": "…", "description": "…",
                                          "firstaid_advice": "…" } ] } }
  ],
  "answers": [ { "label": "Gatunek", "value": "Kot" } ]
}
  • diseases — maksymalnie 5 dopasowań powyżej 20%, od najsilniejszego
  • triage — poziom pilności wraz z opisem i ikoną
  • answers — podsumowanie ankiety, gotowe do wyświetlenia
  • pin — sześciocyfrowy kod dostępu dla weterynarza; warto go pokazać użytkownikowi, patrz niżej

PIN — po co go wyświetlać

pin to kod, który użytkownik podaje weterynarzowi w gabinecie. Lekarz wpisuje go w swoim panelu i otwiera dzięki temu wynik prediagnozy — a przy okazji zwierzak i jego właściciele zostają powiązani z tą placówką.

Dla użytkownika oznacza to, że wypełniona w aplikacji partnera prediagnoza trafia do konkretnego gabinetu, a wizyta, którą lekarz następnie założy, pojawi się na osi czasu i w module wizyt. Pominięcie pin w interfejsie zamyka tę drogę — kodu nie da się odzyskać inaczej niż przez ponowny odczyt wyniku.

pin jest stały dla danej prediagnozy: ponowne wywołanie results/{id} generuje nowy kod dostępu do samego wyniku, ale pin pozostaje ten sam.

Ponowne wyświetlenie wyniku

GET /details/{prediagnosisId}

Odczyt zapisanego wyniku, w tym samym kształcie co results, bez przeliczania. Tego należy używać wszędzie tam, gdzie wynik jest tylko pokazywany — na przykład przy otwarciu prediagnozy z historii zwierzaka.

Edycja odpowiedzi

GET /last-slide/{prediagnosisId}

Otwiera zakończoną ankietę na ostatnim pytaniu, z wypełnioną wcześniej odpowiedzią. Stamtąd cofa się przez prev-slide do pytania, które trzeba poprawić, a potem wraca w przód przez next-slide. Odpowiedź na ostatni slajd ponownie zwraca { "finished": true } i wtedy wywołuje się results.

Dwie konsekwencje edycji:

  • wynik jest przeliczany od zera, więc lista chorób może się zmienić
  • generowany jest nowy kod dostępu; pin pozostaje ten sam

Najczęstsze przyczyny błędów

Objaw Przyczyna
slide_not_found przy next-slide W polu id wysłano identyfikator prediagnozy zamiast slide_id
answer_not_found Puste answer — każde pytanie wymaga odpowiedzi; uwaga, nieodpowiedziany slajd wraca właśnie z ""
Odpowiedź wielokrotnego wyboru nie zapisuje się poprawnie Wysłano tablicę zamiast JSON-stringa przy format: "SELECT_MULTI"
/start/{petId} pokazuje pełną ankietę Profil zwierzaka nie ma kompletu siedmiu pól
Przerwana ankieta zniknęła start zakłada nową za każdym razem — id trzeba było zapisać
Po prev-slide wrócił inny slajd, niż oczekiwano Pytanie o objawy szczegółowe bez opcji zostało pominięte
Wynik zmienia się przy odświeżeniu Użyto results zamiast details do ponownego wyświetlenia

Przykładowa pełna sekwencja

GET  /start/{petId}                → slajd
POST /next-slide  { "id": "<slide_id>", "answer": "..." }   → kolejny slajd
POST /next-slide  { ... }                                    → kolejny slajd
     … aż do …
POST /next-slide  { ... }                                    → { "finished": true }
GET  /results/{prediagnosisId}                               → wynik

później, przy ponownym otwarciu:
GET  /details/{prediagnosisId}