Skip to content

System Configuration

This guide explains every setting in the System Configuration panel and how each one affects rota generation.


Overview

System Configuration is a single record that stores all global settings for the rota management system. There is only one configuration entry -- if none exists, the system creates one with default values the first time it is needed.

You can find it in the Django admin at Config > System Configuration. Because it is a singleton, you will see at most one entry. Click it to open the edit form. The system prevents you from creating additional entries or deleting the existing one.

Changes to configuration are audited automatically. The system records which fields changed, the old and new values, and who made the change.


Settings Reference

The table below lists every setting, what it controls, its default value, and guidance on when to change it.

Core Working Parameters

Setting What It Controls Default When to Change
target_working_days_per_week The number of working days per week that counts as full-time equivalent (FTE). Used to calculate each clinician's target shift allocation based on their WTE percentage. 3.50 Change if your practice defines full-time differently. A higher value means clinicians are expected to work more days per week at full WTE. A lower value means fewer days. Must be between 0.01 and 7.00.

Minimum Staffing

Setting What It Controls Default When to Change
minimum_doctors A JSON dictionary specifying the minimum number of doctors required for each day of the week. Keys are Monday, Tuesday, Wednesday, Thursday, Friday. The rota generator fills gaps until these minimums are met. {"Monday": 9, "Tuesday": 7, "Wednesday": 8, "Thursday": 6, "Friday": 6} Change to match your practice's staffing policy. Higher values mean more doctors must be on shift each day. Mondays typically need the most cover. Each value must be a positive integer.

Minimum Staffing Rules (time-limited overrides)

On top of the base minimums, the dashboard's Minimum Staffing Rules page (on the Settings & Tools page, under Setup in the sidebar) manages rules that override a day's minimum when specific conditions hold — for example lifting Wednesdays from 7 to 8 whenever two named partners are both working, or covering a seasonal period when the practice runs bigger clinics.

A rule fires on a date when it is enabled, the date is inside its start/end window (blank starts immediately; blank ends never end), the weekday matches (a rule naming no days matches every weekday), and every named clinician is working that day (a rule naming no clinicians ignores this). When several rules fire on the same day, the highest minimum wins. A firing rule replaces the day's configured base — it can lower a minimum as well as raise it.

On the rules page you can toggle a rule on or off and edit its dates; the rule's weekdays, clinicians, and minimum are set when the rule is created (in Django admin or code). Disabled rules are ignored by every minimum staffing calculation — leave capacity, staffing validation, and alerts alike.

Holiday Periods (practice closures)

The Holiday Periods page (admin navigation) defines date ranges when the practice is closed — typically one per year for the Christmas and New Year shutdown, but any closure can be recorded. During a holiday period:

  • Leave requests covering those dates are blocked (the leave validator enforces it).
  • The leave booking calendar shows the days as "Closed" instead of the normal capacity colours.

Each period has a name (for example "Christmas 2026"), a start date, and an end date. You can add, edit, and delete periods from the page; every change is recorded in the audit trail, and deleting a period immediately lets clinicians request leave across those dates again. This replaced the old fixed Christmas-period settings, which could only ever describe one date range.

Leave Booking Cutoff

Setting What It Controls Default When to Change
leave_booking_cutoff The date beyond which clinicians cannot book normal leave (annual leave, days not working, planned sick). Study leave and coroners court are unrestricted. Administrators can always book on a clinician's behalf. None (blank) Set it while an Annual Leave Round is being planned, so next year's leave is not booked first-come-first-served before the round settles. Clear it once the round is locked — the round page reminds you while it still blocks the year. While in force, the booking calendar shows affected days as "Awaiting Release".

Duty Doctor Configuration

Setting What It Controls Default When to Change
duty_doctors_required The number of duty doctors assigned on a normal working day. Phase 6 (Add Duty Doctors) uses this to determine how many duty slots to create each day. 1 Increase if your practice requires more than one duty doctor on regular days. Must be at least 1.
duty_doctors_post_bank_holiday The number of duty doctors assigned on the first working day after a bank holiday. This is typically higher because of increased patient demand. 2 Increase if post-bank-holiday days need extra duty cover in your practice. Must be at least 1.
post_bank_holiday_minimum When a day is the first working day after a bank holiday, the system uses the minimum staffing level from this day of the week instead of the day's own minimum. This lets you apply a higher minimum (typically Monday's) to post-bank-holiday days. Monday Change if you want post-bank-holiday staffing based on a different day's minimum. Must be a valid day name (Monday through Sunday).

Fixed Period

