Budowa interfejsu administratora

TfrxDoc

Jest to kontrolka, która nie musi obowiązkowo występować w dokumencie, ale jej obecność jest bardzo wskazana. W przyszłych  wersjach może być obowiązkowa

Kontrolka ta zbiera w jednym miejscu zdarzenia i funkcje wspólne dla wszystkich poddokumentów występujących w całym dokumencie. Stąd jest wskazana do zarządzania polami (nadawanie wartości, odczyt wartości, inicjowanie wartości, walidacja dokumentu jako całości). Dostarcza też informacji o całym dokumencie.

Choć możliwe jest postawienie wielu kontrolek TfrxDoc na dokumencie, to analizowana jest tylko jedna, więc nie należy stawiać ich więcej, niż jedną (inaczej system nie wie, którą wybrać i wybór jest nieprzewidywalny)

Właściwości

Poniższe właściwości, mimo, że widoczne w czasie projektowania formularza mają sensowne wartości dopiero w czasie wykonywania.

property idx_raportu : integer
Zawiera idx aktualnego raportu
property idx_dokumentu : integer
Idx dokumentu, pod jakim cały dokument jest zapisany do bazy
property Editable : boolean
Czy dokument jest w chwili obecnej w stanie edycji
property Upr_odczyt : string
String z uprawnieniami wymaganymi do odczytu dokumentu. Analogiczne do funkcji WPContainer.GetDocReadRights
property Upr_edycja : string
String z uprawnieniami wymaganymi do edycji dokumentu. Analogiczne do funkcji WPContainer.GetDocEditRights
property Modified : boolean
Czy dokument został zmodyfikowany podczas obecnej sesji edycji jest dostępny
property MinStatusToPrint
Umożliwia określenie, jaki jest wymagany minimalny status dokumentu, by możliwe było jego wydrukowanie. Domyślnie X (czyli drukować można jedynie dokumenty zatwierdzone)
property MinStatus : char;
Tylko do odczytu. Określa najniższy stan grupy pól w aktualnym dokumencie.
property MaxStatus : char;
Tylko do odczytu. - Określa najwyższy stan grupy pól w aktualnym dokumencie.
property DefaultFieldGetOptions : TWPMailMergeContinueOptions
Określa domyślne parametry wstawianych danych podczas inicjowania pola za pomocą zdarzenia GetFieldValue

UWAGA: Domyślnie z przyczyn kompatybilności ze starymi raportami w polu jest ustawiona wartość: mmMergeAsHTML. Wydaje się, że optymalnie powinna być pusta i wówczas system będzie przyjmował tekst nieformatowany - czyli zachowa znaki końca linii i inne.

property FieldGetOptions : TWPMailMergeContinueOptions
Określa rzeczywiste parametry wstawianych danych podczas inicjowania pola za pomocą zdarzenia GetFieldValue. Może być w tym zdarzeniu zmieniane w celu wymuszenia odpowiedniego zachowania dla tego konkretnego pola. Jest zawsze przed wywołaniem zdarzenia GetFieldValue reinicjowane wartością z pola DefaultFieldGetOptions
property InitScriptsOnlyForEditable : Boolean
Domyślnie True. Powoduje, że skrypty i zdarzenia są odpalane jedynie gdy dokument jest edytowalny. Gdy False, to skrypt główny jest kompilowany zawsze (gdy skrypt jest dostępny) przy otwieraniu dokumentu i wykonywane są ewentualne zdarzenia (np.: OnGetFrameName).

UWAGA: Właściwość WPContainer.UseOpenDocForReading jest niezależna od tej opcji.

Funkcje

