Zwierzaki — przebieg integracji¶
Ścieżki są względne wobec /partner/v1/pets — poza tworzeniem i edycją zwierzaka,
które trafiają wprost w /partner/v1/pets i są tu zapisane pełną ścieżką.
Uwierzytelnienie jak w pozostałych modułach: x-client-id, x-api-key, x-user-id.
Dokument opisuje profil zwierzaka i jego cykl życia. Książeczka zdrowia — leczenia cykliczne, wizyty, leki i oś czasu — jest opisana osobno.
Zasada ogólna¶
Zwierzak jest punktem zaczepienia dla całej reszty integracji: identyfikator zwrócony przy jego utworzeniu wraca potem w kalkulatorze żywieniowym, prediagnozie i książeczce zdrowia.
Profil opiera się na naszych słownikach — gatunek, rasa, płeć, kastracja, przedział wiekowy i budowa są wybierane z list, a nie wpisywane tekstem.
Krok 1 — dane słownikowe¶
Jednym wywołaniem pobiera się komplet list do formularza:
{ "genders": [ { "value": "…", "label": "Samiec" } ],
"species": [ { "value": "…", "label": "Pies" } ],
"colors": [ … ],
"castration": [ … ],
"age": [ … ],
"build": [ … ] }
Rasy zależą od gatunku, więc pobiera się je dopiero po jego wyborze:
Zwraca { id, label, order } — order służy do wyróżnienia najpopularniejszych ras
na początku listy.
Dostępne jest też GET /species-list, jeśli potrzebne są same gatunki bez reszty
formularza.
Krok 2 — sprawdzenie numeru chipa¶
GET /check-chip?chip=616093900123456
GET /check-chip?chip=616093900123456&pet_id={petId} — przy edycji
Numer mikroczipa jest unikalny w całym systemie. Endpoint zwraca true, gdy numer
jest wolny, albo 409, gdy jest już przypisany do innego zwierzęcia.
Parametr pet_id wyklucza z porównania samego edytowanego zwierzaka — bez niego
edycja zwierzaka z niezmienionym chipem zgłosiłaby konflikt sama ze sobą.
Krok 3 — utworzenie zwierzaka¶
POST /partner/v1/pets
{ "name": "Burek",
"gender": "<id>", "species_id": "<id>", "race_id": "<id>", "castration": "<id>",
"age": "<id>", "build": "<id>",
"weight": 12.5, "chip": "616093900123456", "birth_date": "2021-04-02" }
| Pole | Wymagane | Skąd wartość |
|---|---|---|
name |
tak | |
species_id |
tak | GET /pets-profile-relations |
race_id |
tak | GET /races-list/{speciesId} |
gender |
tak | GET /pets-profile-relations |
build |
tak | GET /pets-profile-relations |
age |
tak | GET /pets-profile-relations |
castration |
tak | GET /pets-profile-relations |
color |
nie | GET /pets-profile-relations |
weight |
nie | kilogramy |
birth_date |
nie | data |
chip |
nie | numer mikroczipa, unikalny w całym systemie |
image_id, image_src |
nie | zdjęcie — patrz niżej |
Innych pól nie przyjmujemy: nieznana nazwa kończy się 400.
species_id i race_id trzeba przekazać oba. Gatunek nie jest wyprowadzany
z rasy — zapisujemy dokładnie to, co przyjdzie w żądaniu. Zwierzak bez gatunku nie
przejdzie przez kalkulator żywieniowy, a prediagnoza zada mu komplet pytań zamiast
skróconej ścieżki.
Sprawdzamy też, czy rasa należy do podanego gatunku; niezgodność kończy się 400.
Zdjęcie zwierzaka wgrywa się wcześniej ścieżką plików z
purpose: "pet_avatar", a z potwierdzenia przekazuje się tutaj id jako image_id
i path jako image_src.
Zwierzak zostaje przypisany do użytkownika z nagłówka x-user-id jako jego główny
właściciel.
Krok 4 — odczyt¶
Stronicowanie jest liczone od zera — page=0 to pierwsza strona. take domyślnie
20, maksymalnie 100. Odpowiedź listy zawiera total z pełną liczbą zwierząt, więc
liczbę stron wylicza się po swojej stronie.
Lista zwraca dane skrócone: identyfikator, imię, zdjęcie, is_main_owner i status.
Pełne dane — z rozwiniętymi słownikami — daje dopiero profile/{petId}: gatunek, rasa,
płeć, kastracja, wiek, budowa i kolor przychodzą tam jako obiekty z nazwą w języku
żądania, a nie same identyfikatory.
Zwierzaki oznaczone jako zmarłe nie pojawiają się na zwykłej liście — mają własną.
Krok 5 — edycja¶
PATCH /partner/v1/pets/{petId}
{ "name": "Burek",
"species_id": "<id>", "race_id": "<id>", "gender": "<id>",
"build": "<id>", "age": "<id>", "castration": "<id>",
"weight": 13.1, "chip": "616093900123456" }
Edycja przyjmuje dokładnie ten sam zestaw pól co tworzenie. Mimo metody PATCH
żądanie nie jest częściowe: pola wymagane trzeba przesłać za każdym razem, nawet
gdy się nie zmieniają.
Przy edycji dochodzą do nich chip i weight — te dwa pola są zapisywane
bezwarunkowo, więc ich pominięcie skasowałoby dotychczasową wartość. Zamiast
kasować po cichu, wymagamy ich obecności: wartość albo pusty łańcuch ("") lub null,
jeśli mają zostać wyczyszczone. W formularzu wystarczy więc zwykłe pole tekstowe
z pustą wartością domyślną.
Pozostałe pola opcjonalne — color, birth_date, image_id, image_src — pominięte
zachowują dotychczasową wartość.
W praktyce: GET /profile/{petId}, podmiana zmienianych wartości, odesłanie kompletu.
Gatunek i rasa są sprawdzane tak samo jak przy tworzeniu — rasa musi należeć do podanego gatunku.
Edycja wymaga, by użytkownik był głównym właścicielem zwierzaka.
Zakończenie i usunięcie — dwie różne operacje¶
kill oznacza zwierzaka jako zmarłego — ustawia datę śmierci. Znika ze zwykłej
listy, pojawia się na liście zmarłych, a cała historia medyczna zostaje nietknięta.
Zwraca zaktualizowany profil.
delete usuwa powiązanie użytkownika ze zwierzakiem, a nie sam wpis. Zwraca
{ "count": 1 } — liczbę usuniętych powiązań, nie usuniętych zwierząt.
Obie wymagają uprawnień głównego właściciela.
Domyślny weterynarz¶
Zwierzakowi można przypisać weterynarza z naszej bazy:
GET /search-vet?phrase=kowalski
PATCH /set-vet-default { "pet_id": "…", "vet_id": "…" }
GET /pet-default-vet/{petId}
Wyszukiwarka zwraca { vet: { id, label }, clinique }, gdzie label to imię
i nazwisko, a clinique — nazwa i miasto placówki, jeśli weterynarz jest do którejś
przypisany.
Przekazanie pustego vet_id w set-vet-default usuwa przypisanie.
Brak przypisanego weterynarza to pusta odpowiedź¶
pet-default-vet/{petId} odpowiada wtedy 200 z pustym ciałem — zero bajtów,
a nie null ani {}. To nie jest błąd, ale response.json() się na tym wywraca,
więc odpowiedź trzeba sprawdzić przed parsowaniem:
const res = await fetch(url, { headers });
const text = await res.text();
const vet = text ? JSON.parse(text) : null;
Po przypisaniu weterynarza endpoint zwraca normalny obiekt.
Aktywny zwierzak¶
Zaznacza, którego zwierzaka pokazywać domyślnie, gdy użytkownik ma ich kilka.
Wartość wraca jako is_default_pet na liście zwierząt. Zwraca { "count": 1 }.
Jest to wyłącznie preferencja wyświetlania — nie wpływa na dostęp ani na dane.
Najczęstsze przyczyny błędów¶
| Objaw | Przyczyna |
|---|---|
409 przy tworzeniu lub edycji |
Numer chipa jest już przypisany do innego zwierzęcia |
409 przy edycji z niezmienionym chipem |
Pominięto pet_id w check-chip |
403 przy edycji, kill lub delete |
Użytkownik nie jest głównym właścicielem |
400 przy edycji jednego pola |
PATCH nie jest częściowy — komplet pól wymaganych trzeba dosłać za każdym razem |
| Chip albo waga zniknęły po edycji | Nie przesłano ich w żądaniu — przy edycji są wymagane |
| Pusta lista mimo istniejących zwierząt | Zwierzaki oznaczone jako zmarłe — patrz pets-deceased-list |
400 przy tworzeniu lub edycji |
Rasa nie należy do podanego gatunku |
400 z „property … should not exist" |
Pole spoza zestawu, np. passport czy behaviour |
| Kalkulator żywieniowy odrzuca zwierzaka | Powstał bez species_id — oba pola są wymagane |
delete nie usunął zwierzaka |
Usuwa powiązanie z użytkownikiem, nie sam wpis |
Błąd parsowania przy pet-default-vet |
Brak weterynarza to puste ciało odpowiedzi, nie null |
Przykładowa sekwencja¶
GET /partner/v1/pets/pets-profile-relations → listy wyboru
GET /partner/v1/pets/races-list/{speciesId} → rasy dla wybranego gatunku
GET /partner/v1/pets/check-chip?chip=… → czy numer wolny
POST /partner/v1/pets → { id }
GET /partner/v1/pets/pets-list?page=0&take=20
GET /partner/v1/pets/profile/{petId}
PATCH /partner/v1/pets/{petId} → aktualizacja (ten sam komplet pól)