Backend
Backend design, models, APIs and resolution engine for Missing Details.
Backend
Architecture Overview
Missing Details spans livehealth-frontend, crelio-app (PY-3), and legacy livehealthapp (PY-2). Config management and list/patch APIs are in PY-3; some entity creation and legacy flows still run through PY-2 controllers.
System Design Diagram
Storage & Models
Primary tables:
-- MissingDetailsTemplates — master template catalog.
-- LabMissingDetailsConfiguration — per-lab active config rows (soft-disable semantics).
-- LabMissingDetails — runtime missing-detail incidents (is_resolved flag, placeholder value).
-- MissingDetailsEntityCreation — trace rows for entity creation caused by config save.
Key model locations:
missing_details_templates.pylab_missing_details_configuration.pylab_missing_details.py- legacy mirrors in
livehealthapp/labs/models.py
Core backend responsibilities
| Concern | Backend responsibility |
|---|---|
| Source of truth | Persist templates, lab configs, runtime missing rows, entity creation traces |
| Auto-resolution | Compare stored placeholder vs actual incoming value |
| Scope enforcement | Lab/org restrictions on list endpoints |
| Flag propagation | Attach has_missing_fields to report/patient/bill payloads |
| Bootstrap entities | Queue or create domain entities for entity-backed defaults |
| Activity logging | Record queueing, success, failure, and creation traces |
Runtime engine & resolution
Auto-resolution flow:
- Find unresolved
LabMissingDetailsrows for the patient/bill context. - Map the missing field into a lookup key via
MISSING_FIELDS_MODEL_FIELD_MAPPER. - Check if that key exists in
values_map. - Compare the incoming actual value with the stored placeholder value.
- If the values differ, mark the row resolved and set
resolved_atand resolver identity where available.
Important helpers:
build_value_mapper(...)— flattens saved objects into comparable strings.create_or_update_missing_details_entries(...)— main create/resolve engine.MISSING_FIELDS_MODEL_FIELD_MAPPER— maps template names to object fields for resolution.
Important Missing Details Snippets (Backend)
These examples show the core backend resolution and manual-resolve patterns.
Auto-resolution loop (PY-3)
Source: utils.py
for field_id, config in config_map.items():
existing = existing_map.get(field_id)
if not existing:
continue
search_key = lookup_key(
getattr(existing.field, "module", ""),
getattr(existing.field, "name", ""),
)
if not search_key or search_key not in values_map:
continue
actual_value = values_map.get(search_key)
if actual_value == existing.field_value:
continue
existing.is_resolved = True
existing.resolved_at = now
existing.resolved_by_doctor_id = doctor_id or None
existing.resolved_by_lab_user_id = lab_user_id or None
to_update.append(existing)Why it matters: maps template → object key, compares incoming value vs placeholder, and marks rows resolved when they differ.
Manual resolution (PATCH → model)
Source: lab_missing_details_view.py and lab_missing_details.py
# View layer
updated_count = LabMissingDetails.resolve(
ids=ids,
lab_id=lab_id,
resolved=is_resolved,
actor="doctor" if request.session.get("is_doctor", None) else "lab_user",
)
# Model layer
@classmethod
def resolve(cls, *, ids: list[int], lab_id: int, resolved: bool, actor=None) -> int:
qs = cls.objects.filter(id__in=ids, lab_id=lab_id)
now = timezone.now()
update_data = {"is_resolved": resolved, "updated_at": now}
if resolved:
update_data["resolved_at"] = now
else:
update_data["resolved_at"] = None
update_data["resolved_by_doctor"] = None
update_data["resolved_by_lab_user"] = None
with transaction.atomic():
return qs.update(**update_data)Why it matters: bulk resolution with lab-scope enforcement and consistent audit fields.
APIs
| Method | Endpoint | Purpose |
|---|---|---|
GET | /api-v3/registration/patients/missing-details-templates | Fetch master templates |
GET | /api-v3/registration/patients/lab-missing-details-config | Fetch active lab configs |
POST | /api-v3/registration/patients/lab-missing-details-config | Create/update/disable configs |
GET | /api-v3/account/missing-details/lab-fields | Fetch runtime missing-detail rows |
PATCH | /api-v3/account/missing-details/lab-fields | Mark rows resolved/unresolved |
Runtime capture piggybacks on:
POST /api-v3/registration/patients/new— patient create/update path.POST /api-v3/finance/bill/{labBillId}/update— billing update path.
Entity creation and logging
Two tracks:
- PY-3 local creation:
LabMissingDetailsConfiguration.process_field(...)may create insurance/group entities locally and logs viaActivityLog. - Legacy PY-2 webhook: PY-3 queues a Fusion webhook; PY-2 controller executes creation and
MissingFieldsActivityLoggerwritesActivityLogandMissingDetailsEntityCreation.
Key backend locations & helpers
| Area | Function / class | Path | Role |
|---|---|---|---|
| PY-3 config API | LabMissingDetailsConfigView | missing_details_view.py | Read/write active lab config |
| PY-3 config model | LabMissingDetailsConfiguration | lab_missing_details_configuration.py | Config persistence and entity bootstrap |
| PY-3 runtime engine | create_or_update_missing_details_entries | utils.py | Create/resolve runtime rows |
| PY-3 value mapper | build_value_mapper | utils.py | Flatten patient data into comparable strings |
| PY-3 mapper contract | MISSING_FIELDS_MODEL_FIELD_MAPPER | constants.py | Bridge between template names and object fields |
| PY-3 list/patch API | LabMissingDetailsView | lab_missing_details_view.py | Missing detail listing and resolution |
| Legacy entity endpoint | missing_field_controller | registration/api.py | Dispatch entity creation to the right py2 controller |
| Legacy activity logger | MissingFieldsActivityLogger | utils.py | Log entity creation success/failure and create MissingDetailsEntityCreation |
Example: Activity log for entity creation
This screenshot shows an activity log entry validating entity creation triggered by a Missing Details configuration.
Safe SQL / Debugging Cheatsheet
-- Active configs for a lab
SELECT id, field_name, field_value, field_module, field_category, is_disabled
FROM LabMissingDetailsConfiguration
WHERE lab_id = ? AND is_disabled = 0
ORDER BY field_name;-- Runtime unresolved missing details for a patient
SELECT id, field_name, field_value, field_module, is_resolved, created_at, resolved_at
FROM LabMissingDetails
WHERE lab_id = ? AND user_details_id = ? AND is_resolved = 0
ORDER BY created_at DESC;-- Entity creation traces caused by config save
SELECT id, config_id, entity_name, object_id, lab_id, org_id, created_at
FROM MissingDetailsEntityCreation
WHERE lab_id = ?
ORDER BY created_at DESC;