Backend

Backend design, models, APIs and resolution engine for Missing Details.

👤 Rucha Mahesh Kulkarni📅 Updated: Mar 16, 2026📁 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:

Core backend responsibilities

ConcernBackend responsibility
Source of truthPersist templates, lab configs, runtime missing rows, entity creation traces
Auto-resolutionCompare stored placeholder vs actual incoming value
Scope enforcementLab/org restrictions on list endpoints
Flag propagationAttach has_missing_fields to report/patient/bill payloads
Bootstrap entitiesQueue or create domain entities for entity-backed defaults
Activity loggingRecord queueing, success, failure, and creation traces

Runtime engine & resolution

Auto-resolution flow:

  1. Find unresolved LabMissingDetails rows for the patient/bill context.
  2. Map the missing field into a lookup key via MISSING_FIELDS_MODEL_FIELD_MAPPER.
  3. Check if that key exists in values_map.
  4. Compare the incoming actual value with the stored placeholder value.
  5. If the values differ, mark the row resolved and set resolved_at and 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

MethodEndpointPurpose
GET/api-v3/registration/patients/missing-details-templatesFetch master templates
GET/api-v3/registration/patients/lab-missing-details-configFetch active lab configs
POST/api-v3/registration/patients/lab-missing-details-configCreate/update/disable configs
GET/api-v3/account/missing-details/lab-fieldsFetch runtime missing-detail rows
PATCH/api-v3/account/missing-details/lab-fieldsMark 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:

  1. PY-3 local creation: LabMissingDetailsConfiguration.process_field(...) may create insurance/group entities locally and logs via ActivityLog.
  2. Legacy PY-2 webhook: PY-3 queues a Fusion webhook; PY-2 controller executes creation and MissingFieldsActivityLogger writes ActivityLog and MissingDetailsEntityCreation.

Key backend locations & helpers

AreaFunction / classPathRole
PY-3 config APILabMissingDetailsConfigViewmissing_details_view.pyRead/write active lab config
PY-3 config modelLabMissingDetailsConfigurationlab_missing_details_configuration.pyConfig persistence and entity bootstrap
PY-3 runtime enginecreate_or_update_missing_details_entriesutils.pyCreate/resolve runtime rows
PY-3 value mapperbuild_value_mapperutils.pyFlatten patient data into comparable strings
PY-3 mapper contractMISSING_FIELDS_MODEL_FIELD_MAPPERconstants.pyBridge between template names and object fields
PY-3 list/patch APILabMissingDetailsViewlab_missing_details_view.pyMissing detail listing and resolution
Legacy entity endpointmissing_field_controllerregistration/api.pyDispatch entity creation to the right py2 controller
Legacy activity loggerMissingFieldsActivityLoggerutils.pyLog 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.

Activity log - entity creation

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;

On this page