Przejdź do treści

Bundle

Model Bundle jest globalnym, wspólnym zasobem integracyjnym standardu Kamsoft.FAIR. Wzorowany jest na FHIR Bundle, ale w uproszczonej postaci przeznaczonej do wymiany żądań i odpowiedzi między modułami API.ERP.

Bundle nie dziedziczy po DomainResource — jest osobnym typem transportowym (envelope).


1. Zakres i zastosowanie

Bundle jest samodzielnym zasobem integracyjnym i pełni rolę lekkiego zestawu dla scenariuszy, w których jedna wiadomość przenosi:

  • typ zestawu wymiany (type jako prosty code),
  • sekcję request z listą operacji (opcjonalnie),
  • sekcję response z uproszczonym statusem wyniku i listą operacji wynikowych,
  • każda operacja zawiera method, url (URI do referowania wewnętrznego) oraz resource (lub payload zdarzenia — patrz tryb message).

Model nie implementuje pełnej semantyki FHIR Bundle.entry[]. Zamiast tego upraszcza strukturę do dwóch sekcji biznesowych: request i response.

Zasada agnostyczności typu zasobu

Pole type określa sposób obsługi zestawu, a nie rodzaj przenoszonych danych. W request.items / response.items (tryby collection, batch, transaction, document) może znaleźć się dowolny DomainResource — np. Party, ProductDefinition, Document, InventoryDocument, Employment itd.


2. Typy bundle (type)

Dozwolone wartości type:

Wartość Semantyka (skrót)
collection Zbiór zasobów w odpowiedzi (odczyt)
batch Wiele operacji CRUD — każda niezależnie
transaction Wiele operacji CRUD — jedna transakcja (all-or-nothing)
message Zdarzenia integracyjne — nie model CRUD zasobów
document Spójny zestaw zasobów tworzących jedną całość dokumentową

W modelu JSON pole type jest prostym kodem, wzorowanym na FHIR code.

2.1 collection — zbiór elementów w odpowiedzi

Aspekt Opis
Cel Opakować wynik zapytania — lista zasobów zwróconych w jednej odpowiedzi
Kierunek Głównie response; request opcjonalny (kryteria wyszukiwania)
Atomowość Brak — brak operacji zapisu, tylko agregacja odczytu
Obsługa items Każdy element to niezależny wynik; brak wspólnej transakcji
response.status Zwykle success; partial gdy część elementów nie została dołączona (np. brak uprawnień do pojedynczego rekordu)

Typowe użycie: stronicowany wynik GET kolekcji, wyszukiwanie z wieloma trafieniami, zestawienie powiązanych zasobów zwróconych klientowi w jednym payloadzie.

2.2 batch — niezależna obsługa zasobów wewnątrz

Aspekt Opis
Cel Wykonać wiele operacji CRUD w jednym żądaniu HTTP
Atomowość Brak — operacje są niezależne
Wynik response.status: success, partial lub failure
Rollback Nie — udane operacje pozostają zatwierdzone; nieudane zwracają błąd per item
Per-item Każdy element response.items odpowiada pozycji z request.items; method może być error przy niepowodzeniu pojedynczej operacji

Typowe użycie: masowy import lub synchronizacja wielu zasobów z systemu zewnętrznego, gdzie błąd jednej pozycji nie powinien cofać pozostałych.

2.3 transaction — akcje w kontekście jednej transakcji

Aspekt Opis
Cel Wykonać wiele operacji CRUD jako jedna transakcja biznesowa
Atomowość Tak — all-or-nothing
Wynik success tylko gdy wszystkie operacje się powiodły; w przeciwnym razie failure i rollback całości
Referencje wewnętrzne urn:uuid: w url do powiązań między tworzonymi zasobami w ramach tego samego bundle (np. PartyPartyRole)

Typowe użycie: utworzenie powiązanych zasobów, które muszą wejść do systemu razem; operacje wymagające spójności referencyjnej w jednym kroku.

2.4 message — obsługa zdarzeń, nie zasobów

Aspekt Opis
Cel Przenosić komunikaty / zdarzenia integracyjne (pub/sub, webhooki, kolejki)
Zawartość Payload nie jest modelem CRUD zasobów; zawiera typ zdarzenia, metadane, opcjonalnie referencje do zasobów
Odróżnienie collection, batch, transaction, document operują na DomainResource w modelu żądanie/odpowiedź; message służy powiadomieniu o zdarzeniu — konsument sam pobiera zasoby, jeśli potrzebuje
Kierunek Zwykle jednokierunkowy (event); request lub response zależnie od profilu integracji

Elementy items w trybie message mogą nie być pełnymi DomainResource — struktura zależy od profilu zdarzenia (np. eventType, occurredAt, subject jako Reference).

2.5 document — spójna całość dokumentowa

Aspekt Opis
Cel Zestaw zasobów tworzących jedną spójną całość (jedno źródło prawdy)
Zawartość Dowolne DomainResource powiązane semantycznie (np. dokument + pozycje w contained, dokument + załączniki)
Atomowość Zależy od profilu i kontraktu API — często jak transaction przy zapisie

3. Porównanie trybów

Tryb Co niesie items Atomowość zapisu Typowy kierunek
collection dowolne DomainResource (odczyt) — (brak zapisu) response
batch dowolne DomainResource (CRUD) nie — partial OK request → response
transaction dowolne DomainResource (CRUD) tak — all-or-nothing request → response
message zdarzenia (nie pełny CRUD) zależy od brokera asynchroniczny flow
document dowolne DomainResource (spójna całość) zależy od profilu request i/lub response

4. Struktura Bundle