Setting What It Controls Default When to Change
fixed_period_weeks The number of weeks from the current date that are protected from automatic changes. Shifts within this fixed period are not overwritten by automatic generation or rebalancing. This gives clinicians stability in their near-term schedule. 6 Increase to give clinicians more advance certainty. Decrease if you need the system to be able to adjust shifts closer to the current date. Must be at least 1.
current_date The reference date used to calculate the fixed period boundary. If blank, the system uses today's actual date. This field is mainly used for testing or for freezing the rota at a specific point in time. None (blank) Leave blank for normal operation. Set a date only if you need to simulate a different "today" for fixed period calculations.

Reporting Periods

Setting What It Controls Default When to Change
reporting_periods A JSON list of reporting period configurations. Each period has a name, start_date, end_date, and annual_leave_percentage_required. These periods are used to calculate clinician targets and leave entitlement across the year. Two six-month periods (January-June and July-December) Update at the start of each new year to set the correct date ranges for your reporting periods. Each period's dates should cover the full year without gaps.

UK Bank Holidays

Setting What It Controls Default When to Change
uk_nation Determines which set of UK bank holidays the system recognises. Different nations have different bank holiday dates (for example Scotland does not have an Easter Monday bank holiday). england Set to your practice's nation. Valid values are england, scotland, wales, and northern_ireland. Warning: This cannot be changed after any shifts have been generated, to prevent historical inconsistencies.

Christmas and New Year Restrictions

The Christmas period defines a restricted date range during which clinicians cannot request leave. The leave validator blocks any leave request that includes dates within this period.

Setting What It Controls Default When to Change
christmas_period_start_month The month number when the restricted Christmas period begins. 12 (December) Change if your practice's restricted period starts in a different month. Must be 1-12.
christmas_period_start_day The day of month when the restricted Christmas period begins. 24 (24 December) Adjust if your practice defines a different start date. Must be 1-31.
christmas_period_end_month The month number when the restricted Christmas period ends. 1 (January) Change if your practice's restricted period ends in a different month. Must be 1-12.
christmas_period_end_day The day of month when the restricted Christmas period ends. 2 (2 January) Adjust if your practice defines a different end date. Must be 1-31.

The default restricted period is 24 December to 2 January. The system correctly handles the year boundary when the period spans December into January.

WTE Balance Weights (Phase 5)

These settings control how the Phase 5 optimiser prioritises fairness when arranging partner shifts. The two weights must always sum to 1.0.

Setting What It Controls Default When to Change
enable_wte_balance Master toggle for the WTE balance optimisation phase. When disabled, Phase 5 is skipped entirely. True (enabled) Disable only if you want to skip WTE balancing and rely on other phases alone. Most practices should leave this enabled.
wte_balance_deficit_weight How much the optimiser prioritises reducing individual clinician deficits (the gap between shifts worked and target). A higher value means the system focuses more on closing the gap for clinicians who are furthest behind. 0.6 Increase to prioritise closing individual deficits. Must be between 0 and 1.
wte_balance_day_distribution_weight How much the optimiser prioritises balancing shifts evenly across days of the week. A higher value means the system focuses more on making sure no single day is overloaded or underloaded relative to others. 0.4 Increase to prioritise even day-of-week distribution. Must be between 0 and 1.

The two weights must sum to 1.0 (the system allows a tolerance of 0.01). For example, if you increase the deficit weight to 0.7, you must set the day distribution weight to 0.3.

Optimisation Settings

Setting What It Controls Default When to Change
optimization_iterations The number of randomised iterations the optimiser runs during generation. More iterations increase the chance of finding a better solution but take longer. 10 Increase for larger rotas or when you need better optimality (for example to 20 or 50). Decrease for faster generation on smaller rotas. Must be at least 1.

AI Agent API

These settings gate the AI Agent API (the interface an external AI assistant can use to read and propose changes to rota data). If you do not use the AI integration, leave them alone.

Setting What It Controls Default When to Change
ai_api_enabled Master toggle for the AI Agent API. When off, all AI endpoints refuse requests. False Enable only when integrating an AI assistant.
ai_api_approval_mode When on, AI-proposed changes are staged as transactions and wait for a human to approve them on the AI Approvals page before being applied. True Keep on unless you fully trust the integration.
ai_api_approval_timeout_minutes How long a proposed AI transaction waits for approval before being auto-rejected. 60 Raise if approvals are not reviewed within the hour.

Shift Notifications

Setting What It Controls Default When to Change
enable_shift_notifications Master toggle for email notifications about shift changes. When disabled, no emails are sent when shifts are created, modified, or deleted. True (enabled) Disable during initial data import or bulk generation to avoid sending a flood of emails to clinicians. Re-enable once normal operation resumes.
shift_notification_batch_mode When enabled, shift change notifications are queued instead of sent immediately. An admin can then review, consolidate, and send them as a batch, or discard them. False Enable before running bulk generation or major rota changes. Disable and send the batch when you are done.
batch_mode_enabled_at Records when batch mode was last activated. Set automatically by the system. None Do not edit manually.
batch_mode_enabled_by Records which user last activated batch mode. Set automatically by the system. None (blank) Do not edit manually.

