Skip to content

Models

This page documents MedUX's model conventions and key models.

Tenant-Scoped Models

Models that belong to a specific tenant should use the mixins from Conjunto:

TenantModelMixin

For models that must belong to a tenant:

from conjunto.tenants.models import TenantModelMixin

class MyModel(TenantModelMixin, models.Model):
    name = models.CharField(max_length=100)

This adds a tenant ForeignKey and scopes querysets to the current tenant automatically.

OptionalTenantModelMixin

For models that may belong to a tenant (or be global):

from conjunto.tenants.models import OptionalTenantModelMixin

class SharedResource(OptionalTenantModelMixin, models.Model):
    name = models.CharField(max_length=100)

Key Models

Patient (medux.core)

The central model for patient demographics. Includes name, date of birth, address, insurance, and contact information.

Encounter (medux.core)

Represents a clinical encounter (visit) linked to a patient. Contains encounter date, type, and associated clinical data.

Tenant (medux.common)

Represents a practice or organizational unit. Used as CONJUNTO_TENANT_MODEL = "common.Tenant".

User (medux.core)

Custom user model (AUTH_USER_MODEL = "core.User"). Extends CommonUser from medux.common.

Employee (medux.employees)

Employee record linked to a user account. Includes working contracts and scheduling information.

Model Conventions

  • Use gettext_lazy for verbose_name and verbose_name_plural
  • Use TenantModelMixin for tenant-scoped data
  • Migrations: during pre-alpha, migrations may be squashed or reset between releases
  • Use UUIDs for public-facing identifiers where appropriate

Coded values: use TextChoices

For small, fixed, code-time enumerations (observation status, device status, request priority, organization type, administrative gender, contact-point system, etc.), use django.db.models.TextChoices:

  • Inline at the call site as a models.TextChoices subclass.
  • Store as CharField(choices=…).
  • No extra table, no FK, no fixtures.
  • Translations via gettext_lazy.

Examples in core: medux.core.models.organizations.AdministrativeGender, medux.core.models.devices.DeviceStatus / DeviceStatusReason, medux.core.models.observations.ObservationStatus, medux.core.models.contact.ContactPointSystem.

Large external terminology systems (ICD-10, ICPC-2, SNOMED CT, LOINC, ATC, PZN, …) are out of scope for the core models and will be handled by dedicated plugins when needed.