> For the complete documentation index, see [llms.txt](https://docs.mymedtrics.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.mymedtrics.com/get-started/classic-data-mapping/scheduling.md).

# Scheduling

Rotations / Clinical Scheduling, Shift Schedules, Calendar & Events: 29 Medtrics Classic tables and their confirmed Oracle fields.

Rotations / Clinical Scheduling, Shift Schedules, Calendar & Events — 29 Medtrics Classic tables with 218 confirmed fields (16% of the mapping): Unchanged 29 · Renamed 99 · ID changed 90. Each table below lists where its confirmed fields went, what to change in a query, and a starter query. Back to the [map of the data](/get-started/classic-data-mapping.md).

![Scheduling: 29 Medtrics Classic tables; the number is confirmed fields, the bar is the outcome mix](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2FLeMO7Frr5iqRy1QDLCkw%2Fmap-sched.png?alt=media)

### Rotations / Clinical Scheduling

14 tables, 139 confirmed fields: Unchanged 18 · Renamed 76 · ID changed 45.

#### rotations\_academicyear

**rotations\_academicyear** → `academic_periods` · *replaced* · 2 confirmed fields (Unchanged 1 · ID changed 1)

Academic year/semester periods - foundational time structure referenced across domains.

> A single 'year' record with a mid-term date and an optional program list becomes a generic dated period with a type enum, plus a bulk-generation recipe table. The optional program list is the part that did not survive.

![Where the 2 confirmed fields of rotations\_academicyear went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2F8pnx6HBhIzgPdU0deShw%2Fflow-rotations-academicyear.png?alt=media)

| Medtrics Classic field | Oracle          | Outcome    | Note                |
| ---------------------- | --------------- | ---------- | ------------------- |
| `id` integer           | `id` UUID       | ID changed | Integer link → UUID |
| `end_date` date        | `end_date` DATE | Unchanged  |                     |

* Re-key 1 ID field. Join people on `email`, not on old IDs.
* Add `WHERE deleted_at IS NULL`: `academic_periods` keeps deleted rows.

```sql
-- Starter query: confirmed fields only. Was rotations_academicyear.
SELECT
  t.id,       -- was id
  t.end_date  -- was end_date
FROM academic_periods t
WHERE t.deleted_at IS NULL;
```

#### rotations\_block

**rotations\_block** → `block_schedules`, `rotation_block_directors` · *renamed* · 3 confirmed fields (Unchanged 2 · ID changed 1)

User schedule assignments within blocks. Split table: each field names its new table.

> Same idea (a dated slot), but the parent changed: Medtrics Classic Block belonged to a ProgramSchedule, Oracle blocks belong to an academic\_period and a block\_structure, with clinical\_schedule\_id only an optional pointer.

![Where the 3 confirmed fields of rotations\_block went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2FSa4bUT6Ak6BY3Mt7wq04%2Fflow-rotations-block.png?alt=media)

| Medtrics Classic field        | Oracle                                       | Outcome    | Note                                                |
| ----------------------------- | -------------------------------------------- | ---------- | --------------------------------------------------- |
| `program_schedule_id` integer | block\_schedules.`clinical_schedule_id` UUID | ID changed | Integer link → UUID pointing to clinical\_schedules |
| `start_date` date             | rotation\_block\_directors.`start_date` DATE | Unchanged  |                                                     |
| `end_date` date               | rotation\_block\_directors.`end_date` DATE   | Unchanged  |                                                     |

* Re-key 1 ID field. Join people on `email`, not on old IDs.
* Add `WHERE deleted_at IS NULL`: `block_schedules`, `rotation_block_directors` keep deleted rows.

#### rotations\_programschedule

**rotations\_programschedule** → `clinical_schedule_groups`, `clinical_schedule_roles`, `clinical_schedule_sites`, `clinical_schedule_users`, `clinical_schedules` · *split* · 19 confirmed fields (Unchanged 3 · Renamed 13 · ID changed 3)

Group-based access control for clinical schedules. Split table: each field names its new table.

> The per-year schedule container was split into a header, a reusable block calendar, and five access-control tables that replace the Medtrics Classic many-to-many fields.

![Where the 19 confirmed fields of rotations\_programschedule went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2FzKxmbcUM4Ylro1xWLFFC%2Fflow-rotations-programschedule.png?alt=media)

| Medtrics Classic field                    | Oracle                                         | Outcome    | Note                                              |
| ----------------------------------------- | ---------------------------------------------- | ---------- | ------------------------------------------------- |
| `id` integer                              | clinical\_schedules.`id` UUID                  | ID changed | Integer link → UUID                               |
| `academic_year_id` integer                | clinical\_schedules.`academic_period_id` UUID  | ID changed | Integer link → UUID pointing to academic\_periods |
| `program_id` integer                      | clinical\_schedules.`program_id` UUID          | ID changed | Integer link → UUID pointing to programs          |
| `less_than_week` boolean                  | clinical\_schedules.`schedule_config` JSONB    | Renamed    | bool → json (Merged, Type changed)                |
| `display_user_portal` boolean             | clinical\_schedules.`schedule_config` JSONB    | Renamed    | bool → json (Merged, Type changed)                |
| `send_email` boolean                      | clinical\_schedules.`schedule_config` JSONB    | Renamed    | bool → json (Merged, Type changed)                |
| `updated_at` timestamptz                  | clinical\_schedules.`published_at` TIMESTAMPTZ | Renamed    | (Split)                                           |
| `is_schedule_program` boolean             | clinical\_schedules.`schedule_config` JSONB    | Renamed    | bool → json (Merged, Type changed)                |
| `created_date` timestamptz                | clinical\_schedules.`created_at` TIMESTAMPTZ   | Renamed    |                                                   |
| `schedule_details` boolean                | clinical\_schedules.`schedule_config` JSONB    | Renamed    | bool → json (Merged, Type changed)                |
| `restrict_rotation_view` boolean          | clinical\_schedules.`schedule_config` JSONB    | Renamed    | bool → json (Merged, Type changed)                |
| `show_block_naming` boolean               | clinical\_schedules.`schedule_config` JSONB    | Renamed    | bool → json (Merged, Type changed)                |
| `show_rotation_tab_default` boolean       | clinical\_schedules.`schedule_config` JSONB    | Renamed    | bool → json (Merged, Type changed)                |
| `enable_rotation_block_directors` boolean | clinical\_schedules.`schedule_config` JSONB    | Renamed    | bool → json (Merged, Type changed)                |
| `show_contact_faculty` boolean            | clinical\_schedules.`schedule_config` JSONB    | Renamed    | bool → json (Merged, Type changed)                |
| `show_contact_trainee` boolean            | clinical\_schedules.`schedule_config` JSONB    | Renamed    | bool → json (Merged, Type changed)                |
| `name` varchar                            | clinical\_schedules.`name` TEXT                | Unchanged  |                                                   |
| `description` text                        | clinical\_schedules.`description` TEXT         | Unchanged  |                                                   |
| `updated_at` timestamptz                  | clinical\_schedules.`updated_at` TIMESTAMPTZ   | Unchanged  | (Split)                                           |

* Swap the 13 renamed fields and point `FROM` at `clinical_schedule_groups` (and the other new tables).
* Re-key 3 ID fields. Join people on `email`, not on old IDs.
* Add `WHERE deleted_at IS NULL`: `clinical_schedules` keeps deleted rows.

#### rotations\_programschedule\_roles

**rotations\_programschedule\_roles** → `clinical_schedule_roles` · 2 confirmed fields (ID changed 2)

Role-based access control for clinical schedules.

![Where the 2 confirmed fields of rotations\_programschedule\_roles went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2FT0xmA0eQuN8jXkx7pgfE%2Fflow-rotations-programschedule-roles.png?alt=media)

| Medtrics Classic field  | Oracle         | Outcome    | Note                                                                                                                |
| ----------------------- | -------------- | ---------- | ------------------------------------------------------------------------------------------------------------------- |
| `id` integer            | `id` UUID      | ID changed | Integer ID replaced by a new UUID. Medtrics Classic → new ID crosswalk is kept by the migration (see Keys & joins). |
| `customrole_id` integer | `role_id` UUID | ID changed | Integer link → UUID pointing to roles                                                                               |

* Re-key 2 ID fields. Join people on `email`, not on old IDs.

```sql
-- Starter query: confirmed fields only. Was rotations_programschedule_roles.
SELECT
  t.id,      -- was id
  t.role_id  -- was customrole_id
FROM clinical_schedule_roles t;
```

#### rotations\_programschedule\_sites

**rotations\_programschedule\_sites** → `clinical_schedule_sites` · 2 confirmed fields (ID changed 2)

Sites associated with clinical schedules.

![Where the 2 confirmed fields of rotations\_programschedule\_sites went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2Fkcwf3DNPHBwyzJugdJ02%2Fflow-rotations-programschedule-sites.png?alt=media)

| Medtrics Classic field         | Oracle         | Outcome    | Note                                                                                                                |
| ------------------------------ | -------------- | ---------- | ------------------------------------------------------------------------------------------------------------------- |
| `id` integer                   | `id` UUID      | ID changed | Integer ID replaced by a new UUID. Medtrics Classic → new ID crosswalk is kept by the migration (see Keys & joins). |
| `participatingsite_id` integer | `site_id` UUID | ID changed | Integer link → UUID pointing to sites                                                                               |

* Re-key 2 ID fields. Join people on `email`, not on old IDs.

```sql
-- Starter query: confirmed fields only. Was rotations_programschedule_sites.
SELECT
  t.id,      -- was id
  t.site_id  -- was participatingsite_id
FROM clinical_schedule_sites t;
```

#### rotations\_programschedule\_users

**rotations\_programschedule\_users** → `clinical_schedule_users` · 2 confirmed fields (ID changed 2)

User-level access control for clinical schedules.

![Where the 2 confirmed fields of rotations\_programschedule\_users went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2FFu97yY0MzarNgEEWDKvF%2Fflow-rotations-programschedule-users.png?alt=media)

| Medtrics Classic field | Oracle         | Outcome    | Note                                                                                                                |
| ---------------------- | -------------- | ---------- | ------------------------------------------------------------------------------------------------------------------- |
| `id` integer           | `id` UUID      | ID changed | Integer ID replaced by a new UUID. Medtrics Classic → new ID crosswalk is kept by the migration (see Keys & joins). |
| `user_id` integer      | `user_id` UUID | ID changed | Integer link → UUID pointing to profiles                                                                            |

* Re-key 2 ID fields. Join people on `email`, not on old IDs.

```sql
-- Starter query: confirmed fields only. Was rotations_programschedule_users.
SELECT
  t.id,      -- was id
  t.user_id  -- was user_id
FROM clinical_schedule_users t;
```

#### rotations\_programschedule\_view\_access\_to\_roles

**rotations\_programschedule\_view\_access\_to\_roles** → `clinical_schedule_roles` · 2 confirmed fields (ID changed 2)

Role-based access control for clinical schedules.

![Where the 2 confirmed fields of rotations\_programschedule\_view\_access\_to\_roles went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2FcubzkWa5a8zztLfi21l5%2Fflow-rotations-programschedule-view-access-to-roles.png?alt=media)

| Medtrics Classic field  | Oracle         | Outcome    | Note                                                                                                                |
| ----------------------- | -------------- | ---------- | ------------------------------------------------------------------------------------------------------------------- |
| `id` integer            | `id` UUID      | ID changed | Integer ID replaced by a new UUID. Medtrics Classic → new ID crosswalk is kept by the migration (see Keys & joins). |
| `customrole_id` integer | `role_id` UUID | ID changed | Integer link → UUID pointing to roles                                                                               |

* Re-key 2 ID fields. Join people on `email`, not on old IDs.

```sql
-- Starter query: confirmed fields only. Was rotations_programschedule_view_access_to_roles.
SELECT
  t.id,      -- was id
  t.role_id  -- was customrole_id
FROM clinical_schedule_roles t;
```

#### rotations\_programschedule\_view\_access\_to\_users

**rotations\_programschedule\_view\_access\_to\_users** → `clinical_schedule_users` · 2 confirmed fields (ID changed 2)

User-level access control for clinical schedules.

![Where the 2 confirmed fields of rotations\_programschedule\_view\_access\_to\_users went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2FIzHjg9M2ItCuldHb9jXs%2Fflow-rotations-programschedule-view-access-to-users.png?alt=media)

| Medtrics Classic field | Oracle         | Outcome    | Note                                                                                                                |
| ---------------------- | -------------- | ---------- | ------------------------------------------------------------------------------------------------------------------- |
| `id` integer           | `id` UUID      | ID changed | Integer ID replaced by a new UUID. Medtrics Classic → new ID crosswalk is kept by the migration (see Keys & joins). |
| `user_id` integer      | `user_id` UUID | ID changed | Integer link → UUID pointing to profiles                                                                            |

* Re-key 2 ID fields. Join people on `email`, not on old IDs.

```sql
-- Starter query: confirmed fields only. Was rotations_programschedule_view_access_to_users.
SELECT
  t.id,      -- was id
  t.user_id  -- was user_id
FROM clinical_schedule_users t;
```

#### rotations\_rotation

**rotations\_rotation** → `clinical_rotation_instances`, `rotations` · *same/split* · 20 confirmed fields (Unchanged 4 · Renamed 11 · ID changed 5)

Rotation catalog: one live offering per program code at a site. GCR is optional. Optional rotation\_template\_id points at the Medtrics Classic rotations row until that table is dropped. Split table: each field names its new table.

> Same catalog of rotation definitions, but it changed domain: Medtrics Classic had it in the `rotations` app alongside scheduling; Oracle put it in 04\_curriculum while every scheduling consumer sits in 08\_clinical\_schedules.

![Where the 20 confirmed fields of rotations\_rotation went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2F3lGMqapdpOe5r2bCXCgk%2Fflow-rotations-rotation.png?alt=media)

| Medtrics Classic field                     | Oracle                                                            | Outcome    | Note                                                              |
| ------------------------------------------ | ----------------------------------------------------------------- | ---------- | ----------------------------------------------------------------- |
| `id` integer                               | rotations.`id` UUID                                               | ID changed | Integer link → UUID (Split)                                       |
| `program_id` integer                       | clinical\_rotation\_instances.`program_id` UUID                   | ID changed | Integer link → UUID pointing to programs (Split)                  |
| `program_id` integer                       | rotations.`program_id` UUID                                       | ID changed | Integer link → UUID pointing to programs (Split)                  |
| `graded_course_rotation_id` integer        | clinical\_rotation\_instances.`graded_course_rotation_id` UUID    | ID changed | Integer link → UUID pointing to graded\_course\_rotations (Split) |
| `graded_course_rotation_id` integer        | rotations.`graded_course_rotation_id` UUID                        | ID changed | Integer link → UUID pointing to graded\_course\_rotations (Split) |
| `id` integer                               | clinical\_rotation\_instances.`display_order` INTEGER             | Renamed    | (Split)                                                           |
| `id` integer                               | rotations.`code` TEXT                                             | Renamed    | int → text (Split, Merged, Type changed)                          |
| `id` integer                               | rotations.`display_order` INTEGER                                 | Renamed    | (Split)                                                           |
| `codename` varchar                         | clinical\_rotation\_instances.`code` TEXT                         | Renamed    | (Split)                                                           |
| `codename` varchar                         | rotations.`code` TEXT                                             | Renamed    | (Split, Merged)                                                   |
| `active` boolean                           | clinical\_rotation\_instances.`is_active` BOOLEAN                 | Renamed    | (Split)                                                           |
| `active` boolean                           | rotations.`is_active` BOOLEAN                                     | Renamed    | (Split)                                                           |
| `log_case_reminder_days` integer           | clinical\_rotation\_instances.`case_reminder_days` INTEGER        | Renamed    |                                                                   |
| `log_case_reminder_enabled` boolean        | clinical\_rotation\_instances.`case_reminder_enabled` BOOLEAN     | Renamed    |                                                                   |
| `allow_swap_rotation` boolean              | clinical\_rotation\_instances.`allow_swap` BOOLEAN                | Renamed    |                                                                   |
| `require_document_upload_for_swap` boolean | clinical\_rotation\_instances.`require_document_for_swap` BOOLEAN | Renamed    |                                                                   |
| `name` varchar                             | clinical\_rotation\_instances.`name` TEXT                         | Unchanged  | (Split)                                                           |
| `name` varchar                             | rotations.`name` TEXT                                             | Unchanged  | (Split)                                                           |
| `description` text                         | rotations.`description` TEXT                                      | Unchanged  |                                                                   |
| `excused_from_events` boolean              | clinical\_rotation\_instances.`excused_from_events` BOOLEAN       | Unchanged  |                                                                   |

* Swap the 11 renamed fields and point `FROM` at `clinical_rotation_instances` (and the other new tables).
* Re-key 5 ID fields. Join people on `email`, not on old IDs.
* Add `WHERE deleted_at IS NULL`: `clinical_rotation_instances`, `rotations` keep deleted rows.

#### rotations\_rotationsite

**rotations\_rotationsite** → `clinical_rotation_instances`, `rotation_sites` · *split* · 8 confirmed fields (Renamed 2 · ID changed 6)

Rotation catalog: one live offering per program code at a site. GCR is optional. Optional rotation\_template\_id points at the Medtrics Classic rotations row until that table is dropped. Split table: each field names its new table.

> The Medtrics Classic rotation-to-site join survives almost unchanged as rotation\_sites (same funding columns, renamed gme to gme\_percentage and irfdpu to irf\_dppu), but clinical\_rotation\_instances now says the same thing a second time off a different parent.

![Where the 8 confirmed fields of rotations\_rotationsite went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2FlWHi7TDzwBV7lOXYAB1r%2Fflow-rotations-rotationsite.png?alt=media)

| Medtrics Classic field | Oracle                                                    | Outcome    | Note                                              |
| ---------------------- | --------------------------------------------------------- | ---------- | ------------------------------------------------- |
| `id` integer           | clinical\_rotation\_instances.`id` UUID                   | ID changed | Integer link → UUID (Split)                       |
| `id` integer           | rotation\_sites.`id` UUID                                 | ID changed | Integer link → UUID (Split)                       |
| `rotation_id` integer  | clinical\_rotation\_instances.`rotation_template_id` UUID | ID changed | Integer link → UUID pointing to rotations (Split) |
| `rotation_id` integer  | rotation\_sites.`rotation_id` UUID                        | ID changed | Integer link → UUID pointing to rotations (Split) |
| `site_id` integer      | clinical\_rotation\_instances.`site_id` UUID              | ID changed | Integer link → UUID pointing to sites (Split)     |
| `site_id` integer      | rotation\_sites.`site_id` UUID                            | ID changed | Integer link → UUID pointing to sites (Split)     |
| `gme` integer          | rotation\_sites.`gme_percentage` INTEGER                  | Renamed    |                                                   |
| `ime` integer          | rotation\_sites.`ime_percentage` INTEGER                  | Renamed    |                                                   |

* Swap the 2 renamed fields and point `FROM` at `clinical_rotation_instances` (and the other new tables).
* Re-key 6 ID fields. Join people on `email`, not on old IDs.
* Add `WHERE deleted_at IS NULL`: `clinical_rotation_instances`, `rotation_sites` keep deleted rows.

#### rotations\_schedulerequestattachment

**rotations\_schedulerequestattachment** → `schedule_change_request_attachments` · *merged* · 5 confirmed fields (Renamed 3 · ID changed 2)

Supporting documents for schedule change requests.

> Three request tables plus the separate swap flows became one. The structured 'propose a brand new site and preceptor' fields did not survive as columns.

![Where the 5 confirmed fields of rotations\_schedulerequestattachment went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2Fn001bUTgIBWAI5rFIOe6%2Fflow-rotations-schedulerequestattachment.png?alt=media)

| Medtrics Classic field        | Oracle                   | Outcome    | Note                                                       |
| ----------------------------- | ------------------------ | ---------- | ---------------------------------------------------------- |
| `id` integer                  | `id` UUID                | ID changed | Integer link → UUID                                        |
| `schedule_request_id` integer | `request_id` UUID        | ID changed | Integer link → UUID pointing to schedule\_change\_requests |
| `file_attachment` varchar     | `file_name` TEXT         | Renamed    | (Split)                                                    |
| `file_attachment` varchar     | `file_url` TEXT          | Renamed    | (Split)                                                    |
| `created_date` timestamptz    | `created_at` TIMESTAMPTZ | Renamed    |                                                            |

* Swap the 3 renamed fields and point `FROM` at `schedule_change_request_attachments`.
* Re-key 2 ID fields. Join people on `email`, not on old IDs.

```sql
-- Starter query: confirmed fields only. Was rotations_schedulerequestattachment.
SELECT
  t.id,         -- was id
  t.file_name,  -- was file_attachment
  t.file_url,   -- was file_attachment
  t.created_at, -- was created_date
  t.request_id  -- was schedule_request_id
FROM schedule_change_request_attachments t;
```

#### rotations\_schedulerequests

**rotations\_schedulerequests** → `schedule_change_requests` · *merged* · 24 confirmed fields (Unchanged 3 · Renamed 12 · ID changed 9)

Unified schedule change, swap, and time-off request workflow.

> Three request tables plus the separate swap flows became one. The structured 'propose a brand new site and preceptor' fields did not survive as columns.

![Where the 24 confirmed fields of rotations\_schedulerequests went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2FvbWqHnskFgY1dQjM32zF%2Fflow-rotations-schedulerequests.png?alt=media)

| Medtrics Classic field             | Oracle                                  | Outcome    | Note                                                            |
| ---------------------------------- | --------------------------------------- | ---------- | --------------------------------------------------------------- |
| `id` integer                       | `id` UUID                               | ID changed | Integer link → UUID (Split)                                     |
| `approved_by_id` integer           | `approved_by` UUID                      | ID changed | Integer link → UUID pointing to profiles (Split)                |
| `approved_by_id` integer           | `reviewed_by` UUID                      | ID changed | Integer link → UUID pointing to profiles (Split)                |
| `approved_by_id` integer           | `updated_by` UUID                       | ID changed | Integer link → UUID pointing to profiles (Split)                |
| `new_specialty_id` integer         | `requested_changes` JSONB               | ID changed | Integer link → UUID (Merged)                                    |
| `rotation_id` integer              | `requested_changes` JSONB               | ID changed | Integer link → UUID (Merged)                                    |
| `site_id` integer                  | `requested_changes` JSONB               | ID changed | Integer link → UUID (Merged)                                    |
| `user_id` integer                  | `created_by` UUID                       | ID changed | Integer link → UUID pointing to profiles (Split)                |
| `user_id` integer                  | `requester_id` UUID                     | ID changed | Integer link → UUID pointing to profiles (Split)                |
| `id` integer                       | `requested_changes` JSONB               | Renamed    | int → json (Split, Merged, Type changed)                        |
| `new_request_site_name` varchar    | `requested_changes` JSONB               | Renamed    | text → json (Merged, Type changed)                              |
| `new_request_site_address` varchar | `requested_changes` JSONB               | Renamed    | text → json (Merged, Type changed)                              |
| `new_request_site_city` varchar    | `requested_changes` JSONB               | Renamed    | text → json (Merged, Type changed)                              |
| `new_request_site_zip` varchar     | `requested_changes` JSONB               | Renamed    | text → json (Merged, Type changed)                              |
| `new_request_site_state` varchar   | `requested_changes` JSONB               | Renamed    | text → json (Merged, Type changed)                              |
| `new_rotation` varchar             | `requested_changes` JSONB               | Renamed    | text → json (Merged, Type changed)                              |
| `applicant_note` text              | `reason` TEXT                           | Renamed    |                                                                 |
| `administrator_note` text          | `review_notes` TEXT                     | Renamed    |                                                                 |
| `created_date` timestamptz         | `created_at` TIMESTAMPTZ                | Renamed    |                                                                 |
| `updated_date` timestamptz         | `reviewed_at` TIMESTAMPTZ               | Renamed    | (Split)                                                         |
| `updated_date` timestamptz         | `updated_at` TIMESTAMPTZ                | Renamed    | (Split)                                                         |
| `start_date` date                  | `start_date` DATE                       | Unchanged  |                                                                 |
| `end_date` date                    | `end_date` DATE                         | Unchanged  |                                                                 |
| `status` varchar                   | `status` enum:schedule\_request\_status | Unchanged  | Now a fixed value list (schedule\_request\_status) (Value list) |

* Swap the 12 renamed fields and point `FROM` at `schedule_change_requests`.
* Re-key 9 ID fields. Join people on `email`, not on old IDs.
* Add `WHERE deleted_at IS NULL`: `schedule_change_requests` keeps deleted rows.

```sql
-- Starter query: confirmed fields only. Was rotations_schedulerequests.
SELECT
  t.id,                -- was id
  t.requested_changes, -- was id
  t.start_date,        -- was start_date
  t.end_date,          -- was end_date
  t.reason,            -- was applicant_note
  t.review_notes,      -- was administrator_note
  t.status,            -- was status
  t.created_at,        -- was created_date
  t.reviewed_at,       -- was updated_date
  t.updated_at,        -- was updated_date
  t.approved_by,       -- was approved_by_id
  t.reviewed_by,       -- was approved_by_id
  t.updated_by,        -- was approved_by_id
  t.created_by         -- was user_id
FROM schedule_change_requests t
WHERE t.deleted_at IS NULL;
```

#### rotations\_userschedule

**rotations\_userschedule** → `block_schedules` · *renamed* · 21 confirmed fields (Unchanged 3 · Renamed 15 · ID changed 3)

User schedule assignments within blocks.

> The learner assignment. The important gain: block\_schedules names a CRI, so the assignment finally knows which hospital it is at; Medtrics Classic UserSchedule had no site column.

![Where the 21 confirmed fields of rotations\_userschedule went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2Fp73MJjG4RoJ4FhZEPo7k%2Fflow-rotations-userschedule.png?alt=media)

| Medtrics Classic field       | Oracle                            | Outcome    | Note                                                |
| ---------------------------- | --------------------------------- | ---------- | --------------------------------------------------- |
| `id` integer                 | `id` UUID                         | ID changed | Integer link → UUID (Split)                         |
| `block_id` integer           | `block_id` UUID                   | ID changed | Integer link → UUID pointing to blocks              |
| `user_id` integer            | `user_id` UUID                    | ID changed | Integer link → UUID pointing to profiles            |
| `id` integer                 | `external_id` TEXT                | Renamed    | int → text (Split, Type changed)                    |
| `confirmed` boolean          | `is_confirmed` BOOLEAN            | Renamed    |                                                     |
| `primary_rotation` boolean   | `is_primary` BOOLEAN              | Renamed    |                                                     |
| `start_date` timestamptz     | `start_at` TIMESTAMPTZ            | Renamed    |                                                     |
| `end_date` timestamptz       | `end_at` TIMESTAMPTZ              | Renamed    |                                                     |
| `gme` integer                | `gme_percentage` INTEGER          | Renamed    |                                                     |
| `ime` integer                | `ime_percentage` INTEGER          | Renamed    |                                                     |
| `serve_as_evaluator` boolean | `serve_as_responder` BOOLEAN      | Renamed    |                                                     |
| `serve_as_evaluatee` boolean | `serve_as_recipient` BOOLEAN      | Renamed    |                                                     |
| `full_block` boolean         | `block_schema` enum:block\_schema | Renamed    | Now a fixed value list (block\_schema) (Value list) |
| `note` text                  | `notes` TEXT                      | Renamed    |                                                     |
| `email_sent` boolean         | `is_email_sent` BOOLEAN           | Renamed    |                                                     |
| `updated_date` timestamptz   | `confirmed_at` TIMESTAMPTZ        | Renamed    |                                                     |
| `review_date` timestamptz    | `reviewed_at` TIMESTAMPTZ         | Renamed    |                                                     |
| `reviewed` boolean           | `is_reviewed` BOOLEAN             | Renamed    |                                                     |
| `credited_length` double     | `credited_length` NUMERIC(5,2)    | Unchanged  |                                                     |
| `sis_class` varchar          | `sis_class` TEXT                  | Unchanged  |                                                     |
| `sis_section` varchar        | `sis_section` TEXT                | Unchanged  |                                                     |

* Swap the 15 renamed fields and point `FROM` at `block_schedules`.
* Re-key 3 ID fields. Join people on `email`, not on old IDs.
* Add `WHERE deleted_at IS NULL`: `block_schedules` keeps deleted rows.

```sql
-- Starter query: confirmed fields only. Was rotations_userschedule.
SELECT
  t.external_id,        -- was id
  t.id,                 -- was id
  t.is_confirmed,       -- was confirmed
  t.is_primary,         -- was primary_rotation
  t.start_at,           -- was start_date
  t.end_at,             -- was end_date
  t.gme_percentage,     -- was gme
  t.ime_percentage,     -- was ime
  t.serve_as_responder, -- was serve_as_evaluator
  t.serve_as_recipient, -- was serve_as_evaluatee
  t.block_schema,       -- was full_block
  t.notes,              -- was note
  t.is_email_sent,      -- was email_sent
  t.confirmed_at        -- was updated_date
FROM block_schedules t
WHERE t.deleted_at IS NULL;
```

#### rotations\_userschedulelog

**rotations\_userschedulelog** → `user_schedule_logs` · *replaced* · 27 confirmed fields (Unchanged 2 · Renamed 20 · ID changed 5)

Audit trail of user-level schedule changes requiring review, mirroring block\_schedule\_logs shape. Backs Medtrics Classic rotations\_userschedulelog migration.

> Medtrics Classic kept typed columns and FKs for every changed field. Oracle keeps old\_values and new\_values JSONB. Easier to write, much harder to query or join.

![Where the 27 confirmed fields of rotations\_userschedulelog went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2FwjzfudSgEZGgbS5KTigt%2Fflow-rotations-userschedulelog.png?alt=media)

| Medtrics Classic field           | Oracle                   | Outcome    | Note                                             |
| -------------------------------- | ------------------------ | ---------- | ------------------------------------------------ |
| `id` integer                     | `id` UUID                | ID changed | Integer link → UUID                              |
| `pa_user_history_fk_id` integer  | `created_by` UUID        | ID changed | Integer link → UUID pointing to profiles (Split) |
| `pa_user_history_fk_id` integer  | `updated_by` UUID        | ID changed | Integer link → UUID pointing to profiles (Split) |
| `user_history_fk_id` integer     | `user_id` UUID           | ID changed | Integer link → UUID pointing to profiles         |
| `reviewer_fk_id` integer         | `reviewer` UUID          | ID changed | Integer link → UUID pointing to profiles         |
| `block` varchar                  | `new_values` JSONB       | Renamed    | text → json (Merged, Type changed)               |
| `rotation` varchar               | `new_values` JSONB       | Renamed    | text → json (Merged, Type changed)               |
| `old_start_date` timestamptz     | `old_values` JSONB       | Renamed    | timestamp → json (Merged, Type changed)          |
| `old_end_date` timestamptz       | `old_values` JSONB       | Renamed    | timestamp → json (Merged, Type changed)          |
| `start_date` timestamptz         | `new_values` JSONB       | Renamed    | timestamp → json (Merged, Type changed)          |
| `end_date` timestamptz           | `new_values` JSONB       | Renamed    | timestamp → json (Merged, Type changed)          |
| `log_date` timestamptz           | `created_at` TIMESTAMPTZ | Renamed    | (Split)                                          |
| `log_date` timestamptz           | `updated_at` TIMESTAMPTZ | Renamed    | (Split)                                          |
| `action` varchar                 | `change_type` TEXT       | Renamed    |                                                  |
| `primary_rotation` boolean       | `new_values` JSONB       | Renamed    | bool → json (Merged, Type changed)               |
| `old_review_date` timestamptz    | `old_values` JSONB       | Renamed    | timestamp → json (Merged, Type changed)          |
| `graded_course_rotation` varchar | `new_values` JSONB       | Renamed    | text → json (Merged, Type changed)               |
| `old_rotation` varchar           | `old_values` JSONB       | Renamed    | text → json (Merged, Type changed)               |
| `old_rotation_code` varchar      | `old_values` JSONB       | Renamed    | text → json (Merged, Type changed)               |
| `program_schedule` varchar       | `new_values` JSONB       | Renamed    | text → json (Merged, Type changed)               |
| `rotation_code` varchar          | `new_values` JSONB       | Renamed    | text → json (Merged, Type changed)               |
| `employee_number` varchar        | `new_values` JSONB       | Renamed    | text → json (Merged, Type changed)               |
| `enrolled` boolean               | `new_values` JSONB       | Renamed    | bool → json (Merged, Type changed)               |
| `sis_class` varchar              | `new_values` JSONB       | Renamed    | text → json (Merged, Type changed)               |
| `sis_section` varchar            | `new_values` JSONB       | Renamed    | text → json (Merged, Type changed)               |
| `review_date` timestamptz        | `review_date` DATE       | Unchanged  | timestamp → date (Type changed)                  |
| `audited` boolean                | `audited` BOOLEAN        | Unchanged  |                                                  |

* Swap the 20 renamed fields and point `FROM` at `user_schedule_logs`.
* Re-key 5 ID fields. Join people on `email`, not on old IDs.

```sql
-- Starter query: confirmed fields only. Was rotations_userschedulelog.
SELECT
  t.id,          -- was id
  t.new_values,  -- was block
  t.old_values,  -- was old_start_date
  t.created_at,  -- was log_date
  t.updated_at,  -- was log_date
  t.change_type, -- was action
  t.created_by,  -- was pa_user_history_fk_id
  t.updated_by,  -- was pa_user_history_fk_id
  t.user_id,     -- was user_history_fk_id
  t.review_date, -- was review_date
  t.reviewer,    -- was reviewer_fk_id
  t.audited      -- was audited
FROM user_schedule_logs t;
```

### Shift Schedules

9 tables, 45 confirmed fields: Unchanged 4 · Renamed 14 · ID changed 27.

#### rotations\_assigndatetoshift

**rotations\_assigndatetoshift** → `schedule_change_requests`, `shift_assignments`, `shift_occurrences` · *replaced* · 5 confirmed fields (Renamed 4 · ID changed 1)

Unified schedule change, swap, and time-off request workflow. Split table: each field names its new table.

> The shift world was rebuilt properly: reusable definition, recurrence rule, period deployment, dated occurrence, person assignment. Medtrics Classic stored times as CharField; Oracle uses TIME and TIMESTAMPTZ.

![Where the 5 confirmed fields of rotations\_assigndatetoshift went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2FdYJAGHrybvdZiCY8jHv6%2Fflow-rotations-assigndatetoshift.png?alt=media)

| Medtrics Classic field | Oracle                                       | Outcome    | Note                                  |
| ---------------------- | -------------------------------------------- | ---------- | ------------------------------------- |
| `site_id` integer      | shift\_occurrences.`site_id` UUID            | ID changed | Integer link → UUID pointing to sites |
| `applied_date` date    | schedule\_change\_requests.`end_date` DATE   | Renamed    | (Split)                               |
| `applied_date` date    | schedule\_change\_requests.`start_date` DATE | Renamed    | (Split)                               |
| `applied_date` date    | shift\_occurrences.`shift_date` DATE         | Renamed    | (Split)                               |
| `description` text     | shift\_occurrences.`notes` TEXT              | Renamed    |                                       |

* Swap the 4 renamed fields and point `FROM` at `schedule_change_requests` (and the other new tables).
* Re-key 1 ID field. Join people on `email`, not on old IDs.
* Add `WHERE deleted_at IS NULL`: `schedule_change_requests`, `shift_assignments`, `shift_occurrences` keep deleted rows.

#### rotations\_assigndatetoshift\_shift\_assinee\_user

**rotations\_assigndatetoshift\_shift\_assinee\_user** → `shift_assignments` · 5 confirmed fields (Renamed 1 · ID changed 4)

Assignments of people to shift occurrences with explicit program, person type, and coverage role context.

![Where the 5 confirmed fields of rotations\_assigndatetoshift\_shift\_assinee\_user went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2F3uldNsUAq7hkmcL10C69%2Fflow-rotations-assigndatetoshift-shift-assinee-user.png?alt=media)

| Medtrics Classic field         | Oracle                     | Outcome    | Note                                             |
| ------------------------------ | -------------------------- | ---------- | ------------------------------------------------ |
| `id` integer                   | `id` UUID                  | ID changed | Integer link → UUID (Split)                      |
| `assigndatetoshift_id` integer | `practicum_metadata` JSONB | ID changed | Integer link → UUID (Merged)                     |
| `user_id` integer              | `practicum_metadata` JSONB | ID changed | Integer link → UUID (Split, Merged)              |
| `user_id` integer              | `user_id` UUID             | ID changed | Integer link → UUID pointing to profiles (Split) |
| `id` integer                   | `practicum_metadata` JSONB | Renamed    | int → json (Split, Merged, Type changed)         |

* Swap the 1 renamed field and point `FROM` at `shift_assignments`.
* Re-key 4 ID fields. Join people on `email`, not on old IDs.
* Add `WHERE deleted_at IS NULL`: `shift_assignments` keeps deleted rows.

```sql
-- Starter query: confirmed fields only. Was rotations_assigndatetoshift_shift_assinee_user.
SELECT
  t.id,                 -- was id
  t.practicum_metadata, -- was id
  t.user_id             -- was user_id
FROM shift_assignments t
WHERE t.deleted_at IS NULL;
```

#### rotations\_callscheduleprogram

**rotations\_callscheduleprogram** → `clinical_schedule_admins`, `clinical_schedule_groups`, `clinical_schedule_roles`, `clinical_schedule_sites`, `clinical_schedule_users`, `clinical_schedules` · *replaced* · 8 confirmed fields (Unchanged 1 · Renamed 3 · ID changed 4)

Administrators for clinical schedules. Split table: each field names its new table.

> The shift world was rebuilt properly: reusable definition, recurrence rule, period deployment, dated occurrence, person assignment. Medtrics Classic stored times as CharField; Oracle uses TIME and TIMESTAMPTZ.

![Where the 8 confirmed fields of rotations\_callscheduleprogram went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2FlGZw5PaKFL7C7Ys1wRkI%2Fflow-rotations-callscheduleprogram.png?alt=media)

| Medtrics Classic field   | Oracle                                      | Outcome    | Note                                          |
| ------------------------ | ------------------------------------------- | ---------- | --------------------------------------------- |
| `location_id` integer    | clinical\_schedules.`schedule_config` JSONB | ID changed | Integer link → UUID (Merged)                  |
| `program_id` integer     | clinical\_schedules.`program_id` UUID       | ID changed | Integer link → UUID pointing to programs      |
| `site_id` integer        | clinical\_schedule\_sites.`site_id` UUID    | ID changed | Integer link → UUID pointing to sites (Split) |
| `site_id` integer        | clinical\_schedules.`schedule_config` JSONB | ID changed | Integer link → UUID (Split, Merged)           |
| `id` integer             | clinical\_schedules.`schedule_config` JSONB | Renamed    | int → json (Merged, Type changed)             |
| `show_place` boolean     | clinical\_schedules.`schedule_config` JSONB | Renamed    | bool → json (Merged, Type changed)            |
| `show_all_shift` boolean | clinical\_schedules.`schedule_config` JSONB | Renamed    | bool → json (Merged, Type changed)            |
| `description` text       | clinical\_schedules.`description` TEXT      | Unchanged  |                                               |

* Swap the 3 renamed fields and point `FROM` at `clinical_schedule_admins` (and the other new tables).
* Re-key 4 ID fields. Join people on `email`, not on old IDs.
* Add `WHERE deleted_at IS NULL`: `clinical_schedules` keeps deleted rows.

#### rotations\_callscheduleprogram\_admin\_users

**rotations\_callscheduleprogram\_admin\_users** → `clinical_schedule_admins` · 2 confirmed fields (ID changed 2)

Administrators for clinical schedules.

![Where the 2 confirmed fields of rotations\_callscheduleprogram\_admin\_users went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2FWdJnYmJOVGRpvMJV6ZJa%2Fflow-rotations-callscheduleprogram-admin-users.png?alt=media)

| Medtrics Classic field | Oracle         | Outcome    | Note                                                                                                                |
| ---------------------- | -------------- | ---------- | ------------------------------------------------------------------------------------------------------------------- |
| `id` integer           | `id` UUID      | ID changed | Integer ID replaced by a new UUID. Medtrics Classic → new ID crosswalk is kept by the migration (see Keys & joins). |
| `user_id` integer      | `user_id` UUID | ID changed | Integer link → UUID pointing to profiles                                                                            |

* Re-key 2 ID fields. Join people on `email`, not on old IDs.

```sql
-- Starter query: confirmed fields only. Was rotations_callscheduleprogram_admin_users.
SELECT
  t.id,      -- was id
  t.user_id  -- was user_id
FROM clinical_schedule_admins t;
```

#### rotations\_callscheduleprogram\_roles

**rotations\_callscheduleprogram\_roles** → `clinical_schedule_roles` · 2 confirmed fields (ID changed 2)

Role-based access control for clinical schedules.

![Where the 2 confirmed fields of rotations\_callscheduleprogram\_roles went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2Fx6v5CDz9bxfvvU3c3rCo%2Fflow-rotations-callscheduleprogram-roles.png?alt=media)

| Medtrics Classic field  | Oracle         | Outcome    | Note                                                                                                                |
| ----------------------- | -------------- | ---------- | ------------------------------------------------------------------------------------------------------------------- |
| `id` integer            | `id` UUID      | ID changed | Integer ID replaced by a new UUID. Medtrics Classic → new ID crosswalk is kept by the migration (see Keys & joins). |
| `customrole_id` integer | `role_id` UUID | ID changed | Integer link → UUID pointing to roles                                                                               |

* Re-key 2 ID fields. Join people on `email`, not on old IDs.

```sql
-- Starter query: confirmed fields only. Was rotations_callscheduleprogram_roles.
SELECT
  t.id,      -- was id
  t.role_id  -- was customrole_id
FROM clinical_schedule_roles t;
```

#### rotations\_callscheduleprogram\_view\_access\_to\_roles

**rotations\_callscheduleprogram\_view\_access\_to\_roles** → `clinical_schedule_roles` · 2 confirmed fields (ID changed 2)

Role-based access control for clinical schedules.

![Where the 2 confirmed fields of rotations\_callscheduleprogram\_view\_access\_to\_roles went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2FKO9p0mQpfa6lPGUZsw0S%2Fflow-rotations-callscheduleprogram-view-access-to-roles.png?alt=media)

| Medtrics Classic field  | Oracle         | Outcome    | Note                                                                                                                |
| ----------------------- | -------------- | ---------- | ------------------------------------------------------------------------------------------------------------------- |
| `id` integer            | `id` UUID      | ID changed | Integer ID replaced by a new UUID. Medtrics Classic → new ID crosswalk is kept by the migration (see Keys & joins). |
| `customrole_id` integer | `role_id` UUID | ID changed | Integer link → UUID pointing to roles                                                                               |

* Re-key 2 ID fields. Join people on `email`, not on old IDs.

```sql
-- Starter query: confirmed fields only. Was rotations_callscheduleprogram_view_access_to_roles.
SELECT
  t.id,      -- was id
  t.role_id  -- was customrole_id
FROM clinical_schedule_roles t;
```

#### rotations\_callscheduleprogram\_view\_access\_to\_users

**rotations\_callscheduleprogram\_view\_access\_to\_users** → `clinical_schedule_users` · 2 confirmed fields (ID changed 2)

User-level access control for clinical schedules.

![Where the 2 confirmed fields of rotations\_callscheduleprogram\_view\_access\_to\_users went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2F40rIcUDi3OQ4N9dza7ZR%2Fflow-rotations-callscheduleprogram-view-access-to-users.png?alt=media)

| Medtrics Classic field | Oracle         | Outcome    | Note                                                                                                                |
| ---------------------- | -------------- | ---------- | ------------------------------------------------------------------------------------------------------------------- |
| `id` integer           | `id` UUID      | ID changed | Integer ID replaced by a new UUID. Medtrics Classic → new ID crosswalk is kept by the migration (see Keys & joins). |
| `user_id` integer      | `user_id` UUID | ID changed | Integer link → UUID pointing to profiles                                                                            |

* Re-key 2 ID fields. Join people on `email`, not on old IDs.

```sql
-- Starter query: confirmed fields only. Was rotations_callscheduleprogram_view_access_to_users.
SELECT
  t.id,      -- was id
  t.user_id  -- was user_id
FROM clinical_schedule_users t;
```

#### rotations\_rotationshiftschedule

**rotations\_rotationshiftschedule** → `rotation_shift_schedules` · *replaced* · 2 confirmed fields (ID changed 2)

Maps rotations to shift templates with weekday patterns.

> The shift world was rebuilt properly: reusable definition, recurrence rule, period deployment, dated occurrence, person assignment. Medtrics Classic stored times as CharField; Oracle uses TIME and TIMESTAMPTZ.

![Where the 2 confirmed fields of rotations\_rotationshiftschedule went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2Fn44WVRpFrLV6tmToVnq9%2Fflow-rotations-rotationshiftschedule.png?alt=media)

| Medtrics Classic field | Oracle                               | Outcome    | Note                                                          |
| ---------------------- | ------------------------------------ | ---------- | ------------------------------------------------------------- |
| `id` integer           | `id` UUID                            | ID changed | Integer link → UUID                                           |
| `rotation_id` integer  | `clinical_rotation_instance_id` UUID | ID changed | Integer link → UUID pointing to clinical\_rotation\_instances |

* Re-key 2 ID fields. Join people on `email`, not on old IDs.

```sql
-- Starter query: confirmed fields only. Was rotations_rotationshiftschedule.
SELECT
  t.id,                            -- was id
  t.clinical_rotation_instance_id  -- was rotation_id
FROM rotation_shift_schedules t;
```

#### rotations\_shiftchangerequest

**rotations\_shiftchangerequest** → `schedule_change_requests` · *replaced* · 17 confirmed fields (Unchanged 3 · Renamed 6 · ID changed 8)

Unified schedule change, swap, and time-off request workflow.

> The shift world was rebuilt properly: reusable definition, recurrence rule, period deployment, dated occurrence, person assignment. Medtrics Classic stored times as CharField; Oracle uses TIME and TIMESTAMPTZ.

![Where the 17 confirmed fields of rotations\_shiftchangerequest went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2F9y8BuMOapbNt5xNcBaxJ%2Fflow-rotations-shiftchangerequest.png?alt=media)

| Medtrics Classic field   | Oracle                                  | Outcome    | Note                                                                   |
| ------------------------ | --------------------------------------- | ---------- | ---------------------------------------------------------------------- |
| `id` integer             | `id` UUID                               | ID changed | Integer link → UUID (Split)                                            |
| `change_to_id` integer   | `requested_changes` JSONB               | ID changed | Integer link → UUID (Merged)                                           |
| `change_with_id` integer | `requested_changes` JSONB               | ID changed | Integer link → UUID (Split, Merged)                                    |
| `change_with_id` integer | `swap_with_user_id` UUID                | ID changed | Integer link → UUID pointing to profiles (Split)                       |
| `shift_id` integer       | `requested_changes` JSONB               | ID changed | Integer link → UUID (Merged)                                           |
| `updated_by_id` integer  | `approved_by` UUID                      | ID changed | Integer link → UUID pointing to profiles (Split)                       |
| `updated_by_id` integer  | `reviewed_by` UUID                      | ID changed | Integer link → UUID pointing to profiles (Split)                       |
| `user_id` integer        | `requester_id` UUID                     | ID changed | Integer link → UUID pointing to profiles                               |
| `id` integer             | `requested_changes` JSONB               | Renamed    | int → json (Split, Merged, Type changed)                               |
| `status` varchar         | `requested_changes` JSONB               | Renamed    | text → json (Split, Merged, Type changed)                              |
| `change_type` varchar    | `requested_changes` JSONB               | Renamed    | text → json (Merged, Type changed)                                     |
| `notes` text             | `reason` TEXT                           | Renamed    |                                                                        |
| `updated_at` timestamptz | `reviewed_at` TIMESTAMPTZ               | Renamed    | (Split)                                                                |
| `admin_comments` text    | `review_notes` TEXT                     | Renamed    |                                                                        |
| `created_at` timestamptz | `created_at` TIMESTAMPTZ                | Unchanged  |                                                                        |
| `status` varchar         | `status` enum:schedule\_request\_status | Unchanged  | Now a fixed value list (schedule\_request\_status) (Split, Value list) |
| `updated_at` timestamptz | `updated_at` TIMESTAMPTZ                | Unchanged  | (Split)                                                                |

* Swap the 6 renamed fields and point `FROM` at `schedule_change_requests`.
* Re-key 8 ID fields. Join people on `email`, not on old IDs.
* Add `WHERE deleted_at IS NULL`: `schedule_change_requests` keeps deleted rows.

```sql
-- Starter query: confirmed fields only. Was rotations_shiftchangerequest.
SELECT
  t.id,                -- was id
  t.requested_changes, -- was id
  t.created_at,        -- was created_at
  t.status,            -- was status
  t.reason,            -- was notes
  t.reviewed_at,       -- was updated_at
  t.updated_at,        -- was updated_at
  t.review_notes,      -- was admin_comments
  t.swap_with_user_id, -- was change_with_id
  t.approved_by,       -- was updated_by_id
  t.reviewed_by,       -- was updated_by_id
  t.requester_id       -- was user_id
FROM schedule_change_requests t
WHERE t.deleted_at IS NULL;
```

### Calendar & Events

6 tables, 34 confirmed fields: Unchanged 7 · Renamed 9 · ID changed 18.

#### events\_attendance

**events\_attendance** → `event_attendance` · *renamed* · 8 confirmed fields (Unchanged 2 · Renamed 2 · ID changed 4)

Unified attendance tracking for events (absorbs former attendance\_records table).

> Same shape - one row per person per event - but the status is now a database enum and the table also absorbed a separate attendance\_records table, which survives as a read-only view.

![Where the 8 confirmed fields of events\_attendance went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2FfzS4aAp830CCMSqcO3CF%2Fflow-events-attendance.png?alt=media)

| Medtrics Classic field     | Oracle                           | Outcome    | Note                                                                                                                |
| -------------------------- | -------------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------- |
| `id` integer               | `id` UUID                        | ID changed | Integer ID replaced by a new UUID. Medtrics Classic → new ID crosswalk is kept by the migration (see Keys & joins). |
| `event_id` integer         | `event_id` UUID                  | ID changed | Integer link → UUID pointing to events                                                                              |
| `user_id` integer          | `user_id` UUID                   | ID changed | Integer link → UUID pointing to profiles                                                                            |
| `created_by_id` integer    | `marked_by` UUID                 | ID changed | Integer link → UUID pointing to profiles                                                                            |
| `created_date` timestamptz | `created_at` TIMESTAMPTZ         | Renamed    |                                                                                                                     |
| `updated_date` timestamptz | `updated_at` TIMESTAMPTZ         | Renamed    |                                                                                                                     |
| `status` varchar           | `status` enum:attendance\_status | Unchanged  | Now a fixed value list (attendance\_status) (Value list)                                                            |
| `notes` text               | `notes` TEXT                     | Unchanged  |                                                                                                                     |

* Swap the 2 renamed fields and point `FROM` at `event_attendance`.
* Re-key 4 ID fields. Join people on `email`, not on old IDs.
* Add `WHERE deleted_at IS NULL`: `event_attendance` keeps deleted rows.

```sql
-- Starter query: confirmed fields only. Was events_attendance.
SELECT
  t.id,         -- was id
  t.status,     -- was status
  t.notes,      -- was notes
  t.created_at, -- was created_date
  t.event_id,   -- was event_id
  t.user_id,    -- was user_id
  t.marked_by,  -- was created_by_id
  t.updated_at  -- was updated_date
FROM event_attendance t
WHERE t.deleted_at IS NULL;
```

#### events\_calendarcoordinator

**events\_calendarcoordinator** → `calendar_coordinators` · *same* · 3 confirmed fields (ID changed 3)

Program-level calendar coordinators who can manage events (Medtrics Classic: events.CalendarCoordinator).

> Oracle adds four capability flags and soft-delete so a revoked coordinator is kept for audit rather than erased.

![Where the 3 confirmed fields of events\_calendarcoordinator went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2FHOwt62uOV6vqt7LB1gDS%2Fflow-events-calendarcoordinator.png?alt=media)

| Medtrics Classic field | Oracle            | Outcome    | Note                                     |
| ---------------------- | ----------------- | ---------- | ---------------------------------------- |
| `id` integer           | `id` UUID         | ID changed | Integer link → UUID                      |
| `program_id` integer   | `program_id` UUID | ID changed | Integer link → UUID pointing to programs |
| `user_id` integer      | `user_id` UUID    | ID changed | Integer link → UUID pointing to profiles |

* Re-key 3 ID fields. Join people on `email`, not on old IDs.
* Add `WHERE deleted_at IS NULL`: `calendar_coordinators` keeps deleted rows.

```sql
-- Starter query: confirmed fields only. Was events_calendarcoordinator.
SELECT
  t.id,         -- was id
  t.program_id, -- was program_id
  t.user_id     -- was user_id
FROM calendar_coordinators t
WHERE t.deleted_at IS NULL;
```

#### events\_event

**events\_event** → `events` · *split* · 15 confirmed fields (Unchanged 5 · Renamed 7 · ID changed 3)

Calendar events (lectures, conferences, meetings, etc.).

> One wide row became a core row plus six satellites. Reads that used to be a single row now need joins, but each concept can now evolve on its own.

![Where the 15 confirmed fields of events\_event went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2F8uDniP6AywbjBaAEk8DS%2Fflow-events-event.png?alt=media)

| Medtrics Classic field        | Oracle                     | Outcome    | Note                                         |
| ----------------------------- | -------------------------- | ---------- | -------------------------------------------- |
| `id` integer                  | `id` UUID                  | ID changed | Integer link → UUID                          |
| `created_by_id` integer       | `created_by` UUID          | ID changed | Integer link → UUID pointing to profiles     |
| `event_type_id` integer       | `event_type_id` UUID       | ID changed | Integer link → UUID pointing to event\_types |
| `created_date` timestamptz    | `created_at` TIMESTAMPTZ   | Renamed    |                                              |
| `start_datetime` timestamptz  | `start_at` TIMESTAMPTZ     | Renamed    |                                              |
| `end_datetime` timestamptz    | `end_at` TIMESTAMPTZ       | Renamed    |                                              |
| `place` varchar               | `venue` TEXT               | Renamed    |                                              |
| `is_trackattendance` boolean  | `track_attendance` BOOLEAN | Renamed    |                                              |
| `is_only_invite_user` boolean | `invite_only` BOOLEAN      | Renamed    |                                              |
| `updated_date` timestamptz    | `updated_at` TIMESTAMPTZ   | Renamed    |                                              |
| `title` varchar               | `title` TEXT               | Unchanged  |                                              |
| `description` text            | `description` TEXT         | Unchanged  |                                              |
| `all_day` boolean             | `all_day` BOOLEAN          | Unchanged  |                                              |
| `is_public` boolean           | `is_public` BOOLEAN        | Unchanged  |                                              |
| `is_mandatory` boolean        | `is_mandatory` BOOLEAN     | Unchanged  |                                              |

* Swap the 7 renamed fields and point `FROM` at `events`.
* Re-key 3 ID fields. Join people on `email`, not on old IDs.
* Add `WHERE deleted_at IS NULL`: `events` keeps deleted rows.

```sql
-- Starter query: confirmed fields only. Was events_event.
SELECT
  t.id,               -- was id
  t.title,            -- was title
  t.description,      -- was description
  t.created_at,       -- was created_date
  t.start_at,         -- was start_datetime
  t.end_at,           -- was end_datetime
  t.all_day,          -- was all_day
  t.venue,            -- was place
  t.is_public,        -- was is_public
  t.is_mandatory,     -- was is_mandatory
  t.track_attendance, -- was is_trackattendance
  t.invite_only,      -- was is_only_invite_user
  t.created_by,       -- was created_by_id
  t.updated_at        -- was updated_date
FROM events t
WHERE t.deleted_at IS NULL;
```

#### events\_event\_groups

**events\_event\_groups** → `event_invited_groups` · 2 confirmed fields (ID changed 2)

Junction table for group-based event invitations.

![Where the 2 confirmed fields of events\_event\_groups went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2FPHygeCKEIDyJe3MPImCP%2Fflow-events-event-groups.png?alt=media)

| Medtrics Classic field | Oracle          | Outcome    | Note                                                                                                                |
| ---------------------- | --------------- | ---------- | ------------------------------------------------------------------------------------------------------------------- |
| `id` integer           | `id` UUID       | ID changed | Integer ID replaced by a new UUID. Medtrics Classic → new ID crosswalk is kept by the migration (see Keys & joins). |
| `event_id` integer     | `event_id` UUID | ID changed | Integer link → UUID pointing to events                                                                              |

* Re-key 2 ID fields. Join people on `email`, not on old IDs.

```sql
-- Starter query: confirmed fields only. Was events_event_groups.
SELECT
  t.id,       -- was id
  t.event_id  -- was event_id
FROM event_invited_groups t;
```

#### events\_event\_programs

**events\_event\_programs** → `event_programs` · 3 confirmed fields (ID changed 3)

Junction table linking events to programs.

![Where the 3 confirmed fields of events\_event\_programs went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2F7Hxwrk4WHcLlatKWCh8r%2Fflow-events-event-programs.png?alt=media)

| Medtrics Classic field        | Oracle            | Outcome    | Note                                                                                                                |
| ----------------------------- | ----------------- | ---------- | ------------------------------------------------------------------------------------------------------------------- |
| `id` integer                  | `id` UUID         | ID changed | Integer ID replaced by a new UUID. Medtrics Classic → new ID crosswalk is kept by the migration (see Keys & joins). |
| `event_id` integer            | `event_id` UUID   | ID changed | Integer link → UUID pointing to events                                                                              |
| `residencyprogram_id` integer | `program_id` UUID | ID changed | Integer link → UUID pointing to programs                                                                            |

* Re-key 3 ID fields. Join people on `email`, not on old IDs.

```sql
-- Starter query: confirmed fields only. Was events_event_programs.
SELECT
  t.id,         -- was id
  t.event_id,   -- was event_id
  t.program_id  -- was residencyprogram_id
FROM event_programs t;
```

#### events\_event\_roles

**events\_event\_roles** → `event_invited_roles` · 3 confirmed fields (ID changed 3)

Junction table for role-based event invitations.

![Where the 3 confirmed fields of events\_event\_roles went](https://2912658775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxpbJErq8GWWHPPkzmpv3%2Fuploads%2FitTtsuPR3riS6LCKxN2B%2Fflow-events-event-roles.png?alt=media)

| Medtrics Classic field  | Oracle          | Outcome    | Note                                                                                                                |
| ----------------------- | --------------- | ---------- | ------------------------------------------------------------------------------------------------------------------- |
| `id` integer            | `id` UUID       | ID changed | Integer ID replaced by a new UUID. Medtrics Classic → new ID crosswalk is kept by the migration (see Keys & joins). |
| `event_id` integer      | `event_id` UUID | ID changed | Integer link → UUID pointing to events                                                                              |
| `customrole_id` integer | `role_id` UUID  | ID changed | Integer link → UUID pointing to roles                                                                               |

* Re-key 3 ID fields. Join people on `email`, not on old IDs.

```sql
-- Starter query: confirmed fields only. Was events_event_roles.
SELECT
  t.id,       -- was id
  t.event_id, -- was event_id
  t.role_id   -- was customrole_id
FROM event_invited_roles t;
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.mymedtrics.com/get-started/classic-data-mapping/scheduling.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