function GetFieldValue(ANazwa : string) : string
odczytuje wartość wskazanego pola. Preferowane jest stosowanie tej metody zamiast analogicznej związanej z containerami.
function GetFieldCode(ANazwa : string) : string
odczytuje wartość kodu wskazanego pola  (nie działa dla CheckBoxów)
function SetFieldValue(ANazwa : string; Value : string; Code = ‘##NULL##’) : boolean

wstawia wartość do wskazanego pola  ; Zwraca true, gdy zmieniono wartość

Dla CheckBoxów należy nadawać wartość   T, albo N.

Wywołanie bez podania wartości: Code powoduje nadanie jedynie wartości, a nie kodu – np.:

SetFieldValue(‘Jakas_nazwa_pola’, ‘Jakas wartość’);

Preferowane jest stosowanie tej metody zamiast analogicznej związanej z containerami.

UWAGA: Funkcja (podobnie jak i analogiczne w containerach) wstawiają wartość pola jedyni gdy pole znajduje się już w jakiejś otwartej karcie. Nie wstawia bezpośrednio danych do XMLa.

function SetFieldValueFormated(ANazwa : string; Value : string; AFormat : string = 'ANSI'; Code = ‘##NULL##’) : boolean

Funkcja analogiczna do SetFieldValue, ale pozwala na wprowadzanie tekstu formatowanego. Jako format można podać jedną z wartości: ANSI, RTF, HTML, WPTOOLS.

UWAGA1: Po wstawieniu wartości kursor jest automatycznie przemieszczany do podanego pola.

UWAGA2: Funkcji nie należy stosować w sytuacji, gdy pole występuje w dokumencie kilkukrotnie. Wówczas wywołanie funkcji spowoduje dublowanie treści pola.

UWAGA3: Funkcji ta obecnie jest zastąpiona przez funkcję SetFieldValueFormated2

function SetFieldValueFormated2(ANazwa : string; Value : string; AOptions : TWPMailMergeContinueOptions = 0; Code = ‘##NULL##’) : boolean

Preferowane jest stosowanie tej metody zamiast SetFieldValueFormated.

Pozwala na formatowanie stawianego tekstu w sposób analogiczny, jak podczas inicjowania pól w evencie OnFieldGetData.

Przykładowe wywołanie:

FieldContainer.SetFieldValueFormated2('epikryza','{\rtf1\ansi\ansicpg1250\deff0
\deflang1045{\fonttbl{\f0\fnil\fcharset238 Calibri;}{\f1\fnil\fcharset0 Calibri;}}
{\*\generator Msftedit 5.41.21.2509;}\viewkind4\uc1\pard\sa200\sl276\slmult1\f0
\fs22 No i nic do \ul\i\fs32 wstawie\ulnone\i0\fs22 nia\lang1033\f1\par}',
mmMergeAsRTF + mmIgnoreLoadedFontSize) // tekst jako RTF z pomijaniem wielkości czcionek
function ChkFrameLoaded(ANazwa : string; AAutoLoad : boolean = true) : boolean

Funkcja sprawdza, czy załadowany jest wskazany frame AName (może zawierać nazwę$sid). AAutoLoad oznacza, że jeśli nie jest, to go ładuje z dokumentu.
Jeśli frame nie istnieje, to zwraca false

UWAGA: Frame jest ładowany do wirtualnego okna - czyli nie załaduje go np. do okna zaleceń.

procedure ClearFieldsInGrup(AGrupa : string; ASID : string = ''; aForceForUpperStatus : boolean = false)

Czyści zawartość pól z podanej grupy o podanym SID (zarówno w XMLu, jak i w danych). Gdy pole ma status > 'A', wówczas by je wyczyścić trzeba ustawić: aForceForUpperStatus na True

function GetFieldParam(ANazwa : string; AParam : string) : string

Zwraca wartość wskazanego parametru AParam w definicji pola ANazwa. Jeśli pole nie istnieje, to zwraca ‘’. Nazwy AParam można znaleźć w dokumencie z definicjami pól.

Przykład:

ShowMessage(Doc.GetFieldParam('procedura', 'cmb_drop_data'));

function GetFieldList(AGrp : string) : TStringList

Funkcja tworzy listę nazw pól we wskazanej grupie AGrp.

Lista jest zwracana w postaci TStringList, więc konicznie trzeba pamiętać, by go zwolnić po wykorzystaniu (wskazane jest wykorzystanie konstrukcji Try … fnally).

Poniżej przykład pokazujący listę pól w grupie ‘Ogólne’ (lista nie jest przypisywana do zmiennej, ale obsługiwana w ramach With…  

with Doc.GetFieldList('Ogólna') do 
begin               
   try                                                                     
      ShowMessage(CommaText);               
   finally                                                                                           
      Free;               
   end;                                                                             
end;

Kolejny przykład:

s := '';                                                            
ls := Doc.GetFieldList('Ogólna');      
try                       
   for i := 0 to ls.Count-1 do              
      s := s + ',' + 

   Doc.GetFieldValue(ls[i]);         
   ShowMessage(s);      
finally                                                                                              
   ls.Free;    // Zwalnianie ls w ramach finally      
end;                                                  
function GetActualStatus(AFld : string; ASID : string = '') : string
Zwraca aktualny status (etap edycji) pól w grupie, do której należy wskazane pole. Pole może nie być jeszcze zapisane do dokumentu – w takim wypadku program ustali status pól z grupy na podstawie innych już istniejących pól.  Jeśli takich nie znajdzie, to zwraca ‘A’.
function CanEditField(AField : string; ASID : string) : boolean;
Czy wolno edytować wskazane pole. Pole może być podawane jako:  POLE$SID  (wówczas SID musi być równe ‘’), lub oddzielnie nazwa pola i SID
function CanReadField(AField : string; ASID : string) : boolean;

Czy wolno odczytywać zawartość wskazanego pola. Pole może być podawane jako:  POLE$SID  (wówczas SID musi być równe ‘’), lub oddzielnie nazwa pola i SID

function CanRevertField(AField : string; ASID : string) : boolean;

Czy wolno cofać aktualny etap edycji wskazanego pola. Pole może być podawane jako:  POLE$SID  (wówczas SID musi być równe ‘’), lub oddzielnie nazwa pola i SID

function GrpConfirm(AGrp : string; ASID : string = ‘’; AShowError : Boolean = true) : integer;
function GrpRevert(AGrp : string; ASID : string = ‘’; AShowError : Boolean = true) : integer;

Podane funkcje odpowiednio: zatwierdza, lub cofa zatwierdzenie wskazanej grupy pól.

function GrpConfirmRevertSafe(AGrps : string; AShowError : Boolean = true; AOperation: char = 'C'; AUslugiToConfirm : string = ''; aSource = ''; AKorekta : char = '-') : integer

Zatwierdza, cofa zatwierdzenie grup, lub jedynie zapisuje pola do BF (zaleznie od parametru ARevert (R - revert; C - confirm; S - jedynie zapis pól do BF) wg listy podanej w parametrze AGrps w postaci nazw pól i ew. SIDów oddzielnych przecinkami.  Nazwy można zawrzeć w cudzysłowie. Np: Grypa_pierwsza$SID123,"Grupa druga$123", GrupaTrzecia.

Fakty są zapisywane zgodnie z hierarchią określoną w powiązaniach między kategoriami - na podstawie tych powiązań system określa powiązania zapisywanych faktów. Jeśli w ramach jednego dokumentu są te same kategorie nadrzędne więcej, niz raz (np. dane dotyczące prawej i lewej strony) to o tym, do którego faktu nadrzędnego zostaną przypisane fakty podrzędne (czyli czy do prawej, czy lewej strony) decyduje kolejność wymieniania grup w parametrze AGrp. "Dzieci" są przypisywane do ostatnio dodanego rodzica.

Przykład takiego wywołania:

Doc.GrpConfirmRevertSafe('Ogólna,strony$lewa,ftb$tab_lewa_%,strony$prawa,ftb$tab_prawa_%', true, 'S', 'all', 'FfmBadanie|B' + 
inttostr());

Jeśli w ramach zapisywanej kategorii żaden atrybut nie ma wartości, wówczas taki fakt jest usuwany z bazy pod warunkiem, że w definicji powiązań między kategoriami kategoria tego faktu nie posiada kategorii podrzędnych w relacji PartOf.

Czyli jeśli podamy grupę i SID, które obecnie nie istnieją, wówczas system usunie ewentualne fakty odpowiadające tym parametrom (z uwzględnieniem opisanego wyżej wyjątku). Ma to zastosowanie do usuwania oddzielnie zatwierdzanych wierszy tabel - wówczas po usunięciu rekordu należy wykonać polecenie:

Doc.GrpConfirmRevertSafe('tabela$sid_rekordu_3', true, 'S', 'all', 'FfmBadanie|B' + inttostr());

które, jeśli rekord o sid=sid_rekordu_3 był usunięty, spowoduje usunięcie odpowiednich faktów z BF2.

Dla tabel zatwierdzanych w całości jako część dokumentu, zamiast podawania sidów dla poszczególnych rekordów należy podać SID zbiorczy w postaci: sid_odpowiadajacy_rekordowi_%. Wówczas system wykona operację dla wszystkich rekordów z tabeli (również tych, które zostały usunięte, co spowoduje usunięcie odpowiednich faktów).
Czyli aby zatwierdzić dokument zawierający grupę Ogólne i tabelę z polami z grupy tab i sidami w postaci sid_rekordu_, zamiast wymieniać rekordy należy wykonać polecenie:

Doc.GrpConfirmRevertSafe('Ogólne,tab$sid_rekordu_%', true, 'C', 'all', 'FfmBadanie|B' + inttostr());

Z racji zapisywania powiązań istotne jest również, by zawsze wymieniać wszystkie grupy z dokumentu by odzwierciedlić odpowiednią hierarchię nawet w sytuacji, gdy wiemy, że niektóre fakty będą zawierać puste dane - takie fakty nie zostaną zapisane, jeśli nie są nadrzędne. Jeśli są, to zostaną zapisane w pustymi wartościami, ale ich obecność pozwoli na zachowanie prawidłowych relacji między faktami. W ostateczności można podać grupy, które chcemy zachować w podanej hierarchii, przy czym nie wymieniać wszystkich grup, ale te, które stanowią zwartą gałąź, pod warunkiem jednak, że fakt nadrzędny jest j zapisany i daje się unikatowo zidentyfikować np. na podstawie klucza "W badaniu".

Aby mechanizm działał prawidłowo wszystkie kategorie muszą mieć określone rodzaj klucza głównego. Dzięki temu system jest w stanie odnaleźć odpowiedni fakt na podstawie jego parametrów i dokonać modyfikacji/usunięcia.

Preferuję do określanie klucza nie stosować Wg źródła. Dopuszczalne jest oczywiście stosowanie atrybutów jako część klucza. Wyjątkiem są kategorie zapisywane w tabelach. Wówczas dla prawidłowego usuwania rekordów wskazane jest stosowanie klucza Wg źródła, gdyż inne w praktyce będą wymagały rozbudowę klucza o atrybut, który byłby jednym z pól tabeli. Ponieważ w usuniętym rekordzie pola te są czyszczone, więc system nie potrafi określić faktu do usunięcia.

Opcjonalny parametr: AUslugiToConfirm powoduje od razu zmianę statusu usług o podanych idx (lub grupy usług) do statusu zgodnego ze statusem pierwszej zatwierdzanej grupy. Parametr może zawierać:

  • all - zatwierdza wszystkie usługi związane z dokumentem (czyli zgrupowane)
  • lista idx_uslug oddzielonych przecinkami - zatwierdza usługi o podanych idx

Parametr:

  • aSource określa do jakiego źródła należy zapisać fakty. Dla badań należy wpisać: FfmBadanie|Bidx_badania. Jeśli zapisujemy fakty z podanym SIDem, to zostanie on dodany do aSource.

  • aKorekta określa, czy dokument ma być oznaczony jako korygowany:

    • K - rozpoczęcie korekty
    • Z - zakończenie korekty dokumentu;

Jeśli podano aUslugiToConfirm, to dodatkowo zakończy dla tych usług korektę

Inne znaki - nic nie znaczą.

Czyli obecnie zakończenie korekty wygląda tak:

Doc.GrpConfirmRevertSafe('Ogólna', true, 'S', 'all', 'FfmBadanie|B' + inttostr(), 'Z');

Funkcja dodatkowo zapisuje dokument do bazy po zatwierdzeniu. Zapis jest bezpieczny - jeśli którykolwiek z elementów się nie powiedzie, wówczas całość jest wycofywana - również zmiany statusu XMLa.

Zwracają wartość typu Integer:

  • 0 – OK.
  • 1 – Nie odnaleziono grupy powiązanej ze wskazanym polem
  • 3 - Brak uprawnień do zmiany aktualnego etapu edycji danych
  • 4 - Nie określono wartości wymaganego pola
  • 5 - Dokument nie jest otwarty do edycji

Jeśli parametr AShowError = TRUE, wówczas, jeśli wynik 0 -  funkcja generuje wyjątek z odpowiednim komunikatem.

procedure CheckReportSources;

Funkcja odświeża powiązania DataSetów z formularza Delphi (np. qrPobyty z formularza fmHospPobyt). Można ją wykonać w sytuacji, gdy z jakiegoś powodu do powiązanie jest utracone (obecnie takie sytuacje nie powinny mieć miejsca, gdyż odświeżanie odbywa się automatycznie

 
function RegenerateField(AField : string) : string;

Funkcja dokonuje regeneracji wartości wskazanego pola (wypełnia go wartością domyślną).

Pole może zawierać SID.

Zwraca obliczoną wartość domyślną.

Nie można regenerować pól o wartości > ‘A’.

Funkcja działa prawidłowo w nowym systemie uprawnień.

UWAGA: Funkcja obecnie potrafi wstawiać również tekjst formatowany w sposób analogiczny jak podczas inicjowania pola)

procedure AddLink(APac, APobyt, ABadanie: Variant);

Definiuje powiązania dokumentu z pacjentem, pobytem i badaniem. Jeśli dla któregoś z powiązań podamy NULL, wówczas odpowiednie powiązanie nie jest tworzone.

UWAGA: Funkcja nie musi być w ogóle wykonywana – powiązania są tworzone automatycznie. Można jednak przy jej pomocy zmienić domyślne powiązania.

UWAGA: Niektóre uprawnienia edycji dokumentu są związane z powiązaniami dokumentu (np. uprawnienia do edycji badania). Stąd przy braku powiązania testowanie uprawnień da wynik negatywny

UWAGA: Funkcji NIE należy wykonywać dla dokumentów tworzonych w formularzu pobytu pacjenta na oddziale (są tworzone automatycznie)

Przykładowe wywołanie:

procedure wpOnBeforeSaveDocumentEvent(var ErrorMessage : string);

begin

       Doc.AddLink(1, NULL, NULL);

end;

procedure SaveToCache(AFrame : string = '')

Procedura zapisuje frame o podanej nazwie AFrame do tymczasowego schowka. Zapis dotyczy samego dokumentu - nie zapisuje pól z XMLa.
Dla głównego Frame'u (utworzonego bez SIDa z głównego componentu) nie podajemy nazwy.

function RestoreFromCache(AFrame : string= '') : boolean;

Procedura przywraca dokument AFrame na podstawie wcześniej zapisanego do schowka (zwraca true). Jeśli nie dokonano wczesniej zapisu poleceniem SaveToChache, to nic sie nie dzieje (zwraca false).  Odczyt dotyczy tylko treści dokumentu - nie modyfikuje w żaden sposób zapisanych danych w dotyczących pól XMLu.

Dla głównego Frame'u (utworzonego bez SIDa z głównego componentu) nie podajemy nazwy.

UWAGA: Oba polecenia zostały przygotowane w celu zapisania dokumentu, na którym dokonujemy formatowania i wypełniania pól nie zapisywanych do XMLa, by np. wygenerować wydruki z badań, a nastęnie chcemy przywrócić pierwotną postać. Stąd nalezy stosować ją ostrnie, jeśli dokonywano zmian powodujacych zapis danych do XMLa

Obsługa BF - ver. 1.0

function BfAdd(ASID : string; AKategoria : string; AAtrybuty : array; AWartosci : array) : integer

Funkcja dopisuje dane do bazy faktów.

ASID opisuje SID fragmentu dokumentu, który chcemy oznaczyć jako żródło faktu. W praktyce w żródle zostanie zapamiętany identyfikator dokumentu i podany SID. SID nie musi ospowiadać SID pól - chodzi o to, by można usunąć wszystkie fakty o podanym SID w razie konieczności ich ponownego zapisu do bazy faktów.

AKategoria - kategoria faktu

AAtrybuty - tabela z nazwami atrybutów, które chcemy wypełnić

AWartosci - tabela z wartościami atrybutów. Atrybuty można podawać jako liczby, lub stringi. Daty najlepiej podawać jako string w formacie RRRR-MM-DD

procedure BfAddRel(aidx_faktu : integer; aidx_faktu2 : integer; arelacja : string = 'P'; APozim : integer = 1)

Dodaje relacje pomiędzy faktami.

Procedure BfClear(ASID : string)

Usuwa wszystkie fakty pochodzące z aktualnego dokumentu z podanego ASID.

Przykład operacji na BF:

// Czyszczę nieaktualne wpisy (stare wersje faktów z tego samego dokumentu i SID = Dok

Doc.BfClear('Dok');

// Wstawiam fakt RR z jednym atrybutem (domyślnym): czas pomiaru oraz łączę je relacja PartOf z "dziećmi" - wartościami pomiarów

irr := Doc.BfAdd('Dok', 'RR', [''], ['20-03-2009 15:37']);

Doc.BfRel(Doc.BfAdd('Dok', 'SYST', [''], [150]), irr);

Doc.BfRel(Doc.BfAdd('Dok', 'DIAST', [''], [80]), irr);

Odczyt danych

Założenie jest takie, by ładować wszystkie fakty, które potrzebujemy np. podczas inicjowania dokumentu.

Wszystkie funkcje pracują na podzbiorze faktów załadowanych funkcją BfLoad.

function BfLoad(aidx_osoby, aidx_pobytu, aidx_badania, aidx_uslugi : integer; akategorie : variant) : boolean

Funkcja ładuje dane na temat podanej listy kategorii do pamięci. Mogą to być dane dotyczące pacjenta,pobytu, badania, lub usługi.

Kategorie podajemy w postaci tablicy.

Jeśli istnieją powiązania pomiędzy faktami, to są ładowane również fakty powiązane.

function BfFind(akategoria : string; aindex : char; aindexatr : string) : boolean

Funkcja pozwala na odnalezienie interesującego nas faktu w gronie poprzednio załadowanych funkcją BfLoad. Jej działanie polega za zawężeniu datasetu qryFakty do faktów spełniających kryteria

Akategoria oznacza poszukiwaną kategorię.

Aindex może przyjmować wartości:

L - oznacza rekord odpowiadający najniższej wartości atrybutu aindexatr

H - oznacza rekord odpowiadający najwyższemu wartości atrybutu aindexatr (czyli np. data ostatniego badania).

Gdy Aindex nie zostanie podany, wówczas szukanie jest zakańczane na etapie znalezienia kategorii, bez analizy wartości atrybutów

function BfGetAtr(aatr : string; APlain : boolean = false) : string

Funkcja pozwala doczytać wartość dowolnego atrybutu (aatr – nazwa atrybutu) faktu odnalezionego poprzednią funkcją.

Aplain – gdy TRUE, wówczas wartości numeryczne i daty nie są konwertowane do formatu stosowanego w systemie IC.

function BfFindRel(AElem : integer; APoziom: integer = 1; ARelacja: string = 'P'):boolean;

Funkcja szuka fakty powiązane z aktualnym fakem. Jej efektem jest zawężenie datasetu qryFakty do faktów spełniających kryteria (czyli powiązanych).

AElem – strona analizy powiązań. Relacje są zapisane w postaci Fakt X (AElem = 0) jest w relacji Arelacja z faktem Y (AElem = 0). Stąd dla relacji „X jest częścią Y”, jeśli do analiz wskażemy X – czyli AElem = 0 – wówczas znajdziemy wszystkie fakty, których częścią jest aktualny fakt (czyli znajdzie „rodziców”). Zależnie od wartości parametru Apoziom znajdziemy powiązania na odpowiednim poziomie. Analogicznie jeśli do analiz wskażemy Y (AElem = 1), to mówimy: „Znajdź fakty składowe aktualnego faktu – czyli fakty „dzieci”)

ARelacja – zakres analizowanych relacji – P: PartOf; A – AtributOf

Apoziom - Poziom analizowanych relacji. 1 oznacza bezpośrednio powiązane; 2 i wyższe – powiązania pośrednie; 0 – dowolne powiązania.

function BfGetActSelection: string;

Funkcja pozwala zachować aktualny wybór, by móc go następnie przywrócić do datasetu qryFakty po dokonaniu jakichś operacji.

procedure BfSetActSelection(AFilter: string);

Funkcja przywraca podany wybów Afilter do datasetu qryFakty.

Obługa BF - ver 2.0

function Bf(ASID : string; AKategoria : string; AAtrybuty : array; AWartosci : array; aCzas_faktu : TDateTiem = 0; idx_nadrzedny : integer = 0; alp : integer = 0; aidx_faktu:integer = 0; aOperation = 'I') : integer;

Zasadnicza funkcja służąca operacjom na faktach.

Należy ją stosować zarówno do dodawania, modyfikowania jak i usuwania faktów.

ASID - sid do zapisania do źródła faktu

AKategoria - nazwa kategorii faktu (nie są brane pod uwagę kategorie w relacji IS)

AAtrybuty     - tablica nazw atrybutów

AWartosci    - tablica z wartościami atrybutów

aCzas_faktu - czas zaistnienia zdarzenia odpowiadającego faktowi

idx_nadrzedny - idx faktu nadrzędnego

alp - pozycja faktu w ramach faktu nadrzędnego

aidx_faktu     - idx_faktu, którego dotyczy operacja - ma znaczenie dla modyfikacji i usuwania

aOperation    - oeracja dokonywana na fakcie

Gdy nie okreslono aidx_faktu, lub gdy nie onaleziono wskazanego faktu, to jest on dodawany.

Jeśli fakt istnieje to akcja jest zależna od pola:

  • aOperation
  • D  lub DELETE     - usuwa fakt
  • U  lub  UPDATE    - aktualizuje pola, dla których dostarczono wartości w parametrach; Atrybuty są aktualizowane w zakresie wskazanych atrybutów
  • O   lub OVERRIDE  - aktualizuje wszystkie pola dostarczonymi wartościami (też NULL) - atrybuty są zamienione jako całość tablicy VAL
  • I    lub INSERT    - dodaje, nie analizując wartości pola aidx_faktu

Zwraca idx_faktu, którego dotyczyła operacja - czyli np. idx nowoutworzonego faktu.

procedure BfAddRel(aidx_faktu : integer; aidx_faktu2 : integer; arelacja : string = 'P'; APozim : integer = 1)

Dodaje relacje pomiędzy faktami.

Procedure BfClear(ASID : string)

Usuwa wszystkie fakty pochodzące z aktualnego dokumentu z podanego ASID. UWAGA: Muszą dotyczyć tego samego pacjenta (co jest oczywiste)

function Bf2GetSQL(aLevel : string; akategorie: variant; afiltr: string) : string;

Generuje SQL zapytania do bazy faktów

aLavel - określa szczegółowość zapytania:

O - wszystkie fakty osoby powiązanej z dokumentem

H - wszystkie fakty z hospitalizacji powiązanej z dokumentem

P - wszystkie fakty z pobytu powiązanego z dokumentem

B - wszystkie fakty z badania powiązanego z dokumentem

U - wszystkie fakty z usługi powiązanej z dokumentem

aKategorie - lista nazw kategorii w postaci np: ['wynik', 'badanie fizykalne']. Funkcja uwzględnia podane kategorie i wszystkie, które od nich dziedziczą.

aFiltr - dodatkowy filtr do wstawienia do klauzuli WHERE - np:  'av(f) = ''Jakaś wartość'' '

Funkcja generuje SQL w postaci np:

select * /*pola*/ from getfacts_bad(34,751) f where nazwa = any(array[['WIZYTA','KODY'])

tak, by wpis /*pola*/ można było zamienić na dowolne dodatkowe pola. Dodatkowo tablica zaczyna się [[, tak by ten SQL można było wprost przypisać do SQL.Text dowolnego frxKQuery.

function Bf2GetAtr(aatr : string; aQuery : TfrxKQuery; APlain : boolean = false; aDefault : string = '##ERROR##') : string;

Pozwala na odczyt wartości wskazanego atrybutu z datasetu utworzonego przy użyciu poprzedniego polecenia. W razie błędu, gdy określimy aDefault, to ta wartość zostanie zwrócona - inaczej generowany jest wyjątek.

procedure Bf2Protect(afacts : string; alevel : string);

Funkcja ustawia zadany stopień protekcji aLevel dla faktów podanych na liście afacts (string zawierający listę idx_faktów oddzielonych przecinkami);

aLevel może przyjmować następujące wartości (cyfra):

0 - bez zabezpieczeń. Może być usuwany i modyfikowany
3 - nie wolno usuwać; Wolno modyfikować
8 - nie wolno usuwać, ani modyfikować.

UWAGA: Fakty muszą dotyczyć tego samego pacjenta.

function Bf2Is(aChild, aParent: string): boolean;

Funkcja sprawdza relację dziedziczenia (IS) - czy kategoria aChild równa się aParent, lub dziedziczy z aParent.

function Bf2GetAtrCount(aDataSet: TfrxKQuery): integer;

Funkcja zwraca ilość atrybutów w fakcie z aktualnego rekordu.

function Bf2GetAtrByName(aAtr: string; aDataSet: TfrxKQuery): TAtrEx;

Funkcja w aktualnym fakcie wyszukuje atrybut o podanej nazwie i go zwraca w postaci objektu klasy TAtrEx.

function Bf2GetAtrByIdx(aAtrIdx: integer; aDataSet: TfrxKQuery): TAtrEx;

Funkcja w aktualnym fakcie wyszukuje atrybut o podanej pozycji i go zwraca w postaci obiektu klasy TAtrEx.

Funkcja uwzględnia fakt,czy w fakcie zapisano wymaganą kolejność atrybutów (wówczas jest ona brana pod uwagę), czy nie - wówczas kolejność jest uzależniona od wartości LP atrybutu w definicji kategorii.

UWAGA: Idx oznacza pozycję na liście atrybutów, przy czym pierwsza pozycja ma aAtrIdx=0. Wartość ta nie ma związku z wartością LP, ani IDX w definicji atrybutów.

property LastAtr :TAtrEx

Ostatnio znaleziony atrybut funkcją: Bf2GetAtrByIdx lub Bf2GetAtrByName

 

Przykład dla BF1:

Doc.BfLoad(3,0,0,0,['RR']); // Odczyt faktów pomiarów RR i powiązanych dla pacjenta o idx = 3

if Doc.BfFind('RR', 'H', 'Czas pomiaru') then // Szukam najnowszego pomiaru
   showMessage(Doc.BfGetAtr('Czas pomiaru')) 
else
   ShowMessage('Nie odnaleziono');

sr := Doc.BfGetActSelection; // zapamiętuję wybór faktu - by później do niego wrócić

if Doc.BfFind('SYST', 'H', '') then // Szukam jakiegokolwiek ciśnienia skurczowego (nie analizuję wartości)
   showMessage(Doc.BfGetAtr('Wartosc')) // Zwracam jego wartość
else
   ShowMessage('Nie odnaleziono');

// Załóżmy, że obecnie stoję na fakcie kategorii: Ciśnienie skurczowe (SYST).Jest on częścią ciśnienia RR
// Znalazłem dziecko (SYST) -> szukam rodzica (czyli SYST IsPartOf RR)

if Doc.BfFindRel(0) then begin
   // Znalazłem rodzica (RR)
   // Odczytuję, kiedy wykonano pomiaru (atrybut klasy RR); Przy okazji zwracam uwagę na funkcję: GetExtListValue
   s := GetExtListValue('kategorie', ) + ' wykonano: ' + Doc.BfGetAtr('Czas pomiaru') + #13#10;

   // Teraz szukam składowych (czyli elementów, które są składowymi RR)
   if Doc.BfFindRel(1) then begin // czyli dzieci aktualnej relacji IsPartOfWhat
      while not performdataset('qryFakty', 'Eof') do begin
          s := s + GetExtListValue('kategorie', ) + ' wynosi ' + Doc.BfGetAtr('Wartosc') + #13#10;
         performdataset('qryFakty', 'Next') 
      end; 
   end
   else
      ShowMessage('Nie udało się odnaleźć dzieci'); 

   showMessage(s);
end 
else 
   ShowMessage('Nie odnaleziono rodzica');

// teraz próba powrotu do faktu RR
Doc.BfSetActSelection(sr);
ShowMessage('Powrót do faktu: ' + GetExtListValue('kategorie', ));

Przykład dla BF2:

Założeniem przy tworzeniu API dla BF2 było to, można korzystać z klasycznych funkcji i poleceń datasetów zamiast tworzyć specjalne polecenia.

Poniżej przykład użycia funkcji BF2GetSQL i Bf2GetAtr

s := Doc.BF2GetSQL('B', ['WIZYTA', 'KODY'], '');

ShowMessage('Zapytanie: ' + s);

with qrZapBF2 do begin    // Zwykła kontrolka z datasetem postawiona na raporcie i połączona z dmCommon.db_bf
   if SQL.Text  '' then
      Close;
      SQL.Text := s;
      Open;
   end;
   First;
   s := '';

   while not qrZapBF2.eof do begin
      if  = 'KODY' then
         s := s + ' atr: kod:' + Doc.Bf2GetAtr('kod', qrZapBF2) + ' treść: ' + Doc.Bf2GetAtr('treść', qrZapBF2)
      else
         s := s + ' atr: Wartość:' + Doc.Bf2GetAtr('wartość', qrZapBF2) + ' bdf: ' + Doc.Bf2GetAtr('bdf', qrZapBF2);
      Next;
   end;

ShowMessage('Wynik: ' + s);
end; 

Przykład 2 - zaawansowany odczyt atrybutów: (zwracam uwagę na fakt, że pierwszorazowe wykonanie funkcji Bf2GetAtrByIdx powoduje inicjację LastAtr dzięki czemu w celu odczytu parametrów tego samego atrybutu nie trzeba ponownie wykonywać funkcji

s := Doc.BF2GetSQL('O', ['OSOBA'], '');
ShowMessage('Zapytanie: ' + s);
with qrZapBF2 do begin
    if SQL.Text s then begin
        Close;
        SQL.Text := s;
        Open;
    end;
    First;
    s := '';
    while not qrZapBF2.eof do begin
        c := Doc.Bf2GetAtrCount(qrZapBF2);
        s := #13#10 + 'Fakt: ' + FloatToStr() + #13#10;
        for i := 0 to c-1 do begin
            s := s + Doc.Bf2GetAtrByIdx(i, qrZapBF2).etykieta + ' = ' + Doc.LastAtr.Value + #13#10;
        end;
        s := s + 'Oraz dodatkowo wg nazwy atrybutu: ' + Doc.Bf2GetAtrByName('NAZWISKO', qrZapBF2).etykieta + ' = ' + Doc.LastAtr.Value + #13#10;
        Next;
    end;
    ShowMessage('Wynik nowy: '+ #13#10 + s);
end;

Datasety można też filtrować - np: np:

qrZapBF2.Filtered := false;                            
if qrZapBF2.Filter = ('nazwa = ''KODY''') then                                         
  qrZapBF2.Filter := 'nazwa = ''WIZYTA'''
else
  qrZapBF2.Filter := 'nazwa = ''KODY''';
qrZapBF2.Filtered := true;

 

Zdarzenia: OnFieldGetData

podczas inicjacji dokumentu – umożliwia wprowadzanie wartości domyślnych. Podczas inicjowana dokumentu wartość pola jest wypełniana wartością pola pochodzącą z innych formularzy dokumentu. Jeśli nigdzie nie ma tego pola, wówczas jest odczytywana wartość z sekcji dane XML. Jeśli i tu nie zostanie odnaleziona, wówczas jest generowana na podstawie wyrażenia wartości domyślnej i kierowana do tego zdarzenia. Wartość zwrócona przez to zdarzenie jest wstawiana do inicjowanego pola.

   Zwrócona wartość jest przetwarzana przez system w zaleności od aktualnej wartości własności: FieldGetOptions, którą można w tym zdarzeniu dowolnie ustawić. Jeśli nie dokonamy zmian tej wartości to brana pod uwagę jest wartość z pola: DefaultFieldGetOptions. Dzięki temu możliwe jest np. określenie formatu, w jakim wstawiamy tekst. 

Przykład:

procedure FieldContainerOnFieldGetData(Sender: TComponent; Field: string; var Result : string; var ACode : string);
begin

  If field = 'epikryza' then begin
   
   if NOT qrFakty.FieldByName('Epikryza').IsNull then begin

     // Poniższy zapis oznacza, że wpisywany poniżej tekst jest w formacie RTF

     // oraz ma być zastosowane mmDeleteEmptyParagraph  (dla przykładu)

     // Jeśli chcemy określić, że jest to zwykły tekst, to najlepiej podać:

     // FieldContainer.FieldGetOptions :=  0;

     FieldContainer.FieldGetOptions :=  mmMergeAsRTF + mmDeleteEmptyParagraph;

      // Teraz zapis pola w formacie określonym powyżej.

      // Zakładam, że pole Epikryza jest pobrane z faktu, w którym automatycznie

      // zapisano dane formatowane, lub ręcznie zapisano dane po kompresji funkcją CompressEndStr


     result := DeCompressEncStr(qrFakty.FieldByName('Epikryza').AsString);       

   end;
      
  end;
    
end;
      

   UWAGA: Obecnie jest to preferowane  zdarzenie inicjowania pól (należy je stosować zamiast analogicznego zdarzenia w klasach frxWPContainer i frxFRContainer). Jeśli jest ono przypisane, wówczas analogiczne zdarzenia wspomnianych klas nie są wywoływane.    

OnAcceptDefFieldValueEvent

Zdarzenie jest wywoływne podczas inicjowania danych na podstawie BF2. Gdy dane pole jest automatycznie inicjowane na podstawie BF2, wówczas dla każdego inicjowanego pola po ustaleniu inicjowanych wartości  jest wywoływane to zdarzenie. W ramach jego obsłygi można odrzucić inicjację tego pola ustawiając Accept na false, lub zmienić zainicjowane wartości odpowiednio modyfikując parametry: AValue, ACode, APlainValue.

W czasie wywołania można posługiwać się wszystkimi danymi z faktu źródłowego - jest on ustawiony w datasecie: qrBfInit.  UWAGA: W definicji raportu trzeba z zakładce Raport/Date zaznaczyć ten dataset, by był on dostępny z poziomu kodu. Dataset oferuje te same pola co view  facts z bazy bf2.

Przykładowa obsługa zdarzenia:

 

procedure DocOnAcceptDefFieldValueEvent(AField: string; var AValue: string; var ACode : string; var APlainValue : string;  AFieldGetOptions :     TWPMailMergeContinueOptions; var Accept : boolean);
begin
 
  // Aktualny rekord w datasecie: qrBfInit jest źródłem faktu, 
  // więc można pobrać z niego dowolne dane na temat faktu - również z poszczególnych atrubutów (funkcja: Bf2GetAtr)
 
  //Można też zmienić wartości uznane za domyślne np zapis poniżej:
  APlainValue := APlainValue + ' - a teraz dodany';                                                                                                

  // SPrawdzam, czy jest fakt z konkretnego dnia i tylko te akcepuję; 
  Accept : = Trunc()=   Trunc(StrToDate('10-11-2011'));   
 
     //Można też np sprawdzić, czy jest z dzisiaj:   
     //    Trunc() =  Trunc(date);
end;

OnBeforeChangeFieldEvent

Wywoływana podczas zmiany wartości pola – zanim wartość zostanie zapisana do poszczególnych pól w formularzach.

Umożliwia dokonanie zmian zapisywanych wartości poprzez odpowiednią modyfikację zmiennych: ANewValue i ANewCode. Dzięki temu można przez zapisem np. zmienić czcionkę na dużą. Podczas dalszej modyfikacji pola są wywoływane analogiczne zdarzenia w poszczególnych containerach zawierających wskazane pole.

UWAGA: Patrz na opis TfrxDoc.OnBeforeChangeFieldEvent

  OnBeforeConfirmDocumentEvent        

  •  zdarzenie jest wywoływanie podczas wciśnięcia klawisza „Zatwierdź”, lub „Cofnij zatwierdzenie”  na formularzu edycji danych (np. w formatce pobytów), która ma za zadanie zakończyć etap edycji danych grupy pól, w której stoi kursor.

W zdarzeniu tym można dokonać samodzielnie zakończenia etapu – wówczas należy wstawić False w parametr: ADoDefault.

Parametr: ARevert oznacza, czy operacja dotyczy zakańczania, czy cofania zakończenia etapu edycji.

Wpisanie jakiegoś komunikatu do zmiennej AMessage powoduje wyświetlenie jej jako błędu i przerwanie zakańczania dokumentu.

W związku z tym komunikat może być wykorzystywany również do dokonywania walidacji przed zakończeniem, choć lepsza wydaje się w tym celu zdarzenie: OnBeforeChangeStatus, które jest wywoływane po OnBeforeConfirmDocumentEvent. OnBeforeChangeStatus(AGrp : string; ASID : string; AOldStatus : string; ANewStatus : string; var AMessage : string);

Wykonywane tuż przed zmianą etapu edycji grupy pól (już po sprawdzeniu uprawnień do tej operacji).

Jeśli wprowadzi się jakąś wiadomość do zmiennej AMessage wówczas zostanie to zgłoszone jako błąd i zmiana nie zostanie dokonana. OnAfterChangeStatus(AGrp : string; ASID : string; AOldStatus : string; ANewStatus : string; var AMessage : string);

Wykonywane tuż po zmianie etapu edycji grupy pól (już po zaktualizowaniu protekcji pól odzwierciedlającej nowy status pól).

Jeśli wprowadzi się jakąś wiadomość do zmiennej AMessage wówczas zostanie to zgłoszone jako błąd, jednak zmiana zostanie już dokonana. OnGetPathAndName(var AName, APath : string)

Ustalanie ścieżki w drzewie dokumentów i nazwy dokumentu, gdzie należy zapisać dokument. UWAGA: Dotyczy dokumentów innych, niż powiązanych z pobytami tworzonymi w formularzu pobytów.

OnAddImageEvent(aImage : TObject; AParam : string)

Wywoływany przez aplikację w celu wklejenia obrazka aImage (TJPEGImage) do dokumentu. aParam obecnie nie jest stosowany. Proponowana obsługa - np. funkcja: frxWPContainer.InsertImageToTable

OnGetFactTimeStamp(aCategory : string; aSid : string; var aStamp : TDateTime)

Wywoływany w momencie autmatycznego zapisywania faktów do BF. Pozwala dla kategorii aCategory  i sidu aSid określić czas faktu, który zostanie zapisany do bazy. Obługa polega na przypisaniu dati i czasu do zmiennej: sStamp. Jeśli event nie jest obsłoy, to system przypisze aktualną datę i czas.

OnGetFrameNameEvent(aFrameId : string; var aFrameName : string);

Wywoływany w momencie, gdy system chce ustalić jakie frame prezentować w poszczególnych oknach (dotyczy np. w formularzu badania okien przebiegu wizyty oraz okna zaleceń).
Dla podanego aFrameId okreslamy frame (z dopuszczalnym SIDem) za pomocą którego ma być prezentowany dany widok.
Dla badań obecnie dopuszczamy aFrameID: 
      MainFrame - oznacza przebieg wizyty
      Zalecenia - oznacza zalcenia

Brak obsługi zdarzenia powoduje przyjęcie wartości domyślnych wynikających z ustawień MainContainer kontenerów (dla nowotworzonych dokumentów) i tego jak dokument został zapisany.

UWAGA: Event jest wywoływany często przed załadowaniem framów, więc mogą źle działać funkcje GetFldValue - stąd decyzja o wyborze framów powinna być uzalniona od twardych danych takich, jak dane z bazy, uprawnienia itp.

OnPrepareDocument  (var AName : string; var aUsl : string; var aRodzajDokumentu : integer; var aSource : string; var aStatusProtekcji : string; var aDokStatus : string; aParam : string; var aContinue : boolean)

Wywoływany w czasie generowania dokumentów z wynikami.
Parametr aUsl sły do zwracania informacji o tym, dla jakich usług generujemy dokument:
- ALL (lub pusty string) oznacza wszystkie usługi w grupie
- MAIN - oznacza główną usłgugę z grupy
- lista idx_uslug oddzielonych przecinkami - oznacza listę usług
aRodzajDokumentu oznacza odppwiedni rodzaj dokumentu: s_uslugi_dok_standardowe.idx_sdokumentu_uslugi
aSource oznacza skąd ma pochodzić treść dokumentu. Obecnie dopuszalne jest:
- pusty ciąg - wówczas z głównego frame - czyli z zakładki przebiegu wizyty
- 'Zalecenia' - z framu zaleceń
- Nazwa dowolnego innego componentu (frxFR/WPComponent) w połaczeniu z ewentualnymi SIDami. Takie wywołanie spowoduje utworzenie odpowiedniego Framu i zapis wygenerowanej treści do dokumentu
Planowane jest rozszerzenie o możliwość generowania na podstawie innego raportu.
aStatusProtekcji - pozwala wymusić inny, niz liczony na podstawie statusus usługi stopień protekcji; Gdy puste - system dobierze automatycznie
aDokStatus - narzuca status dokumentu. Obecnie obsługiwane: N - zwykły (wart. domyślna); U - ukryty - czyli niewidoczny w przeglądarce; widoczny w badaniu;   
aContinue - gdy zwrócimy TRUE, to system po wygenerowaniu dokumentu ponownie wywoła Event i wygeneruje kolejny dokument; FALSE - kończy generowanie dokumentów
sParam  Dwie wartości parametru mają znaczenie:
'' - czyli pusty parametr jest wysyłany standardowo przez mechanizm zapisu dokumentów - np. w momencie zakańczania usługi
'#główny#' - ten ciąg znaków jest wysyłany w sytuacji, gdy system oczekuje zapisu dokumentu głownego - jest on niezbędny, by mna do niego doczepić
Ponadto parametr może przyjmować dowolną wartość zależnie od tego, co zostanie wysłane przez użytkownika funkcją AddDocument 

OnNotifyEvent(aEvent : string; aParam : string);

Wysyłany jako informacja o wielu róznych zdarzeniach.

aEvent zawiera nazwę zdarzenia. Obecnie zawiera jedną z wartosci:

  • CONFIRM   - oznacza, że właśnie wciśnięto klawisz zatwierdzania usługi. W ramach obsługi zdarzenia należy przyjąć, że do prawidłowego funkcjonowania zatwierdzania/cofania zatwierdzania koniecznie trzeba korzystać z nowej funkcji: GrpConfirmRevertSafe
  • CORRECTION   - rozpoczęto  wykonywanie korekta badania. Przykładowa obsługa poniżej:
      if aEvent = 'CORRECTION' then 
            Doc.SetFieldValue('Powód korekty', 'Powód korekty: ' + Param);                                                                                                                                  
  • CORRECTIONEND  - zakończenie korekty. Skrypt powinien zakończyć korekte dokumentu i usługi. Przykład:
    Doc.GrpConfirmRevertSafe('Ogólna', true, 'S', 'all', 'FfmBadanie|B' + inttostr(, 'Z'));
  • VIEWCHANGED  - po odswieżeniu tabeli qrUslugi, zmianie zakładki i kilku innych rzadszych zdarzeniach
  • FACTSSAVED - wysyłana po zatwierdzeniu dowolnego dokumentu. W aParam podana jest lista zapisanych kategorii oraz informacje o powiązaniach zapisanych faktów w postaci listy oddzielonej przecinkami - jak niżej:
    idx_osoby,idx_hosp,idx_pobytu,idx_badania,idx_uslugi,kategoria1,kategoria2,kategoria3.....
    Event jest wysyłany do wszystkich aktualnie otwartych w systemie dokumentów (też aktualnie nie edytowanych)
    Nazwy kategorii są zapisane dużymi literami. 
  • VIEWCHANGED  - po odswieżeniu tabeli qrUslugi, zmianie zakładki i kilku innych rzadszych zdarzeniach
  • REFERRALCHANGED - po dodaniu nowego skierowania i usunięciu istniejącego do listy skierowań oraz wystawieniu skierowania na wizytę kontrolną.

aParam - dodatkowe parametry zadarzenia. Wysyłany jako informacja o wielu różnych zdarzeniach.

OnBeforeSaveFacts(AGrp : string; ASID : string; var aSource : string; var aSaveFacts : boolean);

Wywoływane podczas zatwierdzania grupy pól w celu potwierdzenia źródła, jakie ma być użyte do zapisu faktów z aktualnej grupy.

Agrp i ASID oznaczają aktualnie zatwierdzaną grupę.M

  • aSource - śródło, jakie zostanie dodane do zapisywanych faktów (można zmienić)
  • aSaveFacts - jeśli ustawimy na false, to fakty z tej grupy nie będa zapisywane. UWAGA: Ten parametr można ustawiać na FALSE jedynie w sytuacji, jeśli aktualnie zapisywane kategorie nie są nadrzędne wobec jakichś innych kategorii. W przeciwnym razie brak zapisu danej kategorii nadrzędnej uniemożliwi zapis "dzieci", lub dopięcie ich do innego, ostatnio zapisanego faktu danej kategorii nadrzędnej.

Ze zdarzeniem wiąże się obecnie promowany zapis faktów powiązanych do BF.

Przykład - gdy dodajemy tabelę, to pozycje w danym rekordzie tabeli powinny otrzymać jako fakt nadrzędny jakiś fakt z głównego dokumentu. Source dla poszczególnych rekordów nie musi odpowiadac dokładnie pozycji w tabeli, ale np. pochodzić wprost z jakiegos pola w tabeli - np. dla formularza zabiegu wszczepienia stymulatorów w tabeli z listą wszczepionych elektrod optymalnie byłoby, by każda elektroda z jej parametrami była oddzielnym faktem z atrybutami takimi jak nazwa, nr seryjny, próg stymulacji itp. Jej faktem nadrzędnym powinien być zabieg implantacji, a SIDy dla źródła powinny odpowiadać lokalizacji elektrody - np. prawy przedsionek, lewy przedsionek itp.