Curriculum structures
A curriculum is a tree of containers. Each container states a requirement, such as “Core Courses”, “Prescribed Electives” or “Choose 12 UOC from the following”, and holds subject entries, child containers, or both.
We don’t impose a shape on the tree. Depth, naming and how you divide requirements are yours to decide, so build whatever describes your program.
What a container carries
dynamicRules exists so we can render handbook text faithfully. Nothing
evaluates it, and no assessment reads it. If a requirement has to affect an
outcome, it needs to be an explicit entry.
Draft first, then publish
Containers are created as DRAFT, which is what lets you assemble and review a whole tree
before anything depends on it.
Three operations are allowed only while a container is a draft:
- attaching it to a program or specialisation, with
PUT /structures/{structureId}/owner - nesting it under another container, with
PUT /structures/{structureId}/parent - deleting it
Publishing with PUT /structures/{structureId}/status sets the tree LIVE. Assessment reads
live trees, so the shape stops moving at that point, though you can still add and remove
subject entries.
To find work you started and left, GET /structures/drafts lists drafts that aren’t yet
attached to anything.
Ownership
A container is owned by at most one program or specialisation, never both. While it is still a draft it can belong to neither, which is how you build a tree before deciding where it goes.
Ownership applies to the root of a tree. Child containers belong to their parent and inherit the owner from it.
Deleting a program or specialisation deletes its containers along with it. If you delete a specialisation that some other container references, that entry stays where it is with its link cleared, so you don’t silently remove someone else’s requirement.
Adding and removing subjects
A subject must already exist in your catalogue at that code and year before you can add it to a container. Create the subject first, then reference it.
Entries carry a resolved flag. When it’s false, the code isn’t in the catalogue. This
only happens for entries that came from the original handbook import, never for anything you
add through the API.
Entries have an itemType of Course, Major, Minor, Honours,
Specialisation or Research. A subject entry reports itemType: "Course"
even though the endpoints call it a subject. The stored value predates the
rename, and changing it would rewrite tens of thousands of historical rows, so
match on "Course" rather than "Subject".
Only Course entries can be added through the API. The rest came from the handbook import
and are read-only.
Reading a curriculum
The first two return the whole tree, nested, with entries in sibling order. The third returns a single container and everything beneath it. Both produce the same shape, so one renderer will handle either.
A typical build
POST /structuresfor the root, then again for each child. All of them start asDRAFT.PUT /structures/{id}/parentto nest the children.POST /structures/{id}/subjectsto add entries.GET /structures/{rootId}to review the assembled tree.PUT /structures/{id}/ownerto attach it to its program.PUT /structures/{id}/statusto publish itLIVE.
Steps 1 to 4 are freely reversible. From step 5 onwards the shape is settled.