How to Access System Configuration

Most configuration lives in the Django admin:

  1. Log in to the Django admin interface (typically at /django-admin/; from the site's sidebar use System Admin).
  2. Under the Config section, click System Configuration.
  3. Click the existing configuration entry to open the edit form.
  4. Modify the settings you need to change.
  5. Click Save to apply changes.

Two settings are also editable from the dashboard itself, without going to Django admin — both live on the Settings & Tools page (Setup → Settings & Tools in the sidebar):

  • The Settings page (/admin/settings/) sets and clears the Leave Booking Cutoff — the one you will touch most often around a leave round.
  • The Minimum Staffing Rules page manages the time-limited minimum overrides described above.

All changes are validated before saving. If a value is invalid (for example a weight outside 0-1, or a missing day in minimum_doctors), the system will show a validation error and the change will not be saved.


Important Warnings

Changes take effect on the next rota generation

Most configuration changes do not immediately alter existing shifts. They affect the next time you run a generation phase. The exception is uk_nation, which affects bank holiday detection used across the system.

The UK nation setting is locked after generation

Once any shifts exist in the system, the uk_nation setting cannot be changed. This prevents inconsistencies where historical shifts were generated against one nation's bank holidays but later calculations use a different nation's dates. If you need to change nation, you would need to clear all shifts first.

WTE balance weights must sum to 1.0

The deficit weight and day distribution weight are not independent. They must always add up to 1.0. The system will reject a save if the weights do not sum correctly.

Minimum doctors values affect Phase 3

The minimum_doctors dictionary directly controls how many shifts Phase 3 (Fill to Minimum) creates. Setting these values too high for your workforce will result in unfilled days and alerts. Setting them too low may leave your practice understaffed.

Christmas period affects leave requests

The Christmas period settings are enforced by the leave validator. Any leave request that includes dates within the configured restricted period will be rejected automatically. Make sure the date range matches your practice policy.

Shift notifications can generate a lot of email

If enable_shift_notifications is on and shift_notification_batch_mode is off, every shift change triggers an individual email. Before running bulk operations, consider enabling batch mode to queue notifications for review.

Rota generation is guarded against this (issue #178): if a rota generation step (any phase task in the admin dashboard, or manage.py generate_rota) is started with a start date inside the notification window (the 6-week visibility boundary) while notifications are on and batch mode is off, the step fails immediately with an error explaining how to proceed -- enable batch mode, pick a later start date, or disable shift notifications. No shifts are changed by a refused run.

Running the batch-mode workflow

The batch-mode cycle is done from the dashboard, not Django admin:

  1. On the admin Overview page, find the Shift Notification Batch Mode panel and press Start Batch Mode. An amber banner appears site-wide while batch mode is active.
  2. Run your generation phases or bulk changes. Each shift change queues a notification instead of emailing immediately.
  3. Open the banner's review link (the Batch Mode Active card on the Overview also leads there). The review page groups everything queued by clinician — new shifts, modified shifts, deleted shifts — so you can see exactly what each person would be emailed.
  4. Press Send Batch Emails to dispatch the batch, or Discard All (Silent) to drop the queue without sending (useful after a practice-wide regeneration where clinicians would only need the final state).
  5. Turn batch mode off again.

User Access (Dashboard Admins)

The User Access page manages who can use the admin dashboard. In the navigation it sits under its own Superadmin heading, and only superusers can see the heading or open the page — a Dashboard Admin's membership is a superuser's decision, not a group decision (otherwise one Dashboard Admin could revoke another's access, including a superuser's).

Membership of the Dashboard Admins group is what grants access to /admin/ — it is a system-access group, separate from clinician groups, which control rota rules and are edited on each clinician's page.

The page lists every user account with its linked clinician, whether it is a superuser, and its Dashboard Admin state. Grant gives the user full admin dashboard access (managing shifts, leave, and clinicians across the practice); Revoke removes it without touching the account or the linked clinician record.

Guardrails apply:

  • You cannot revoke your own access — ask another superuser to do it for you.
  • The last Dashboard Admin cannot be revoked (nobody else could get back into /admin/).
  • Every grant and revoke is recorded in the audit trail, naming the acting superuser.

Audit Trail

Every configuration change is logged in the audit system. The log records:

  • Which fields changed.
  • The previous value and new value for each changed field.
  • Who made the change (their username).
  • When the change was made.

You can view configuration audit logs in the Django admin under Config > Audit Logs, filtering by entity type SystemConfiguration.