Ir al contenido

Mock Data

Local development boots into a fully populated database from two Django fixtures, loaded with manage.py loaddata. There are no seed_* management commands — they were removed in favour of native fixtures.

[!info] Authority Mock-data scope (what is allowed where) lives in [[adr-022-mock-data-scope|ADR-022]]. This page is the operational workflow.

Location: backend/fixtures/. Format: Django’s native serialized YAML (dumpdata --format=yaml). Chosen over per-app fixtures/ dirs so the whole dataset lives in one obvious place and the two files load in a fixed, explicit order.

FileContentsRecords
mock_clinic.yamlEverything except employees: mock users, org units, positions, tag catalog, position tags90
mock_employees.yamlOnly employee-scoped data: employees + their tags, assignments, transition logs, tag-change logs266

Per-model breakdown:

ModelFixtureCount
users.User (5 mock users, no superuser)mock_clinic5
demand.OrgUnitmock_clinic25
demand.Positionmock_clinic14
tags.TagCatalogmock_clinic23
tags.PositionTagmock_clinic23
api.Employeemock_employees35
tags.EmployeeTagmock_employees90
assignments.Assignmentmock_employees18
fsm.EmployeeTransitionLogmock_employees33
tags.TagChangeLogmock_employees90

On every boot, backend/entrypoint.sh step [3/6] runs (local settings only):

Ventana de terminal
python manage.py loaddata fixtures/mock_clinic.yaml
python manage.py loaddata fixtures/mock_employees.yaml

To load manually on a fresh instance, run the same two commands inside the container in that order.

mock_clinic.yaml loads first because every employee-scoped row in mock_employees.yaml has a foreign key into it:

  • EmployeeTag / TagChangeLogTagCatalog, User
  • AssignmentPosition
  • EmployeeTransitionLogUser (actor)

Within mock_employees.yaml, Employee is serialized before the rows that reference it. The superuser is excluded from the fixtures — it is created separately by create_superuser ([[admin|Admin]]) and is never referenced as a FK target by mock data.

[!important] TagChangeLog and the raw guard TagChangeLog rows are audit records normally auto-created by a post_save signal on EmployeeTag ([[adr-019-tag-based-requirements|ADR-019]] §11). The signal in apps/tags/signals.py now skips when raw=True, which is the flag Django sets during loaddata. This makes loading idempotent: the 90 TagChangeLog rows come straight from the fixture, and re-running loaddata (e.g. on container restart) does not duplicate them.

Fixtures carry explicit UUID primary keys, so loaddata upserts by PK. Re-running it on a populated DB overwrites rows with identical data — no duplicates, no growth. The entrypoint can therefore re-load on every restart safely.

When you change the dataset (add an employee, a tag, etc.), regenerate from a live DB:

Ventana de terminal
# 1. Boot a clean, fully-loaded DB
docker compose down -v && docker compose up -d
# 2. (apply your edits via the admin/API/shell so they land in the DB)
# 3. Dump back into the two files, respecting the split
docker compose exec api python manage.py dumpdata --format=yaml --indent 2 \
users.User --pks=<comma-separated mock-user PKs> \
> backend/fixtures/_users.part
docker compose exec api python manage.py dumpdata --format=yaml --indent 2 \
demand.OrgUnit demand.Position tags.TagCatalog tags.PositionTag \
> backend/fixtures/_rest.part
cat backend/fixtures/_users.part backend/fixtures/_rest.part > backend/fixtures/mock_clinic.yaml
rm backend/fixtures/_users.part backend/fixtures/_rest.part
docker compose exec api python manage.py dumpdata --format=yaml --indent 2 \
api.Employee tags.EmployeeTag assignments.Assignment fsm.EmployeeTransitionLog tags.TagChangeLog \
> backend/fixtures/mock_employees.yaml

[!note] Exclude the superuser Dump users.User with --pks= limited to the 5 mock users (is_superuser=False). Get them with: python manage.py shell -c "from apps.users.models import User; print(','.join(str(p) for p in User.objects.filter(is_superuser=False).values_list('id', flat=True)))"

Verify a clean boot loads purely from the fixtures:

Ventana de terminal
docker compose down -v && docker compose up -d
docker compose logs api | grep "Installed" # → 90 + 266 objects

The frontend showcase has its own, separate mock dataset at frontend/src/app/shared/mocks/clinic-bienestar.json (the showcase SSOT per [[adr-022-mock-data-scope|ADR-022]]). It is consumed directly by /showcase components without the API and is not generated from, nor coupled to, these backend fixtures. The two share the Clínica Bienestar scenario and aligned deterministic UUIDs, but each is maintained independently. Do not delete or regenerate one from the other.