Spis treści

Gabinet dentystyczny - przygotowania do rysowania diagramu

Przymierzam się powoli do narysowania diagramu zębów.

Założenia

  • Na początku przygotuję bazę - dodam potrzebne tabele - i zastanowię się nad API, jakie może mi się przydać podczas rysowania.

  • Później zamierzam napisać kawałek kodu w JavaScript, który ściągnie z serwera listę zmian (operacji, jakie były wykonywane na poszczególnych zębach) i wyrysuje je na diagramie widocznym w widoku wizyty.

  • Docelowo diagram będzie interaktywny - klikanie w zęby będzie generować po stronie serwera “zmiany stanu uzębienia”.

Dwie tabele

Zacznę od dodania dwóch tabel:

  • state przechowuje nazwy “stanów” uzębienia i określa, czy stan dotyczy całego zęba (np. “do usunięcia”) czy tylko części (np. “wypełnienie czasowe”)
  • change opisuje pojedynczą zmianę (która nakłada się na poprzednie zmiany), która odbywa się w kontekście określonej wizyty, dotyczy zęba o pewnym numerze, określonej (liczbą) strony zęba (0 - całość, 1 - powierzchnia centralna, 2…5 - lewa, górna, prawa, dolna)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
create table if not exists state (
  id integer primary key,
  name string not null,
  whole boolean not null default false
);

create table if not exists change (
 id integer primary key,
 visit_id int not null,
 state_id int not null,
 tooth_num int,
 tooth_side int,
 time int not null default CURRENT_TIMESTAMP,
 foreign key(visit_id) references visit(id),
 foreign key(state_id) references state(id)
);

Tabela state

Zainicjuję tabelę state stanami (se strony diagramzebowy.pl):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
insert into state (id, name, whole) 
  values (0, "próchnica", false);
insert into state (id, name, whole) 
  values (1, "ubytki niepróchnicowe", false);
insert into state (id, name, whole) 
  values (2, "wypełnienie stałe", false);
insert into state (id, name, whole) 
  values (3, "wypełnienie czasowe", false);
insert into state (id, name, whole) 
  values (4, "korona", true);
insert into state (id, name, whole) 
  values (5, "przęsło  mostu", true);
insert into state (id, name, whole) 
  values (6, "proteza", true);
insert into state (id, name, whole) 
  values (7, "implant", true);
insert into state (id, name, whole) 
  values (8, "brak zęba", true);
insert into state (id, name, whole) 
  values (9, "do usunięcia", true);

W przyszłości stomatolog będzie mógł dodać swoje rodzaje “stanów”, określić, czy są “lokalne” i występują na powierzchi zęba, czy “globalne” i dotyczą całego zęba, a później zdefiniować szczegóły dotyczące renderowania.

API

Dodawanie zmian

Jak ma wyglądać API do rejestrowania zmian?

  • Zmiany mogą być jedynie dodawane, nie będzie ich usuwania (nie implementuję endpointów DELETE)
  • Dodawanie zmiany odbywa się zawsze w ramach wizyty, więc stworzę endpoint pozwalający na wywołanie żądania POST: POST /api/visits/:id/add
  • Do bazy pójdzie taka modyfikacja:
1
2
3
4
insert into change 
  (visit_id, state_id, tooth_num, tooth_side) 
values 
  (?, ?, ?, ?);

Wyszukanie zmian w ramach bieżącej wizyty

Do określenia zmian, jakie zostały wykonane w ramach bieżącej wizyty będzie służył endpoint GET /api/visits/:id/visitchanges:

1
2
[karma@tpd|~] curl -X GET "localhost:8080/api/visits/0/visitchanges"
[{"Id":0,"VisitId":0,"PatientId":1,"StateId":0,"ToothNum":21,"ToothSide":3},{"Id":1,"VisitId":0,"PatientId":1,"StateId":2,"ToothNum":25,"ToothSide":4},{"Id":2,"VisitId":0,"PatientId":1,"StateId":2,"ToothNum":26,"ToothSide":2}]

Stan uzębienia w dniu wizyty

Na podstawie zmian stanu dla każdego pacjenta będzie można “wyrenderować” bieżący stan uzębienia, a nawet (hm…) pokazać na osi czasu, jak i kiedy były wykonywane poszczególne zabiegi.

Na razie jednak skupię się na przygotowaniu danych potrzebnych do rysowania: posortuję zmiany dla bieżącego pacjenta w kolejności chronologicznej wizyt (aż do bieżącej wizyty, dla której renderuję widok), a w ramach wizyty posortuję po kolumnie time przechowującej timestamp zmiany:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
with
	pv(id, patient_id, vdatetime) as (
		select id, patient_id, vdatetime
		from visit
		where visit.id = ?)
select
	c.id, c.visit_id, v.patient_id, c.state_id, c.tooth_num, c.tooth_side
from
	change c
left join
	visit v
on
	c.visit_id = v.id
join
	pv
on
	v.patient_id = pv.patient_id
where
	v.vdatetime <= pv.vdatetime
order by
	v.vdatetime asc,
	c.time asc

Dzięki temu uzyskam listę zmian, które mogę nanieść na (nieistniejący jescze) widok uzębienia pokazujący stan jamy ustnej podczas wizyty.

Co dalej?

Na dziś to tyle. Trzeba w końcu zakasać rękawy i zasiąść do javascripta. Ale do tego potrzebuję jakiegoś spokojnego wieczoru.

A dziś jeszcze trzeba zdjąć pranie i nastawić kolejne, umyć naczynia, zetrzeć podłogę poplamioną bulgocącym leczo i przeczytać córeczce “Pucio na wakacjach”.

Kod

https://github.com/kamchy/dent.git