Nazwa Kard. Typ Opis
resourceType 0..1 string Bundle (konwencja REST)
type 1..1 code collection, batch, transaction, message, document
identifier 0..* Identifier Identyfikator zestawu (opcjonalnie)
comment 0..1 string Opis zestawu
request 0..1 BundleSection Sekcja żądania
response 0..1 BundleSection Sekcja odpowiedzi

Co najmniej jedna z sekcji request lub response powinna być obecna (zależnie od trybu i kierunku wymiany).


5. Sekcja request

Sekcja request zawiera minimalne informacje potrzebne do opisania intencji operacji:

Nazwa Kard. Typ Opis
items 1..* BundleItem[] Lista operacji request
items[].method 1..1 code Operacja: create, read, update, delete
items[].url 1..1 uri Wewnętrzny identyfikator URI (ResourceType/id lub urn:uuid:…)
items[].resource 0..1 DomainResource | object Zasób lub payload (w message — struktura zdarzenia)

method opisuje zamiar biznesowy, a nie bezpośrednio metodę HTTP.


6. Sekcja response

Sekcja response zawiera wynik przetwarzania żądania:

Nazwa Kard. Typ Opis
status 1..1 string Wynik zestawu: success, partial, failure
detail 0..1 string Zwięzły opis wyniku lub błędu
items 0..* BundleItem[] Lista operacji response
items[].method 1..1 code Operacja powiązana z wejściową lub error przy błędzie pozycji (batch)
items[].url 1..1 uri Wewnętrzny identyfikator URI
items[].resource 0..1 DomainResource | object Zasób wynikowy lub szczegóły błędu / zdarzenia

status pozostaje domenowy i uproszczony. Mapowanie na kody HTTP powinno być opisane na poziomie kontraktu API, a nie w samym modelu zasobu.

Reguły response.status:

  • batch: success — wszystkie OK; partial — część OK; failure — wszystkie nieudane
  • transaction: success lub failure (bez partial)
  • collection: zwykle success; partial gdy nie wszystkie elementy mogły zostać zwrócone

7. Przykłady

7.1 transaction — powiązane zasoby (all-or-nothing)

{
  "resourceType": "Bundle",
  "type": "transaction",
  "request": {
    "items": [
      {
        "method": "create",
        "url": "urn:uuid:party-1",
        "resource": {
          "resourceType": "Party",
          "id": "party-001",
          "comment": "Nowy podmiot biznesowy"
        }
      },
      {
        "method": "create",
        "url": "urn:uuid:party-role-1",
        "resource": {
          "resourceType": "PartyRole",
          "id": "pr-001",
          "comment": "Rola podmiotu: dostawca",
          "owner": [{ "system": "internal-reference", "value": "urn:uuid:party-1" }]
        }
      }
    ]
  },
  "response": {
    "status": "success",
    "detail": "Wszystkie obiekty zostały utworzone pomyślnie.",
    "items": [
      {
        "method": "create",
        "url": "urn:uuid:party-1",
        "resource": {
          "resourceType": "Party",
          "id": "party-001",
          "meta": { "lastModified": "2026-05-29T10:15:00Z" }
        }
      },
      {
        "method": "create",
        "url": "urn:uuid:party-role-1",
        "resource": {
          "resourceType": "PartyRole",
          "id": "pr-001",
          "meta": { "lastModified": "2026-05-29T10:15:01Z" }
        }
      }
    ]
  }
}

7.2 collection — zbiór zasobów w odpowiedzi

{
  "resourceType": "Bundle",
  "type": "collection",
  "identifier": [{ "value": "search-parties-active" }],
  "response": {
    "status": "success",
    "items": [
      {
        "method": "read",
        "url": "Party/party-001",
        "resource": { "resourceType": "Party", "id": "party-001", "comment": "Kontrahent A" }
      },
      {
        "method": "read",
        "url": "Party/party-002",
        "resource": { "resourceType": "Party", "id": "party-002", "comment": "Kontrahent B" }
      }
    ]
  }
}

7.3 batch — niezależne operacje (partial OK)

{
  "resourceType": "Bundle",
  "type": "batch",
  "request": {
    "items": [
      {
        "method": "update",
        "url": "ProductDefinition/pd-001",
        "resource": { "resourceType": "ProductDefinition", "id": "pd-001", "name": "Towar A (nowa nazwa)" }
      },
      {
        "method": "create",
        "url": "urn:uuid:pd-new",
        "resource": { "resourceType": "ProductDefinition", "id": "pd-999", "name": "Towar nowy" }
      }
    ]
  },
  "response": {
    "status": "partial",
    "detail": "1/2 operacji zakończonych powodzeniem",
    "items": [
      {
        "method": "update",
        "url": "ProductDefinition/pd-001",
        "resource": { "resourceType": "ProductDefinition", "id": "pd-001", "name": "Towar A (nowa nazwa)" }
      },
      {
        "method": "error",
        "url": "urn:uuid:pd-new",
        "resource": {
          "resourceType": "OperationOutcome",
          "comment": "Duplikat identyfikatora"
        }
      }
    ]
  }
}

7.4 message — zdarzenie integracyjne

{
  "resourceType": "Bundle",
  "type": "message",
  "identifier": [{ "value": "evt-2026-00042" }],
  "response": {
    "status": "success",
    "items": [
      {
        "method": "event",
        "url": "Document/doc-invoice-001",
        "resource": {
          "eventType": "DocumentPosted",
          "occurredAt": "2026-06-01T14:30:00Z",
          "subject": { "reference": "Document/doc-invoice-001", "type": "Document" }
        }
      }
    ]
  }
}

8. Odniesienia