Immunizations Service — Domain Model
Status: populated Owner: TBD Last updated: 2026-04-18 Companion: Service Template
1. Aggregate Roots
1.1 ImmunizationRecord
The central aggregate. Represents a single vaccine dose event — administration, refusal, or historical record — for one patient.
ID prefix: imm_
Invariants:
patientIdmust reference a registered patient (not deceased at time of recording).vaccineCodemust resolve in the EPI schedule vocabulary.- A recorded dose cannot transition back to
refusedornot-given. lotNumberis required for administered doses; optional for historical and refused records.administeredAtmust not be in the future.doseQuantitymust be a positive number when provided.- Contraindicated vaccines cannot be recorded as
completedwithout an explicitoverrideReasonand CLINICIAN/ADMIN role. - Tenant isolation: only records belonging to the current tenant are accessible.
State machine:
FHIR mapping: Immunization resource; status maps as completed → completed, not-done → not-done, entered-in-error → entered-in-error.
1.2 ImmunizationForecast
Represents the computed vaccination schedule for a patient — which antigens are due, overdue, or complete.
ID prefix: fcst_
Invariants:
- Forecast is always patient-scoped and tenant-scoped.
- Forecast is derived deterministically from the EPI schedule and the patient's existing
ImmunizationRecordset. - A forecast must be refreshed whenever a new
ImmunizationRecordis created or corrected for the patient. - Contraindications suppress forecast recommendations for affected antigens.
FHIR mapping: ImmunizationRecommendation resource with one recommendation entry per antigen series.
2. Entities
| Entity | Description | ID prefix |
|---|---|---|
ImmunizationRecord | Aggregate root; single dose event | imm_ |
ImmunizationForecast | Computed due-date set per patient | fcst_ |
EpiScheduleEntry | Antigen series definition (read-only from EPI config) | n/a (config) |
ContraindicationRecord | Patient-level contraindication for a vaccine/antigen | cind_ |
RegistrySyncJob | Tracks outbound sync attempt to national registry | rsj_ |
3. Value Objects
| Value Object | Fields | Notes |
|---|---|---|
VaccineCode | system, code, display | CVX code system preferred; EPI code as fallback |
DoseQuantity | value, unit | UCUM units (e.g., mL) |
ImmunizationSite | system, code | SNOMED body site |
ImmunizationRoute | system, code | SNOMED route of administration |
LotNumber | value, expiryDate? | String; expiry optional |
Performer | actorId, actorType, role | Clinician who administered |
ForecastRecommendation | vaccineCode, doseNumber, seriesDoses, dueDate, earliestDate, latestDate, forecastStatus | Per-antigen entry |
ContraindicationReason | code, display, source | SNOMED or local code |
4. Domain Events
| Event | Trigger | Key payload fields |
|---|---|---|
IMMUNIZATIONS.immunization.recorded | Dose administered and saved | immunizationId, patientId, vaccineCode, doseNumber, administeredAt, performerId |
IMMUNIZATIONS.immunization.refused | Patient refused vaccine | immunizationId, patientId, vaccineCode, refusalReason, recordedAt |
IMMUNIZATIONS.immunization.updated | Lot/site/route amended | immunizationId, patientId, changedFields, updatedAt |
IMMUNIZATIONS.immunization.reported | Historical record imported | immunizationId, patientId, source, vaccineCode |
IMMUNIZATIONS.forecast.updated | Forecast recalculated for patient | forecastId, patientId, recommendations[], calculatedAt |
5. Consumed Events
| Event | Source service | Purpose |
|---|---|---|
REGISTRATION.patient.registered | registration-service | Seed forecast on first registration |
REGISTRATION.patient.merged | registration-service | Merge immunization histories to surviving patient |
REGISTRATION.patient.vital-status-changed | registration-service | Suppress outreach for deceased patients |
SCHEDULING.appointment.fulfilled | scheduling-service | Trigger immunization recording workflow |
6. Ubiquitous Language
| Term | Definition |
|---|---|
| EPI schedule | Afghanistan Expanded Programme on Immunization national vaccination schedule defining antigen series, dose intervals, and age windows |
| Forecast | Computed set of due dates for remaining doses across all antigen series for one patient |
| Defaulter | Patient who has missed one or more due vaccine doses beyond the latestDate grace window |
| Contraindication | Clinical reason a specific antigen is contraindicated for a patient; suppresses forecast recommendation |
| Antigen series | A named sequence of vaccine doses protecting against a single disease (e.g., Polio OPV series) |
| Dose number | Ordinal position within an antigen series (1-indexed) |
| Lot number | Batch identifier for a physical vaccine vial |
| Registry sync | Bidirectional exchange with the national immunization registry via interop-service |
| Coverage | Population-level metric: proportion of eligible patients who have completed a vaccine series |
| Historical record | Immunization administered outside the platform, imported for forecasting continuity |