{
  "openapi": "3.0.1",
  "info": {
    "title": "SoftLanding.ApiService | teacher",
    "version": "1.0.0"
  },
  "paths": {
    "/teacher/attendance-documents": {
      "post": {
        "tags": [
          "AttendanceDocument (Teacher)"
        ],
        "summary": "Upload an absence document (multipart/form-data).",
        "description": "As the office endpoint: stores the file and returns its id for the following lesson `PATCH`. Accepts\nPDF, JPEG and PNG up to 10 MB; anything else is `400`.",
        "operationId": "UploadAttendanceDocumentTeacher",
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "required": [
                  "file"
                ],
                "type": "object",
                "properties": {
                  "file": {
                    "$ref": "#/components/schemas/IFormFile"
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UploadedDocument"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpValidationProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/teacher/attendance-documents/{id}": {
      "delete": {
        "tags": [
          "AttendanceDocument (Teacher)"
        ],
        "summary": "Discard your own not-yet-attached upload.",
        "description": "Deletes a document this teacher uploaded that is not attached to any attendance record — what the\ndialog calls when it is closed without saving, so a picked-but-abandoned file leaves nothing behind.\n\nDeliberately narrower than the office route: a document that IS attached to a record cannot be deleted\nhere, and neither can somebody else's upload. Both answer `404` — never `403`, which would already\nconfirm the document exists.",
        "operationId": "DiscardAttendanceDocumentTeacher",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "AttendanceDocument (Teacher)"
        ],
        "summary": "Download an absence document of one of your own lessons.",
        "description": "Streams the stored file. A teacher may only read documents attached to an attendance record of a lesson\nof a course they teach (main or additional teacher), plus their own not-yet-attached upload.\n\nAnything else is `404`, never `403` — these are medical certificates about named students, and a `403`\nwould already confirm that the document exists.",
        "operationId": "DownloadAttendanceDocumentTeacher",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/teacher/homework-documents": {
      "post": {
        "tags": [
          "HomeworkDocument (Teacher)"
        ],
        "summary": "Upload a file for a homework (multipart/form-data).",
        "description": "Stores the file and returns its `id`, `fileName` and `sizeBytes`. Pass that id in `documentIdsToAdd` on\nthe homework create or patch — or on a homework carried by a lesson create (`homeworksToAdd`).\n\nThe document is stored UNATTACHED on purpose: only the upload can mint the id, and a homework created\ntogether with its lesson does not exist yet while the file is being picked. An upload that is never\nattached is removed by the nightly sweep.\n\nAccepts PDF, JPEG and PNG up to 10 MB. An empty file, a larger one or another type is `400`. The bytes\nare stored in the database — the API's filesystem is ephemeral and per-instance, so a path would survive\nneither a redeploy nor a second replica.",
        "operationId": "UploadHomeworkDocumentTeacher",
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "required": [
                  "file"
                ],
                "type": "object",
                "properties": {
                  "file": {
                    "$ref": "#/components/schemas/IFormFile"
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UploadedHomeworkDocument"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpValidationProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/teacher/homework-documents/{id}": {
      "get": {
        "tags": [
          "HomeworkDocument (Teacher)"
        ],
        "summary": "Download a homework file of one of the teacher's own courses.",
        "description": "Streams the stored file with its original name and content type. A teacher reads the files of a homework on a lesson of a course they are on — main or additional teacher, the two count alike — plus their own not-yet-attached upload. Anything else is `404`, not `403`: a 403 would already confirm the file exists.",
        "operationId": "DownloadHomeworkDocumentTeacher",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "HomeworkDocument (Teacher)"
        ],
        "summary": "Discard an upload that was never attached.",
        "description": "Removes an upload that has NOT been attached to a homework — what a dialog calls when the user takes a\nfile back before saving, or leaves without saving.\n\nAn ATTACHED document is `404`, and so is somebody else's upload: without that, this route would be a way\nto delete a worksheet off another person's homework. To remove an attached file, send its id in\n`documentIdsToRemove` on the homework patch.",
        "operationId": "DiscardHomeworkDocumentTeacher",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/teacher/my-profile": {
      "get": {
        "tags": [
          "MyProfile (Teacher)"
        ],
        "summary": "The signed-in teacher's own profile, in the teacher portal's shape.",
        "description": "Returns the signed-in teacher's profile as a `TeacherProfileGet`: identity, contact details,\naddress, bank information, weekly availability, planned absences, spoken and teaching languages,\nthe four office-maintained clearances, completed trainings and child entitlements.\n\nThe record is resolved from the signed-in user, so no id is passed and no filter is accepted.\nThis is the same underlying record as `/teacher/my-profile`, reshaped for the portal and\n**narrowed**: the AHV number, the salary, the Quellensteuer and BVG figures, the nationality, the\ncivil status and the account status are not part of this contract and are not sent.\n\nReturns `404` when the signed-in user has no linked teacher record.",
        "operationId": "GetTeacherMyProfile",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeacherProfileGet"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "MyProfile (Teacher)"
        ],
        "summary": "Partially update the signed-in teacher's own profile (self-editable fields only).",
        "description": "Partially updates the signed-in teacher's profile from a `TeacherProfilePatch`. Self-editable are\nthe address, the bank details (IBAN, account holder), the spoken languages, the weekly\navailability slots and the planned absences; the three collections use the add/update/remove\nstrategy. Everything else — names, e-mail, employment data, the clearances, teaching languages,\ntrainings and child entitlements — is office-maintained and is never changed here, whatever the\nbody contains.\n\nReturns the updated `TeacherProfileGet`, `400` on validation errors, or `404` when the signed-in\nuser has no linked teacher record.",
        "operationId": "UpdateTeacherMyProfile",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TeacherProfilePatch"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeacherProfileGet"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpValidationProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/teacher/my-profile/reset-password": {
      "post": {
        "tags": [
          "MyProfile (Teacher)"
        ],
        "summary": "Send the signed-in teacher their own password-reset link.",
        "description": "Triggers the identity provider's password-reset mail for the signed-in teacher's own login. The\nlink goes to the address on their record and is rendered and delivered by Keycloak itself — this\napplication never learns or sets the password, and the login number never changes.\n\nReturns `204` once the mail was handed over. `400` if the record has no email address (there is\nnowhere to send it), `409` if the record has no login account yet, `404` when the signed-in user\nhas no linked teacher record, and `503` when no identity provider is configured.",
        "operationId": "ResetTeacherMyPassword",
        "responses": {
          "204": {
            "description": "No Content"
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/teacher/my-students": {
      "get": {
        "tags": [
          "Student (Teacher)"
        ],
        "summary": "List the signed-in teacher's students, in the teacher portal's shape.",
        "description": "Returns the students taught by the signed-in teacher, each as the portal's `StudentGet`: the\nperson, their composed status, what they are learning WITH YOU (their shared courses reduced to\nlanguage + level + course type), every course they are enrolled in, their pending course\ninvitations, their materials, their lessons with the recorded attendance, and the responsible\ncustomer's contact details.\n\nMembership is derived from the students' enrolments in the courses you are ASSIGNED to — as the\nmain teacher or as an additional one, the two count the same — and it is the ACCESS RULE, not a\nconvenience filter: no id is accepted for it and students of other teachers are never returned.\n\nFilter with `searchTerm` (student name, customer name, e-mail), `courseId`, `nativeLanguage`,\n`isChild` and `status`; soft-deleted entries are excluded unless you pass `showRemoved=true`.\nPaged and sorted through the usual `Range` / `orderBy` mechanism.\n\nNotes and exam records are deliberately NOT part of a row — they have their own routes, so a\nlist of students does not carry a page of notes nobody has opened.",
        "operationId": "GetTeacherMyStudents",
        "parameters": [
          {
            "name": "SearchTerm",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ShowRemoved",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "CourseId",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "NativeLanguage",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/NullableOfELanguage2"
            }
          },
          {
            "name": "IsChild",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/NullableOfEStudentStatus"
            }
          },
          {
            "name": "CustomerId",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "LearningLanguage",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/NullableOfELanguage2"
            }
          },
          {
            "name": "LearningLevel",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/NullableOfETeachingLevel2"
            }
          },
          {
            "name": "AgeFrom",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "AgeTo",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "Range",
            "in": "header",
            "description": "Pagination window (zero-based, end inclusive): `{start}-{end}` e.g. `0-49`; `-{n}` = last n; `{n}` = first n. When set, the response is 206 with a `Content-Range` header.",
            "schema": {
              "type": "string",
              "example": "0-49"
            }
          },
          {
            "name": "orderBy",
            "in": "query",
            "description": "Sort by this result property name (case-insensitive). Unknown property → 400.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "desc",
            "in": "query",
            "description": "Sort descending when true (default false). Applied before pagination.",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/StudentGet"
                  }
                }
              }
            }
          },
          "206": {
            "description": "Partial Content — returned when a `Range` header is present. Body is the requested window.",
            "headers": {
              "Content-Range": {
                "description": "`items {start}-{end}/{total}` (empty page → `items */{total}`).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/StudentGet"
                  }
                }
              }
            }
          },
          "416": {
            "description": "Range Not Satisfiable — the `Range` header is malformed or starts beyond the last item."
          }
        }
      }
    },
    "/teacher/my-students/{id}": {
      "get": {
        "tags": [
          "Student (Teacher)"
        ],
        "summary": "One of the signed-in teacher's students, in the teacher portal's shape.",
        "description": "Returns one student as the portal's `StudentGet`. Ownership is confirmed by MEMBERSHIP in the\nteacher's own scoped set, so a student the teacher does not teach answers `404` — never `403`,\nwhich would confirm that the person exists.",
        "operationId": "GetTeacherMyStudentById",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StudentGet"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/teacher/student-notes": {
      "get": {
        "tags": [
          "Student Notes (Teacher)"
        ],
        "summary": "The notes on one of the signed-in teacher's students.",
        "description": "Returns the notes on ONE student — `studentId` is required, because a note is an owned row of a\nstudent and the permission question is about that student.\n\n**Every note on the student**, not only your own — the office's and every other teacher's. One\nstudent has one set of notes (merged 2026-08-24); the sheet says as much under its input box.\nDeleting stays restricted to the author, which is what `isMine` on each row is for.\n\n`404` when the student is not one of yours. Filter with `searchTerm` and `authorId`.",
        "operationId": "GetTeacherStudentNotes",
        "parameters": [
          {
            "name": "SearchTerm",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ShowRemoved",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "StudentId",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "AuthorId",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Range",
            "in": "header",
            "description": "Pagination window (zero-based, end inclusive): `{start}-{end}` e.g. `0-49`; `-{n}` = last n; `{n}` = first n. When set, the response is 206 with a `Content-Range` header.",
            "schema": {
              "type": "string",
              "example": "0-49"
            }
          },
          {
            "name": "orderBy",
            "in": "query",
            "description": "Sort by this result property name (case-insensitive). Unknown property → 400.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "desc",
            "in": "query",
            "description": "Sort descending when true (default false). Applied before pagination.",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/StudentNoteGet"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "206": {
            "description": "Partial Content — returned when a `Range` header is present. Body is the requested window.",
            "headers": {
              "Content-Range": {
                "description": "`items {start}-{end}/{total}` (empty page → `items */{total}`).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/StudentNoteGet"
                  }
                }
              }
            }
          },
          "416": {
            "description": "Range Not Satisfiable — the `Range` header is malformed or starts beyond the last item."
          }
        }
      },
      "post": {
        "tags": [
          "Student Notes (Teacher)"
        ],
        "summary": "Add a note to one of the signed-in teacher's students.",
        "description": "Adds a note authored by the signed-in teacher. The author is taken from the session and is never\nread from the body. Returns the created note, `400` on validation errors, `404` when the student\nis not one of yours.",
        "operationId": "CreateTeacherStudentNote",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StudentNotePost"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StudentNoteGet"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpValidationProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/teacher/student-notes/{id}": {
      "delete": {
        "tags": [
          "Student Notes (Teacher)"
        ],
        "summary": "Remove a note from one of the signed-in teacher's students.",
        "description": "Removes the note. `404` when the note does not exist, is already removed, or belongs to a\nstudent who is not yours — the same answer for all three, so the response never confirms that a\nnote exists.\n\n**Only the author may remove a note.** A note by a colleague or by the office is readable (one\nstudent has one set of notes) and answers `403` on a delete. The office itself may remove any.\n\nA note is not editable, here or anywhere: it is a dated remark by a named person, and rewriting\none would change what was said without changing when it was said.",
        "operationId": "DeleteTeacherStudentNote",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/teacher/exam-records": {
      "get": {
        "tags": [
          "Exam Records (Teacher)"
        ],
        "summary": "The exam records of one of the signed-in teacher's students.",
        "description": "Returns the exam records of ONE student — `studentId` is required, for the same reason as with\nthe notes. Unlike a note, an exam record is not private to its author: it is the student's\nrecord and every teacher of theirs sees it.\n\nFilter with `searchTerm`, `examDateFrom`/`examDateTo` and `isPending` (no result recorded yet).\n`404` when the student is not one of yours.",
        "operationId": "GetTeacherExamRecords",
        "parameters": [
          {
            "name": "SearchTerm",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ShowRemoved",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "StudentId",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "ExamDateFrom",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "ExamDateTo",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "IsPending",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Range",
            "in": "header",
            "description": "Pagination window (zero-based, end inclusive): `{start}-{end}` e.g. `0-49`; `-{n}` = last n; `{n}` = first n. When set, the response is 206 with a `Content-Range` header.",
            "schema": {
              "type": "string",
              "example": "0-49"
            }
          },
          {
            "name": "orderBy",
            "in": "query",
            "description": "Sort by this result property name (case-insensitive). Unknown property → 400.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "desc",
            "in": "query",
            "description": "Sort descending when true (default false). Applied before pagination.",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ExamRecordGet"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "206": {
            "description": "Partial Content — returned when a `Range` header is present. Body is the requested window.",
            "headers": {
              "Content-Range": {
                "description": "`items {start}-{end}/{total}` (empty page → `items */{total}`).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ExamRecordGet"
                  }
                }
              }
            }
          },
          "416": {
            "description": "Range Not Satisfiable — the `Range` header is malformed or starts beyond the last item."
          }
        }
      },
      "post": {
        "tags": [
          "Exam Records (Teacher)"
        ],
        "summary": "Record an exam for one of the signed-in teacher's students.",
        "operationId": "CreateTeacherExamRecord",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ExamRecordPost"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExamRecordGet"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpValidationProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/teacher/exam-records/{id}": {
      "patch": {
        "tags": [
          "Exam Records (Teacher)"
        ],
        "summary": "Correct an exam record — typically to fill in the result once it is known.",
        "description": "Partially updates the record. `removeResult` clears a result that was recorded by mistake; a\nnull `result` alone means \"not part of this patch\", the Remove-flag convention this solution\nuses throughout. `404` when the record does not exist or belongs to a student who is not yours.",
        "operationId": "UpdateTeacherExamRecord",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ExamRecordPatch"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExamRecordGet"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpValidationProblemDetails"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Exam Records (Teacher)"
        ],
        "summary": "Remove an exam record from one of the signed-in teacher's students.",
        "operationId": "DeleteTeacherExamRecord",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/teacher/my-courses": {
      "get": {
        "tags": [
          "Course (Teacher)"
        ],
        "summary": "List the courses the signed-in teacher is assigned to, in the teacher portal's shape.",
        "description": "Returns every course the signed-in teacher is on — as its MAIN teacher or as an additional one,\nthe two count the same — each as the portal's `CourseGet`: name, type, language, level, status,\nthe weekly schedule, the room, the whole teaching team, the enrolled class, the students who were\ninvited and have not answered, the required materials and the total number of lessons.\n\nAssignment is the ACCESS RULE, not a convenience filter: no teacher id is accepted for it and\nother people's courses are never returned. A DRAFT course is excluded — it is still being put\ntogether and belongs to the office until it is not a draft any more.\n\nFilter with `searchTerm` (name, description, language, level), `status`, `courseType` and\n`hideFinished` (a course whose end date is past; an OPEN-ENDED course has never ended and always\nsurvives the toggle). Soft-deleted entries are excluded unless you pass `showRemoved=true`. Paged\nand sorted through the usual `Range` / `orderBy` mechanism.\n\n`totalLessonCount` is the course's whole run and is deliberately NOT the length of `lessons` —\nthat collection is the register the sheet lists, which is a fraction of the total.",
        "operationId": "GetTeacherMyCourses",
        "parameters": [
          {
            "name": "SearchTerm",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ShowRemoved",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "HideFinished",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/NullableOfECourseStatus"
            }
          },
          {
            "name": "CourseType",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/NullableOfECourseType"
            }
          },
          {
            "name": "Range",
            "in": "header",
            "description": "Pagination window (zero-based, end inclusive): `{start}-{end}` e.g. `0-49`; `-{n}` = last n; `{n}` = first n. When set, the response is 206 with a `Content-Range` header.",
            "schema": {
              "type": "string",
              "example": "0-49"
            }
          },
          {
            "name": "orderBy",
            "in": "query",
            "description": "Sort by this result property name (case-insensitive). Unknown property → 400.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "desc",
            "in": "query",
            "description": "Sort descending when true (default false). Applied before pagination.",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/CourseGet"
                  }
                }
              }
            }
          },
          "206": {
            "description": "Partial Content — returned when a `Range` header is present. Body is the requested window.",
            "headers": {
              "Content-Range": {
                "description": "`items {start}-{end}/{total}` (empty page → `items */{total}`).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/CourseGet"
                  }
                }
              }
            }
          },
          "416": {
            "description": "Range Not Satisfiable — the `Range` header is malformed or starts beyond the last item."
          }
        }
      }
    },
    "/teacher/my-courses/{id}": {
      "get": {
        "tags": [
          "Course (Teacher)"
        ],
        "summary": "One of the signed-in teacher's courses, in the teacher portal's shape.",
        "description": "Returns one course as the portal's `CourseGet` — the course sheet. A course the teacher is not\nassigned to (and a draft) answers `404`, never `403`: the access rule is row ownership, and a\n`403` would confirm that the course exists.",
        "operationId": "GetTeacherMyCourseById",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CourseGet"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/teacher/lessons": {
      "get": {
        "tags": [
          "Lesson (Teacher)"
        ],
        "summary": "The signed-in teacher's schedule, in the teacher portal's shape.",
        "description": "Returns every lesson of every course the signed-in teacher is assigned to — as its main teacher\nor as an additional one — including the lessons a COLLEAGUE holds, which is what makes a shared\ncourse's timetable readable. `isMine` says which is which; a colleague's row carries no\ncompensation at all (`teachingSalary`, `travelAllowance` and `additionalTravelCost` are null),\nand `isTakeable` says whether it may be picked up.\n\nLessons of a DRAFT course are excluded — a draft is the office's working copy.\n\nFilter with `searchTerm` (homework description, course name), `courseId`, `status`\n(Scheduled / InProgress / Completed / Cancelled — derived from the date, the time and the\ncancellation flag, and reproduced in SQL so paging stays exact), `attendanceState`\n(Recorded / Missing / NotApplicable), `dateFrom` / `dateTo`, `hideCancelled` and `isMine`.\nSoft-deleted entries are excluded unless you pass `showRemoved=true`. Paged and sorted through\nthe usual `Range` / `orderBy` mechanism.\n\n`conflictsWith` lists the reader's OWN overlapping lessons and is computed only for their own\nrows — a colleague's timetable is not disclosed. It is a warning, never a block, and it counts\nthe whole day rather than the current page, so a clash with a lesson the filter hides still\nshows up.",
        "operationId": "GetTeacherLessons",
        "parameters": [
          {
            "name": "SearchTerm",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ShowRemoved",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "CourseId",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/NullableOfELessonStatus"
            }
          },
          {
            "name": "AttendanceState",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/NullableOfELessonAttendanceState"
            }
          },
          {
            "name": "DateFrom",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "DateTo",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "HideCancelled",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "IsMine",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Range",
            "in": "header",
            "description": "Pagination window (zero-based, end inclusive): `{start}-{end}` e.g. `0-49`; `-{n}` = last n; `{n}` = first n. When set, the response is 206 with a `Content-Range` header.",
            "schema": {
              "type": "string",
              "example": "0-49"
            }
          },
          {
            "name": "orderBy",
            "in": "query",
            "description": "Sort by this result property name (case-insensitive). Unknown property → 400.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "desc",
            "in": "query",
            "description": "Sort descending when true (default false). Applied before pagination.",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/LessonGet"
                  }
                }
              }
            }
          },
          "206": {
            "description": "Partial Content — returned when a `Range` header is present. Body is the requested window.",
            "headers": {
              "Content-Range": {
                "description": "`items {start}-{end}/{total}` (empty page → `items */{total}`).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/LessonGet"
                  }
                }
              }
            }
          },
          "416": {
            "description": "Range Not Satisfiable — the `Range` header is malformed or starts beyond the last item."
          }
        }
      },
      "post": {
        "tags": [
          "Lesson (Teacher)"
        ],
        "summary": "Schedule a lesson on one of the signed-in teacher's courses.",
        "description": "Creates a lesson. Course and date/time are required; the room, the holding teacher, the\ngrammar/topic, the notes and any claimed travel cost may travel with the same request — one\ncall either writes the lesson the form describes or writes nothing.\n\nLeave `roomId` unset to keep the COURSE's room: unset means \"wherever the course takes place\",\nso the lesson follows a later change of that room instead of freezing today's answer. Leave\n`teacherId` unset to hold the lesson yourself.\n\n`400` when the course is not one you teach, when you have been deactivated as its co-teacher,\nwhen the named teacher is not an active teacher of that course, when the course is cancelled,\nor when a fide-test course already has its one examination.",
        "operationId": "CreateTeacherLesson",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LessonPost"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LessonGet"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpValidationProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/teacher/lessons/{id}": {
      "get": {
        "tags": [
          "Lesson (Teacher)"
        ],
        "summary": "One lesson of the signed-in teacher's courses, in the teacher portal's shape.",
        "description": "Returns one lesson as the portal's `LessonGet` — the lesson sheet. A lesson outside the\nteacher's courses answers `404`, never `403`: the access rule is row ownership, and a `403`\nwould confirm that the lesson exists.",
        "operationId": "GetTeacherLessonById",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LessonGet"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Lesson (Teacher)"
        ],
        "summary": "Change one of the signed-in teacher's lessons, or hand it to a colleague.",
        "description": "Updates a lesson: its date and time, its room, its documentation, the travel cost claimed for\nit, its attendance records, and who holds it. A null field means \"not part of this patch\"; the\n`remove…` flags are how a value is cleared.\n\nOrdinarily only the teacher HOLDING the lesson — or the course's main teacher — may change it;\nanything else is `403`, not `404`, because the lesson is legitimately in their own list.\n\n**Taking a colleague's lesson over** is a `PATCH` that changes NOTHING BUT `teacherId`. Any ACTIVE\nteacher of the course may do it, which is wider than the ordinary write gate — a take-over is by\ndefinition a change to a lesson you do not hold. The same patch carrying anything else (attendance,\ntimes, notes) is refused as a whole with `403`, so the wider permission can never become a way into a\ncolleague's lesson content. `isTakeable` on the read side says when the portal may offer it.\n\nCancelling is not possible here: it needs a reason, and the reason decides who is paid, so it\nbelongs to the office. `400` for a room or teacher that cannot be assigned, or for an\nattendance record naming a student who is not enrolled.",
        "operationId": "UpdateTeacherLesson",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LessonPatch"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LessonGet"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpValidationProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Lesson (Teacher)"
        ],
        "summary": "Remove one of the signed-in teacher's lessons.",
        "description": "Soft-deletes the lesson — it leaves the schedule but is not destroyed. Permanent deletion is\noffice-only (it needs the `hard-delete` realm role), so this route offers no `hard` flag at\nall rather than an affordance that always fails.\n\n`204` on success, `404` when the lesson is not in the teacher's scope, `403` when it belongs to\na colleague.",
        "operationId": "DeleteTeacherLesson",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/teacher/room-availability": {
      "get": {
        "tags": [
          "Room Availability (Teacher)"
        ],
        "summary": "Which rooms are free on a day, in a window.",
        "description": "Returns every room of the school, grouped by site, each with its operational state and — when\nsomething holds it during the requested window — the time it frees up again\n(`occupiedUntil`). `isAvailable` combines the two, so \"taken\" and \"out of service\" cannot be\nhandled inconsistently: they differ in the reason shown, never in whether the room may be\npicked.\n\n**A teacher is told THAT a room is taken and until when, never by whom or for what.** Every\nsource of occupancy — their own lessons, colleagues' lessons, anything else on the calendar —\nis flattened into that one time, so not even the shape of the answer hints at which kind it\nwas. There is deliberately no course, lesson, teacher or student anywhere in the response.\n\nA lesson with no room of its own is held wherever its COURSE takes place, and that counts:\nunset means \"the course's room\", not \"no room\". A lesson of a DRAFT course occupies too — a\ndraft is invisible everywhere else in the portal, but a room is physical, and excluding it\nwould let two things land in the same room the moment the course goes live. A CANCELLED lesson\nholds nothing.\n\nPass `exceptLessonId` when editing a lesson, or it reports its own room as taken and the\npicker refuses the room the lesson is already in. Touching ends (`09:00-11:00` next to\n`11:00-12:00`) are two consecutive lessons, not a collision.\n\n`400` when the window is empty or inverted — `to` must be after `from`.",
        "operationId": "GetTeacherRoomAvailability",
        "parameters": [
          {
            "name": "Date",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "From",
            "in": "query",
            "required": true,
            "schema": {
              "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
              "type": "string"
            }
          },
          {
            "name": "To",
            "in": "query",
            "required": true,
            "schema": {
              "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
              "type": "string"
            }
          },
          {
            "name": "ExceptLessonId",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoomAvailabilityResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpValidationProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/teacher/dashboard": {
      "get": {
        "tags": [
          "Dashboard (Teacher)"
        ],
        "summary": "The signed-in teacher's Today view, as one snapshot.",
        "description": "Returns the whole Today view in one call: the day it was computed for, today's schedule, the\nabsences reported for today, the four KPI figures and the two nav-badge counts.\n\n**Every number that can be read off a list in this payload IS read off it** — `lessonsToday`,\n`absencesToday` and `nextLesson` are computed properties, so a tile can never contradict the\nlist underneath it. Only the figures that are genuinely not in the payload are stored fields.\n\n`date` is the SERVER's today, sent explicitly: every count was computed against it, and a\nclient on the other side of a date boundary would otherwise print a day that disagrees with the\nnumbers next to it.\n\n**Today's schedule holds more than the \"Lessons today\" tile counts.** A lesson a COLLEAGUE\nholds on a course you co-teach is on your day (`isMine: false`) but is not a lesson you give,\nso the tile counts only your own, uncancelled ones.\n\n`attendancesMissingCount` counts ALL of your lessons that have taken place without their\nattendance being recorded, not just today's — an affected lesson can be weeks old and is then\non no day's schedule, which is the whole reason the badge exists. A lesson still to come is\nnever counted: there is nothing to record yet.\n\n`pendingInviteCount` (the Opportunities badge) and `openApplicationCount` (the KPI tile) are\ntwo different figures and not a duplication: the badge counts course INVITATIONS waiting for\nyour answer, the tile counts open student REQUESTS you could apply to.",
        "operationId": "GetTeacherDashboard",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeacherDashboardGet"
                }
              }
            }
          }
        }
      }
    },
    "/teacher/my-invites": {
      "get": {
        "tags": [
          "Opportunities (Teacher)"
        ],
        "summary": "Course invitations addressed to the signed-in teacher.",
        "description": "Every invitation the office has sent this teacher, answered ones included — the portal shows\nthe history next to what is still open. Filter with `openOnly` for the pending ones,\n`status`, `courseId`, `searchTerm`, and `coursePlanned`.\n\n**Two fields exist to make the decision, and neither is on the office contract.**\n`coursePlanned` says whether the course has any lessons at all yet: an invitation accepted for\na course whose calendar is still empty is a different state from one that is scheduled, and\nthe portal shows it as such. `slotsOutsideAvailability` lists the course's weekly slots that\nfall OUTSIDE the windows the teacher stated in their profile — fully outside is not the test,\nfully INSIDE is: a course running 09:00-12:00 against an availability of 09:00-10:00 is not\nsomething they said they could do. `fitsAvailability` is simply that list being empty.\n\n`coursePlanned` as a FILTER is applied after the page is read, because it is computed rather\nthan stored — the only criterion here that is not answered in SQL.",
        "operationId": "GetTeacherInvites",
        "parameters": [
          {
            "name": "SearchTerm",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ShowRemoved",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/NullableOfEInviteStatus2"
            }
          },
          {
            "name": "OpenOnly",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "CoursePlanned",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "CourseId",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "RoomId",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Range",
            "in": "header",
            "description": "Pagination window (zero-based, end inclusive): `{start}-{end}` e.g. `0-49`; `-{n}` = last n; `{n}` = first n. When set, the response is 206 with a `Content-Range` header.",
            "schema": {
              "type": "string",
              "example": "0-49"
            }
          },
          {
            "name": "orderBy",
            "in": "query",
            "description": "Sort by this result property name (case-insensitive). Unknown property → 400.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "desc",
            "in": "query",
            "description": "Sort descending when true (default false). Applied before pagination.",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TeacherInviteGet"
                  }
                }
              }
            }
          },
          "206": {
            "description": "Partial Content — returned when a `Range` header is present. Body is the requested window.",
            "headers": {
              "Content-Range": {
                "description": "`items {start}-{end}/{total}` (empty page → `items */{total}`).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TeacherInviteGet"
                  }
                }
              }
            }
          },
          "416": {
            "description": "Range Not Satisfiable — the `Range` header is malformed or starts beyond the last item."
          }
        }
      }
    },
    "/teacher/my-invites/{id}": {
      "patch": {
        "tags": [
          "Opportunities (Teacher)"
        ],
        "summary": "Accept or decline a course invitation.",
        "description": "The teacher's answer: `status` must be `Accepted` or `Denied` — `Pending` is a state the\noffice puts an invitation in, never an answer, and it is refused rather than ignored.\n\n`denyReason` (max 200 chars) may accompany a DECLINE and is refused alongside an acceptance:\nthe office reads it as the ground for a refusal, and there is no refusal on an accepted\ninvitation. It is stored and read by the office; the teacher does not get it back.\n\nWhen the answer was given is stamped by the server. An invitation addressed to another\nteacher answers `404` — the access rule is row ownership, and a `403` would confirm it exists.",
        "operationId": "AnswerTeacherInvite",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TeacherInvitePatch"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeacherInviteGet"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpValidationProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/teacher/my-applications": {
      "get": {
        "tags": [
          "Opportunities (Teacher)"
        ],
        "summary": "Open student requests matching the signed-in teacher's qualifications.",
        "description": "The requests this teacher could take on, each with the reader's own application when they have\nalready applied (`myApplication`) and how many teachers have applied in total\n(`applicantCount`).\n\n**The requesting party is anonymised** and stays so until the office assigns the teacher to\nthe student's course: no requesting customer, no preferred address, no student name. What\nremains is what the decision needs — language, level, interest type, period, frequency, the\ntime windows, the notes, and the student's age, whether they are a child, and their native\nlanguage.\n\n**`myApplication.proposedTimeSlots[].conflictLabel`** names the reader's OWN lesson that\ncollides with a proposed window, inside the period the request runs over. Only their own: a\ncolleague being busy is no reason not to apply, and naming their lesson would disclose their\ntimetable. Absent means no collision, which is what `hasSlotConflict` reads off.\n\nFilter with `searchTerm` (language and level — deliberately NOT the student name),\n`language`, `level` and `interestType` in SQL; `hasMyApplication`, `isChild`,\n`preferredLocation`, `status` and the date range are applied to the page afterwards, because\nthe matching contract does not carry them.",
        "operationId": "GetTeacherRequests",
        "parameters": [
          {
            "name": "SearchTerm",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ShowRemoved",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Language",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/NullableOfELanguage2"
            }
          },
          {
            "name": "Level",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/NullableOfETeachingLevel2"
            }
          },
          {
            "name": "InterestType",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/NullableOfEInterestType"
            }
          },
          {
            "name": "Status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/NullableOfEInterestStatus"
            }
          },
          {
            "name": "PreferredLocation",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/NullableOfEPreferredLocation"
            }
          },
          {
            "name": "IsChild",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "HasMyApplication",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "DateFrom",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "DateTo",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "Range",
            "in": "header",
            "description": "Pagination window (zero-based, end inclusive): `{start}-{end}` e.g. `0-49`; `-{n}` = last n; `{n}` = first n. When set, the response is 206 with a `Content-Range` header.",
            "schema": {
              "type": "string",
              "example": "0-49"
            }
          },
          {
            "name": "orderBy",
            "in": "query",
            "description": "Sort by this result property name (case-insensitive). Unknown property → 400.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "desc",
            "in": "query",
            "description": "Sort descending when true (default false). Applied before pagination.",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/InterestGet"
                  }
                }
              }
            }
          },
          "206": {
            "description": "Partial Content — returned when a `Range` header is present. Body is the requested window.",
            "headers": {
              "Content-Range": {
                "description": "`items {start}-{end}/{total}` (empty page → `items */{total}`).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/InterestGet"
                  }
                }
              }
            }
          },
          "416": {
            "description": "Range Not Satisfiable — the `Range` header is malformed or starts beyond the last item."
          }
        }
      }
    },
    "/teacher/my-applications/{id}": {
      "patch": {
        "tags": [
          "Opportunities (Teacher)"
        ],
        "summary": "Apply to a student request, or withdraw an application.",
        "description": "`applicationToAdd` expresses interest with the time slots the teacher proposes;\n`applicationIdToWithdraw` takes an application back. One or the other — the portal never does\nboth in one request.\n\nThe applying teacher is the SIGNED-IN one and is never taken from the payload: applying on a\ncolleague's behalf is not something this portal does.",
        "operationId": "AnswerTeacherRequest",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InterestPatch"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InterestGet"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpValidationProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/teacher/expense-claims": {
      "get": {
        "tags": [
          "Expense Claims (Teacher)"
        ],
        "summary": "List the signed-in teacher's own expense claims.",
        "description": "Returns the claims the signed-in teacher has filed, each with both halves of the record: what\nthey wrote (date, claimed amount, reason, receipt) and what the office answered (status,\napproved amount, note). The claimed amount is never overwritten by the decision — seeing what\nwas asked for is the whole point when a different figure comes back.\n\nOwnership is the ACCESS RULE, not a filter: no teacher id is accepted and other people's claims\nare never returned.\n\nFilter with `searchTerm` (the reason and the office's note), `status`, `dateFrom`/`dateTo` (when\nthe cost was incurred), `settledPeriodYear`/`settledPeriodMonth` and `hasSettledPeriod`\n(which period settled it), `isSettled` (finished = on a payslip that has been paid out),\n`minClaimedAmount`/`maxClaimedAmount` and `hasReceipt`. Soft-deleted (withdrawn) claims are\nexcluded unless you pass `showRemoved=true`. Paged and sorted through the usual `Range` /\n`orderBy` mechanism.\n\nThe period is deliberately NOT derived from `date`: a receipt handed in after its month\nclosed is paid out with the following period, so the month a cost fell in and the month it is\npaid in are two different facts.",
        "operationId": "GetTeacherExpenseClaims",
        "parameters": [
          {
            "name": "SearchTerm",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ShowRemoved",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/NullableOfEExpenseClaimStatus"
            }
          },
          {
            "name": "DateFrom",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "DateTo",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "SettledPeriodYear",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "SettledPeriodMonth",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "HasSettledPeriod",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "IsSettled",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "MinClaimedAmount",
            "in": "query",
            "schema": {
              "type": "number",
              "format": "double"
            }
          },
          {
            "name": "MaxClaimedAmount",
            "in": "query",
            "schema": {
              "type": "number",
              "format": "double"
            }
          },
          {
            "name": "HasReceipt",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Range",
            "in": "header",
            "description": "Pagination window (zero-based, end inclusive): `{start}-{end}` e.g. `0-49`; `-{n}` = last n; `{n}` = first n. When set, the response is 206 with a `Content-Range` header.",
            "schema": {
              "type": "string",
              "example": "0-49"
            }
          },
          {
            "name": "orderBy",
            "in": "query",
            "description": "Sort by this result property name (case-insensitive). Unknown property → 400.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "desc",
            "in": "query",
            "description": "Sort descending when true (default false). Applied before pagination.",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ExpenseClaimGet"
                  }
                }
              }
            }
          },
          "206": {
            "description": "Partial Content — returned when a `Range` header is present. Body is the requested window.",
            "headers": {
              "Content-Range": {
                "description": "`items {start}-{end}/{total}` (empty page → `items */{total}`).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ExpenseClaimGet"
                  }
                }
              }
            }
          },
          "416": {
            "description": "Range Not Satisfiable — the `Range` header is malformed or starts beyond the last item."
          }
        }
      },
      "post": {
        "tags": [
          "Expense Claims (Teacher)"
        ],
        "summary": "File an expense claim.",
        "description": "Files a claim for the signed-in teacher. It starts as `Submitted` — there is no draft state: the\nclaim exists the moment it is handed in.\n\nThe date must not be in the future but is otherwise unrestricted; late is allowed and simply\npays out with the next period. The amount must be greater than zero and the reason is required\n(max 300 characters) — the office decides from it, so it has to name the reason and not just\nthe amount.\n\nA receipt is attached by its id: upload the photo FIRST via `POST\n/teacher/expense-claim-receipts` and reference it here. The claim does not exist yet\nwhile the teacher is taking the picture, which is why the two are separate steps.\n\n`400` when the payload is invalid, or when the signed-in account is not linked to a teacher\nrecord — the claim would then belong to nobody and be invisible the moment it was written.",
        "operationId": "CreateTeacherExpenseClaim",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ExpenseClaimPost"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExpenseClaimGet"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpValidationProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/teacher/expense-claims/{id}": {
      "get": {
        "tags": [
          "Expense Claims (Teacher)"
        ],
        "summary": "One of the signed-in teacher's own expense claims.",
        "description": "Returns one claim. A claim belonging to another teacher answers `404` — never `403`, which would\nconfirm that it exists.",
        "operationId": "GetTeacherExpenseClaimById",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExpenseClaimGet"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Expense Claims (Teacher)"
        ],
        "summary": "Correct one of the signed-in teacher's own expense claims.",
        "description": "Changes only what the teacher wrote: date, claimed amount, reason and the receipt. The status and\nthe office's decision are not on this contract at all.\n\nOnly while the claim is still `Submitted`. Once the office has approved, adjusted or rejected it,\nthe claim is the record of that answer and the request is refused with `409` — file a new claim,\nor ask the office to reopen this one.\n\n`removeReceiptDocument` detaches the current receipt; sending it together with a new\n`receiptDocumentId` is refused (`400`), because those are two opposite intents and whichever the\nserver picked would be a coin toss the teacher never sees.\n\n`404` for another teacher's claim.",
        "operationId": "UpdateTeacherExpenseClaim",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ExpenseClaimPatch"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExpenseClaimGet"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpValidationProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Expense Claims (Teacher)"
        ],
        "summary": "Withdraw one of the signed-in teacher's own expense claims.",
        "description": "Withdraws the claim (a soft delete). There is no separate \"withdrawn\" status — that would be the\nsame lifecycle axis under a second name, and the two would then be able to disagree.\n\nSame window as an edit: only while the claim is still `Submitted` (`409` otherwise). `404` for\nanother teacher's claim.",
        "operationId": "DeleteTeacherExpenseClaim",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/teacher/payslips": {
      "get": {
        "tags": [
          "Payslips (Teacher)"
        ],
        "summary": "List the signed-in teacher's own payslips, newest month first.",
        "description": "Returns one payslip per payroll period, each composed of:\n\n- the RATE GROUPS (lessons × hourly rate, the office's own breakdown) and the fixed base pay,\n- the BONUSES — the free positions the office put on the payment; they are compensation and sit\n  inside the gross,\n- the DEDUCTIONS (AHV/IV/EO, ALV, KTG, NBU) as stored figures, plus BVG and withholding tax,\n- what is paid ON TOP of the net: the travel allowance per lesson, the expense claims this\n  period pays, and the child allowances.\n\nBVG is only DUE in the period it falls in: with a monthly contribution that is every payslip,\nwith an annual one only the month named by `bvgMonth`. Every other payslip of the year reports\nthe amount but nothing due.\n\nThe expense claims listed are the ones assigned to THIS payout period and decided to pay\nsomething (approved or adjusted). A claim still awaiting a decision has no amount yet, and a\nrejected one pays nothing — neither belongs on a payslip.\n\nOwnership is the ACCESS RULE: no teacher id is accepted and other people's payslips are never\nreturned.\n\nFilter by `periodFrom` / `periodTo`, which narrow in the database. `minPayout` / `maxPayout`\nand `searchTerm` are applied AFTER the payslips are composed — deliberately, and worth knowing:\nthe payout is built from five parts, several of which are not columns of the payment at all, so\nthere is nothing for the database to compare. Combining them with paging is therefore not\nexact; narrow by period first.",
        "operationId": "GetTeacherPayslips",
        "parameters": [
          {
            "name": "SearchTerm",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ShowRemoved",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "PeriodFrom",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "PeriodTo",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "MinPayout",
            "in": "query",
            "schema": {
              "type": "number",
              "format": "double"
            }
          },
          {
            "name": "MaxPayout",
            "in": "query",
            "schema": {
              "type": "number",
              "format": "double"
            }
          },
          {
            "name": "Range",
            "in": "header",
            "description": "Pagination window (zero-based, end inclusive): `{start}-{end}` e.g. `0-49`; `-{n}` = last n; `{n}` = first n. When set, the response is 206 with a `Content-Range` header.",
            "schema": {
              "type": "string",
              "example": "0-49"
            }
          },
          {
            "name": "orderBy",
            "in": "query",
            "description": "Sort by this result property name (case-insensitive). Unknown property → 400.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "desc",
            "in": "query",
            "description": "Sort descending when true (default false). Applied before pagination.",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TeacherPayslipGet"
                  }
                }
              }
            }
          },
          "206": {
            "description": "Partial Content — returned when a `Range` header is present. Body is the requested window.",
            "headers": {
              "Content-Range": {
                "description": "`items {start}-{end}/{total}` (empty page → `items */{total}`).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TeacherPayslipGet"
                  }
                }
              }
            }
          },
          "416": {
            "description": "Range Not Satisfiable — the `Range` header is malformed or starts beyond the last item."
          }
        }
      }
    },
    "/teacher/payslips/{id}": {
      "get": {
        "tags": [
          "Payslips (Teacher)"
        ],
        "summary": "One of the signed-in teacher's own payslips.",
        "description": "Returns one payslip. Another teacher's answers `404` — never `403`, which would confirm that it\nexists and that somebody was paid that month.",
        "operationId": "GetTeacherPayslipById",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeacherPayslipGet"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/teacher/expense-claim-receipts": {
      "post": {
        "tags": [
          "Expense Receipts (Teacher)"
        ],
        "summary": "Upload a receipt for an expense claim.",
        "description": "Stores the file and returns its id, which is then put on the claim as `receiptDocumentId`. Upload\nFIRST and reference afterwards: the claim usually does not exist yet while the photo is being\ntaken, so requiring it here would make the normal case impossible.\n\nPDF, JPEG or PNG, up to 10 MB. An empty file, an oversized one or another type is refused with\n`400` and a readable message — the size is checked BEFORE the request is read into memory, or the\ncap would only take effect once the whole thing had already been buffered.\n\nAn upload that never ends up on a claim is discarded by the portal when the sheet is abandoned,\nand swept nightly if that call is lost.",
        "operationId": "UploadTeacherExpenseReceipt",
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "required": [
                  "file"
                ],
                "type": "object",
                "properties": {
                  "file": {
                    "$ref": "#/components/schemas/IFormFile"
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UploadedExpenseReceipt"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/teacher/expense-claim-receipts/{id}": {
      "get": {
        "tags": [
          "Expense Receipts (Teacher)"
        ],
        "summary": "Download a receipt of one of the signed-in teacher's own claims.",
        "description": "Streams the stored file under the name it was uploaded with.\n\nReadable are the receipts of the teacher's OWN claims, plus their own upload that is not on a\nclaim yet — otherwise the sheet could not show back the photo it has just taken. Anything else\nanswers `404`, never `403`: a 403 would confirm the receipt exists.",
        "operationId": "DownloadTeacherExpenseReceipt",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Expense Receipts (Teacher)"
        ],
        "summary": "Discard an uploaded receipt that was never put on a claim.",
        "description": "Removes an upload the teacher made and then abandoned.\n\nRefuses — with `404` — a receipt that is ATTACHED to a claim, and one uploaded by somebody else.\nThat is what keeps this from being turned against a filed claim: the only thing it can remove is\na file that hangs off nothing and that the caller uploaded themselves.",
        "operationId": "DiscardTeacherExpenseReceipt",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/teacher/homeworks": {
      "get": {
        "tags": [
          "Homework (Teacher)"
        ],
        "summary": "List homeworks of the signed-in teacher's lessons.",
        "description": "Returns the homework of the signed-in teacher's own lessons, each as a `HomeworkGet` with the\ntask description, due date and the owning lesson/course context. Homework of other teachers'\nlessons is never returned. Soft-deleted entries are excluded unless you pass `showRemoved=true`.\nFilter with `searchTerm` (matches the description) and `lessonId` to narrow to a single lesson.\nResults are ordered by due date.\n\nSupports pagination and sorting: send an optional `Range` request header (`0-49` = first 50,\n`-50` = last 50, `50` = from index 50; 0-based, end inclusive) plus the `orderBy` (a property\nname of the returned object, case-insensitive) and `desc` query parameters. The body is a\nplain JSON array; the total count is returned in the `Content-Range` response header\n(`items {start}-{end}/{total}`). Status is `206` when a `Range` is sent, `416` if the range\nis invalid.",
        "operationId": "GetHomeworksTeacher",
        "parameters": [
          {
            "name": "SearchTerm",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ShowRemoved",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "LessonId",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "DueFrom",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "DueTo",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "Range",
            "in": "header",
            "description": "Pagination window (zero-based, end inclusive): `{start}-{end}` e.g. `0-49`; `-{n}` = last n; `{n}` = first n. When set, the response is 206 with a `Content-Range` header.",
            "schema": {
              "type": "string",
              "example": "0-49"
            }
          },
          {
            "name": "orderBy",
            "in": "query",
            "description": "Sort by this result property name (case-insensitive). Unknown property → 400.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "desc",
            "in": "query",
            "description": "Sort descending when true (default false). Applied before pagination.",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/HomeworkGet"
                  }
                }
              }
            }
          },
          "206": {
            "description": "Partial Content — returned when a `Range` header is present. Body is the requested window.",
            "headers": {
              "Content-Range": {
                "description": "`items {start}-{end}/{total}` (empty page → `items */{total}`).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/HomeworkGet"
                  }
                }
              }
            }
          },
          "416": {
            "description": "Range Not Satisfiable — the `Range` header is malformed or starts beyond the last item."
          }
        }
      },
      "post": {
        "tags": [
          "Homework (Teacher)"
        ],
        "summary": "Create a homework for one of the signed-in teacher's lessons.",
        "description": "Creates a homework for one of the signed-in teacher's lessons from the `HomeworkPost` body\n(target `lessonId`, description and due date) and returns the created `HomeworkGet` with its\ngenerated id. Returns `400` with validation details if the body is invalid, e.g. if the\nreferenced lesson is not one of your own.",
        "operationId": "CreateHomeworkTeacher",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/HomeworkPost"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HomeworkGet"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpValidationProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/teacher/homeworks/{id}": {
      "get": {
        "tags": [
          "Homework (Teacher)"
        ],
        "summary": "Get one of the signed-in teacher's homeworks by id.",
        "description": "Returns a single homework by its id as a `HomeworkGet`. Returns `404` if no such homework\nexists or if it does not belong to one of the signed-in teacher's lessons.",
        "operationId": "GetHomeworkTeacherById",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HomeworkGet"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Homework (Teacher)"
        ],
        "summary": "Partially update one of the signed-in teacher's homeworks.",
        "description": "Partially updates one of the signed-in teacher's homework assignments: only the fields present\nin the `HomeworkPatch` body (description, due date) are changed; the owning lesson cannot be\nreassigned. Returns the updated `HomeworkGet`, `400` on validation errors, or `404` if the\nhomework does not exist or is not on one of your own lessons.",
        "operationId": "UpdateHomeworkTeacher",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/HomeworkPatch"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HomeworkGet"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpValidationProblemDetails"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Homework (Teacher)"
        ],
        "summary": "Delete one of the signed-in teacher's homeworks (soft by default; ?hard=true to hard-delete).",
        "description": "Deletes one of the signed-in teacher's homework assignments. By default this is a soft delete\n— the homework is hidden from normal listings but can be restored; pass `?hard=true` to remove\nit permanently. Returns `204`, or `404` if the homework does not exist or is not on one of\nyour own lessons.",
        "operationId": "DeleteHomeworkTeacher",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "hard",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "AbsenceGet": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "startDate": {
            "type": "string",
            "format": "date"
          },
          "endDate": {
            "type": "string",
            "format": "date"
          },
          "reason": {
            "type": "string",
            "nullable": true
          },
          "dayCount": {
            "type": "integer",
            "format": "int32"
          },
          "conflictingLessonCount": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          }
        }
      },
      "AbsencePatch": {
        "type": "object",
        "properties": {
          "startDate": {
            "type": "string",
            "format": "date",
            "nullable": true
          },
          "endDate": {
            "type": "string",
            "format": "date",
            "nullable": true
          },
          "reason": {
            "type": "string",
            "nullable": true
          },
          "removeReason": {
            "type": "boolean"
          }
        }
      },
      "AbsencePatchWithId": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "patch": {
            "$ref": "#/components/schemas/AbsencePatch"
          }
        }
      },
      "AbsencePost": {
        "type": "object",
        "properties": {
          "startDate": {
            "type": "string",
            "format": "date"
          },
          "endDate": {
            "type": "string",
            "format": "date"
          },
          "reason": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "AddressInfoDto": {
        "type": "object",
        "properties": {
          "street": {
            "type": "string"
          },
          "houseNumber": {
            "type": "string",
            "nullable": true
          },
          "additionalLine": {
            "type": "string",
            "nullable": true
          },
          "postalCode": {
            "type": "string"
          },
          "city": {
            "type": "string"
          },
          "country": {
            "type": "string"
          },
          "poBox": {
            "type": "string",
            "nullable": true
          }
        },
        "nullable": true
      },
      "AttendanceRecordGet": {
        "type": "object",
        "properties": {
          "ownerRef": {
            "type": "string",
            "format": "uuid"
          },
          "ownerTypeName": {
            "type": "string"
          },
          "studentId": {
            "type": "string",
            "format": "uuid"
          },
          "student": {
            "$ref": "#/components/schemas/StudentRef2"
          },
          "status": {
            "$ref": "#/components/schemas/EnumDtoOfEAttendanceStatus2"
          },
          "absenceDocumentPath": {
            "type": "string",
            "nullable": true
          },
          "absenceDocumentId": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "absenceDocumentSizeBytes": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "AttendanceRecordPatch": {
        "type": "object",
        "properties": {
          "ownerRef": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "ownerTypeName": {
            "type": "string",
            "nullable": true
          },
          "studentId": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "statusId": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "absenceDocumentPath": {
            "type": "string",
            "nullable": true
          },
          "absenceDocumentId": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "removeAbsenceDocument": {
            "type": "boolean"
          },
          "removeAbsenceDocumentPath": {
            "type": "boolean"
          }
        }
      },
      "AttendanceRecordPatchWithId": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "patch": {
            "$ref": "#/components/schemas/AttendanceRecordPatch"
          }
        }
      },
      "AttendanceRecordPost": {
        "type": "object",
        "properties": {
          "ownerRef": {
            "type": "string",
            "format": "uuid"
          },
          "ownerTypeName": {
            "type": "string"
          },
          "studentId": {
            "type": "string",
            "format": "uuid"
          },
          "statusId": {
            "type": "string",
            "format": "uuid"
          },
          "absenceDocumentPath": {
            "type": "string",
            "nullable": true
          },
          "absenceDocumentId": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          }
        }
      },
      "ChildAllowanceGet": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "dateOfBirth": {
            "type": "string",
            "format": "date"
          },
          "entitledFrom": {
            "type": "string",
            "format": "date"
          },
          "entitledTo": {
            "type": "string",
            "format": "date",
            "nullable": true
          },
          "kind": {
            "$ref": "#/components/schemas/EnumDtoOfEChildAllowanceKind"
          },
          "monthlyAmount": {
            "type": "number",
            "format": "double"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "ChildAllowanceRef": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "kind": {
            "$ref": "#/components/schemas/EnumDtoOfEChildAllowanceKind"
          },
          "monthlyAmount": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "CompletedTrainingDto": {
        "type": "object",
        "properties": {
          "trainingCourseId": {
            "type": "string",
            "format": "uuid"
          },
          "trainingCourse": {
            "$ref": "#/components/schemas/TrainingCourseRef"
          },
          "completedAt": {
            "type": "string",
            "format": "date"
          }
        }
      },
      "CourseColorEnumDto": {
        "type": "object",
        "properties": {
          "propertyName": {
            "type": "string"
          },
          "value": {
            "type": "string"
          },
          "enumValue": {
            "$ref": "#/components/schemas/ECourseColor"
          },
          "displayName": {
            "type": "string"
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "CourseGet": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "courseType": {
            "$ref": "#/components/schemas/EnumDtoOfECourseType"
          },
          "subject": {
            "$ref": "#/components/schemas/EnumDtoOfELanguage"
          },
          "level": {
            "$ref": "#/components/schemas/EnumDtoOfETeachingLevel"
          },
          "status": {
            "$ref": "#/components/schemas/EnumDtoOfECourseStatus"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "isForChildren": {
            "type": "boolean"
          },
          "startDate": {
            "type": "string",
            "format": "date"
          },
          "endDate": {
            "type": "string",
            "format": "date",
            "nullable": true
          },
          "weeklySchedule": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WeeklyScheduleSlotDto"
            }
          },
          "totalLessonCount": {
            "type": "integer",
            "format": "int32"
          },
          "roomId": {
            "type": "string",
            "format": "uuid"
          },
          "room": {
            "$ref": "#/components/schemas/RoomRef"
          },
          "mainTeacherId": {
            "type": "string",
            "format": "uuid"
          },
          "teachers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TeacherRef2"
            }
          },
          "isDeactivatedForMe": {
            "type": "boolean"
          },
          "deactivatedForMeAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "students": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StudentRef"
            }
          },
          "invitedStudents": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/InvitedStudentDto"
            }
          },
          "maxStudents": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "capacity": {
            "$ref": "#/components/schemas/EnumDtoOfECourseCapacity"
          },
          "requiredMaterials": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MaterialRef"
            }
          },
          "lessons": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LessonRef"
            },
            "nullable": true
          },
          "displayName": {
            "type": "string",
            "nullable": true
          },
          "studentCount": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "CourseRef": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "courseType": {
            "$ref": "#/components/schemas/EnumDtoOfECourseType"
          },
          "name": {
            "type": "string"
          },
          "displayName": {
            "type": "string",
            "nullable": true
          },
          "subject": {
            "$ref": "#/components/schemas/EnumDtoOfELanguage"
          },
          "level": {
            "$ref": "#/components/schemas/EnumDtoOfETeachingLevel"
          },
          "status": {
            "$ref": "#/components/schemas/EnumDtoOfECourseStatus"
          },
          "color": {
            "$ref": "#/components/schemas/CourseColorEnumDto"
          },
          "teacher": {
            "$ref": "#/components/schemas/TeacherRef"
          },
          "price": {
            "type": "number",
            "format": "double"
          },
          "roomId": {
            "type": "string",
            "format": "uuid"
          },
          "startDate": {
            "type": "string",
            "format": "date-time"
          },
          "endDate": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "weeklySchedule": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WeeklyScheduleSlotDto"
            }
          }
        }
      },
      "CourseRef2": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "courseType": { },
          "name": {
            "type": "string"
          },
          "displayName": {
            "type": "string",
            "nullable": true
          },
          "subject": { },
          "level": { },
          "status": { },
          "color": { },
          "teacher": {
            "nullable": true
          },
          "price": {
            "type": "number",
            "format": "double"
          },
          "roomId": {
            "type": "string",
            "format": "uuid"
          },
          "startDate": {
            "type": "string",
            "format": "date-time"
          },
          "endDate": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "weeklySchedule": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WeeklyScheduleSlotDto"
            }
          }
        },
        "nullable": true
      },
      "CustomerRef": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "displayName": {
            "type": "string"
          },
          "customerType": {
            "$ref": "#/components/schemas/EnumDtoOfECustomerType"
          },
          "isActive": {
            "type": "boolean"
          },
          "address": {
            "$ref": "#/components/schemas/AddressInfoDto"
          }
        },
        "nullable": true
      },
      "DashboardAbsenceRow": {
        "type": "object",
        "properties": {
          "studentName": {
            "type": "string"
          },
          "courseName": {
            "type": "string"
          },
          "lessonStartTime": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string"
          },
          "lessonEndTime": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/EnumDtoOfEAttendanceStatus2"
          },
          "hasDocument": {
            "type": "boolean"
          }
        }
      },
      "DashboardLessonRow": {
        "type": "object",
        "properties": {
          "lessonId": {
            "type": "string",
            "format": "uuid"
          },
          "courseName": {
            "type": "string"
          },
          "courseType": {
            "$ref": "#/components/schemas/EnumDtoOfECourseType"
          },
          "subject": {
            "$ref": "#/components/schemas/EnumDtoOfELanguage"
          },
          "level": {
            "$ref": "#/components/schemas/EnumDtoOfETeachingLevel"
          },
          "date": {
            "type": "string",
            "format": "date"
          },
          "startTime": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string"
          },
          "endTime": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string"
          },
          "roomName": {
            "type": "string"
          },
          "studentCount": {
            "type": "integer",
            "format": "int32"
          },
          "absenceCount": {
            "type": "integer",
            "format": "int32"
          },
          "status": {
            "$ref": "#/components/schemas/EnumDtoOfELessonStatus"
          },
          "isCancelled": {
            "type": "boolean"
          },
          "attendanceState": {
            "$ref": "#/components/schemas/EnumDtoOfELessonAttendanceState"
          },
          "isMine": {
            "type": "boolean"
          },
          "heldByTeacherName": {
            "type": "string",
            "nullable": true
          },
          "isNext": {
            "type": "boolean"
          },
          "minutesUntilStart": {
            "type": "integer",
            "format": "int32"
          }
        },
        "nullable": true
      },
      "DashboardLessonRow2": {
        "type": "object",
        "properties": {
          "lessonId": {
            "type": "string",
            "format": "uuid"
          },
          "courseName": {
            "type": "string"
          },
          "courseType": { },
          "subject": { },
          "level": { },
          "date": {
            "type": "string",
            "format": "date"
          },
          "startTime": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string"
          },
          "endTime": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string"
          },
          "roomName": {
            "type": "string"
          },
          "studentCount": {
            "type": "integer",
            "format": "int32"
          },
          "absenceCount": {
            "type": "integer",
            "format": "int32"
          },
          "status": { },
          "isCancelled": {
            "type": "boolean"
          },
          "attendanceState": { },
          "isMine": {
            "type": "boolean"
          },
          "heldByTeacherName": {
            "type": "string",
            "nullable": true
          },
          "isNext": {
            "type": "boolean"
          },
          "minutesUntilStart": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "DayOfWeek": {
        "type": "integer"
      },
      "EAttendanceStatus": {
        "type": "integer"
      },
      "EBvgMode": {
        "type": "integer"
      },
      "EChildAllowanceKind": {
        "type": "integer"
      },
      "ECountryCode": {
        "type": "integer"
      },
      "ECourseCapacity": {
        "type": "integer"
      },
      "ECourseColor": {
        "type": "integer"
      },
      "ECourseStatus": {
        "type": "integer"
      },
      "ECourseType": {
        "type": "integer"
      },
      "ECustomerType": {
        "type": "integer"
      },
      "EExpenseClaimStatus": {
        "type": "integer"
      },
      "EGender": {
        "type": "integer"
      },
      "EInterestStatus": {
        "type": "integer"
      },
      "EInterestType": {
        "type": "integer"
      },
      "EInviteStatus": {
        "type": "integer"
      },
      "ELanguage": {
        "type": "integer"
      },
      "ELessonAttendanceState": {
        "type": "integer"
      },
      "ELessonCancellationReason": {
        "type": "integer"
      },
      "ELessonStatus": {
        "type": "integer"
      },
      "EMaterialLevel": {
        "type": "integer"
      },
      "EMaterialType": {
        "type": "integer"
      },
      "EnumDtoOfEAttendanceStatus": {
        "type": "object",
        "properties": {
          "enumValue": {
            "$ref": "#/components/schemas/EAttendanceStatus"
          },
          "displayName": {
            "type": "string"
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        },
        "nullable": true
      },
      "EnumDtoOfEAttendanceStatus2": {
        "type": "object",
        "properties": {
          "enumValue": {
            "$ref": "#/components/schemas/EAttendanceStatus"
          },
          "displayName": {
            "type": "string"
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "EnumDtoOfEBvgMode": {
        "type": "object",
        "properties": {
          "enumValue": {
            "$ref": "#/components/schemas/EBvgMode"
          },
          "displayName": {
            "type": "string"
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "EnumDtoOfEChildAllowanceKind": {
        "type": "object",
        "properties": {
          "enumValue": {
            "$ref": "#/components/schemas/EChildAllowanceKind"
          },
          "displayName": {
            "type": "string"
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "EnumDtoOfECountryCode": {
        "type": "object",
        "properties": {
          "enumValue": {
            "$ref": "#/components/schemas/ECountryCode"
          },
          "displayName": {
            "type": "string"
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "EnumDtoOfECourseCapacity": {
        "type": "object",
        "properties": {
          "enumValue": {
            "$ref": "#/components/schemas/ECourseCapacity"
          },
          "displayName": {
            "type": "string"
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        },
        "nullable": true
      },
      "EnumDtoOfECourseStatus": {
        "type": "object",
        "properties": {
          "enumValue": {
            "$ref": "#/components/schemas/ECourseStatus"
          },
          "displayName": {
            "type": "string"
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "EnumDtoOfECourseType": {
        "type": "object",
        "properties": {
          "enumValue": {
            "$ref": "#/components/schemas/ECourseType"
          },
          "displayName": {
            "type": "string"
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "EnumDtoOfECustomerType": {
        "type": "object",
        "properties": {
          "enumValue": {
            "$ref": "#/components/schemas/ECustomerType"
          },
          "displayName": {
            "type": "string"
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "EnumDtoOfEExpenseClaimStatus": {
        "type": "object",
        "properties": {
          "enumValue": {
            "$ref": "#/components/schemas/EExpenseClaimStatus"
          },
          "displayName": {
            "type": "string"
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "EnumDtoOfEGender": {
        "type": "object",
        "properties": {
          "enumValue": {
            "$ref": "#/components/schemas/EGender"
          },
          "displayName": {
            "type": "string"
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "EnumDtoOfEInterestStatus": {
        "type": "object",
        "properties": {
          "enumValue": {
            "$ref": "#/components/schemas/EInterestStatus"
          },
          "displayName": {
            "type": "string"
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "EnumDtoOfEInterestType": {
        "type": "object",
        "properties": {
          "enumValue": {
            "$ref": "#/components/schemas/EInterestType"
          },
          "displayName": {
            "type": "string"
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "EnumDtoOfEInviteStatus": {
        "type": "object",
        "properties": {
          "enumValue": {
            "$ref": "#/components/schemas/EInviteStatus"
          },
          "displayName": {
            "type": "string"
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "EnumDtoOfELanguage": {
        "type": "object",
        "properties": {
          "enumValue": {
            "$ref": "#/components/schemas/ELanguage"
          },
          "displayName": {
            "type": "string"
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "EnumDtoOfELanguage2": {
        "type": "object",
        "properties": {
          "enumValue": {
            "$ref": "#/components/schemas/ELanguage"
          },
          "displayName": {
            "type": "string"
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        },
        "nullable": true
      },
      "EnumDtoOfELessonAttendanceState": {
        "type": "object",
        "properties": {
          "enumValue": {
            "$ref": "#/components/schemas/ELessonAttendanceState"
          },
          "displayName": {
            "type": "string"
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "EnumDtoOfELessonCancellationReason": {
        "type": "object",
        "properties": {
          "enumValue": {
            "$ref": "#/components/schemas/ELessonCancellationReason"
          },
          "displayName": {
            "type": "string"
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        },
        "nullable": true
      },
      "EnumDtoOfELessonStatus": {
        "type": "object",
        "properties": {
          "enumValue": {
            "$ref": "#/components/schemas/ELessonStatus"
          },
          "displayName": {
            "type": "string"
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "EnumDtoOfEMaterialLevel": {
        "type": "object",
        "properties": {
          "enumValue": {
            "$ref": "#/components/schemas/EMaterialLevel"
          },
          "displayName": {
            "type": "string"
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "EnumDtoOfEMaterialType": {
        "type": "object",
        "properties": {
          "enumValue": {
            "$ref": "#/components/schemas/EMaterialType"
          },
          "displayName": {
            "type": "string"
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "EnumDtoOfEPayslipExpenseFlag": {
        "type": "object",
        "properties": {
          "enumValue": {
            "$ref": "#/components/schemas/EPayslipExpenseFlag"
          },
          "displayName": {
            "type": "string"
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        },
        "nullable": true
      },
      "EnumDtoOfEPreferredLocation": {
        "type": "object",
        "properties": {
          "enumValue": {
            "$ref": "#/components/schemas/EPreferredLocation"
          },
          "displayName": {
            "type": "string"
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        },
        "nullable": true
      },
      "EnumDtoOfERoomStatus": {
        "type": "object",
        "properties": {
          "enumValue": {
            "$ref": "#/components/schemas/ERoomStatus"
          },
          "displayName": {
            "type": "string"
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "EnumDtoOfEStudentStatus": {
        "type": "object",
        "properties": {
          "enumValue": {
            "$ref": "#/components/schemas/EStudentStatus"
          },
          "displayName": {
            "type": "string"
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "EnumDtoOfETeachingLevel": {
        "type": "object",
        "properties": {
          "enumValue": {
            "$ref": "#/components/schemas/ETeachingLevel"
          },
          "displayName": {
            "type": "string"
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "EnumDtoOfETest": {
        "type": "object",
        "properties": {
          "enumValue": {
            "$ref": "#/components/schemas/ETest"
          },
          "displayName": {
            "type": "string"
          },
          "sortOrder": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "EPayslipExpenseFlag": {
        "type": "integer"
      },
      "EPreferredLocation": {
        "type": "integer"
      },
      "ERoomStatus": {
        "type": "integer"
      },
      "EStudentStatus": {
        "type": "integer"
      },
      "ETeachingLevel": {
        "type": "integer"
      },
      "ETest": {
        "type": "integer"
      },
      "ExamRecordGet": {
        "type": "object",
        "properties": {
          "studentId": {
            "type": "string",
            "format": "uuid"
          },
          "description": {
            "type": "string"
          },
          "examDate": {
            "type": "string",
            "format": "date"
          },
          "result": {
            "type": "string",
            "nullable": true
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "ExamRecordPatch": {
        "type": "object",
        "properties": {
          "description": {
            "type": "string",
            "nullable": true
          },
          "examDate": {
            "type": "string",
            "format": "date",
            "nullable": true
          },
          "result": {
            "type": "string",
            "nullable": true
          },
          "removeResult": {
            "type": "boolean"
          }
        }
      },
      "ExamRecordPost": {
        "type": "object",
        "properties": {
          "studentId": {
            "type": "string",
            "format": "uuid"
          },
          "description": {
            "type": "string"
          },
          "examDate": {
            "type": "string",
            "format": "date"
          },
          "result": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "ExpenseClaimGet": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "format": "date"
          },
          "settledPeriodYear": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "settledPeriodMonth": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "settledPeriodDisplay": {
            "type": "string",
            "nullable": true
          },
          "isPaidOut": {
            "type": "boolean"
          },
          "claimedAmount": {
            "type": "number",
            "format": "double"
          },
          "reason": {
            "type": "string"
          },
          "receiptDocumentId": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "receiptDocumentSizeBytes": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "hasReceipt": {
            "type": "boolean"
          },
          "status": {
            "$ref": "#/components/schemas/EnumDtoOfEExpenseClaimStatus"
          },
          "approvedAmount": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "officeNote": {
            "type": "string",
            "nullable": true
          },
          "isEditable": {
            "type": "boolean"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "ExpenseClaimPatch": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "format": "date",
            "nullable": true
          },
          "claimedAmount": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "reason": {
            "type": "string",
            "nullable": true
          },
          "receiptDocumentId": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "removeReceiptDocument": {
            "type": "boolean"
          }
        }
      },
      "ExpenseClaimPost": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "format": "date"
          },
          "claimedAmount": {
            "type": "number",
            "format": "double"
          },
          "reason": {
            "type": "string"
          },
          "receiptDocumentId": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          }
        }
      },
      "HomeworkDocumentRef": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "fileName": {
            "type": "string"
          },
          "contentType": {
            "type": "string"
          },
          "sizeBytes": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "HomeworkGet": {
        "type": "object",
        "properties": {
          "lessonId": {
            "type": "string",
            "format": "uuid"
          },
          "description": {
            "type": "string"
          },
          "dueDate": {
            "type": "string",
            "format": "date"
          },
          "lessonStartDate": {
            "type": "string",
            "format": "date",
            "nullable": true
          },
          "course": {
            "$ref": "#/components/schemas/CourseRef2"
          },
          "documents": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HomeworkDocumentRef"
            }
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "HomeworkPatch": {
        "type": "object",
        "properties": {
          "description": {
            "type": "string",
            "nullable": true
          },
          "dueDate": {
            "type": "string",
            "format": "date",
            "nullable": true
          },
          "documentIdsToAdd": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "nullable": true
          },
          "documentIdsToRemove": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "nullable": true
          }
        }
      },
      "HomeworkPost": {
        "type": "object",
        "properties": {
          "lessonId": {
            "type": "string",
            "format": "uuid"
          },
          "description": {
            "type": "string"
          },
          "dueDate": {
            "type": "string",
            "format": "date"
          },
          "documentIdsToAdd": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "nullable": true
          }
        }
      },
      "HomeworkRef": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "description": {
            "type": "string"
          },
          "dueDate": {
            "type": "string",
            "format": "date"
          },
          "documents": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HomeworkDocumentRef"
            }
          }
        }
      },
      "HttpValidationProblemDetails": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "nullable": true
          },
          "title": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "detail": {
            "type": "string",
            "nullable": true
          },
          "instance": {
            "type": "string",
            "nullable": true
          },
          "errors": {
            "type": "object",
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          }
        }
      },
      "IFormFile": {
        "type": "string",
        "format": "binary"
      },
      "InterestGet": {
        "type": "object",
        "properties": {
          "language": {
            "$ref": "#/components/schemas/EnumDtoOfELanguage"
          },
          "level": {
            "$ref": "#/components/schemas/EnumDtoOfETeachingLevel"
          },
          "interestType": {
            "$ref": "#/components/schemas/EnumDtoOfEInterestType"
          },
          "status": {
            "$ref": "#/components/schemas/EnumDtoOfEInterestStatus"
          },
          "preferredLocation": {
            "$ref": "#/components/schemas/EnumDtoOfEPreferredLocation"
          },
          "notes": {
            "type": "string",
            "nullable": true
          },
          "studentAge": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "isChild": {
            "type": "boolean",
            "nullable": true
          },
          "studentNativeLanguage": {
            "$ref": "#/components/schemas/EnumDtoOfELanguage2"
          },
          "requestedStudentCount": {
            "type": "integer",
            "format": "int32"
          },
          "startDate": {
            "type": "string",
            "format": "date-time"
          },
          "endDate": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "lessonsPerWeek": {
            "type": "integer",
            "format": "int32"
          },
          "lessonDurationMinutes": {
            "type": "integer",
            "format": "int32"
          },
          "numberOfLessons": {
            "type": "integer",
            "format": "int32"
          },
          "availabilityWindows": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TimeSlotDto"
            }
          },
          "applicantCount": {
            "type": "integer",
            "format": "int32"
          },
          "myApplication": {
            "$ref": "#/components/schemas/TeacherApplicationGet"
          },
          "hasMyApplication": {
            "type": "boolean"
          },
          "hasSlotConflict": {
            "type": "boolean"
          },
          "displayName": {
            "type": "string",
            "nullable": true
          },
          "periodInfo": {
            "type": "string",
            "nullable": true
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "InterestPatch": {
        "type": "object",
        "properties": {
          "applicationToAdd": {
            "$ref": "#/components/schemas/TeacherApplicationPost"
          },
          "applicationIdToWithdraw": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          }
        }
      },
      "InvitedStudentDto": {
        "type": "object",
        "properties": {
          "student": {
            "$ref": "#/components/schemas/StudentRef"
          },
          "invitedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "LearningSubjectDto": {
        "type": "object",
        "properties": {
          "language": {
            "$ref": "#/components/schemas/EnumDtoOfELanguage"
          },
          "level": {
            "$ref": "#/components/schemas/EnumDtoOfETeachingLevel"
          },
          "courseType": {
            "$ref": "#/components/schemas/EnumDtoOfECourseType"
          }
        }
      },
      "LessonGet": {
        "type": "object",
        "properties": {
          "courseId": {
            "type": "string",
            "format": "uuid"
          },
          "course": {
            "$ref": "#/components/schemas/CourseRef2"
          },
          "startDate": {
            "type": "string",
            "format": "date"
          },
          "endDate": {
            "type": "string",
            "format": "date"
          },
          "startTime": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string"
          },
          "endTime": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string"
          },
          "durationMinutes": {
            "type": "integer",
            "format": "int32"
          },
          "courseDisplay": {
            "type": "string",
            "nullable": true
          },
          "roomId": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "room": {
            "$ref": "#/components/schemas/RoomRef"
          },
          "hasOwnRoom": {
            "type": "boolean"
          },
          "status": {
            "$ref": "#/components/schemas/EnumDtoOfELessonStatus"
          },
          "cancellationReason": {
            "$ref": "#/components/schemas/EnumDtoOfELessonCancellationReason"
          },
          "attendanceState": {
            "$ref": "#/components/schemas/EnumDtoOfELessonAttendanceState"
          },
          "teacherId": {
            "type": "string",
            "format": "uuid"
          },
          "teacher": {
            "$ref": "#/components/schemas/TeacherRef"
          },
          "isMine": {
            "type": "boolean"
          },
          "isTakeable": {
            "type": "boolean"
          },
          "teachingSalary": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "travelAllowance": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "additionalTravelCost": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "homeworks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HomeworkGet"
            },
            "nullable": true
          },
          "nextLessonStartDate": {
            "type": "string",
            "format": "date",
            "nullable": true
          },
          "attendanceRecords": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AttendanceRecordGet"
            },
            "nullable": true
          },
          "grammar": {
            "type": "string",
            "nullable": true
          },
          "notes": {
            "type": "string",
            "nullable": true
          },
          "conflictsWith": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LessonRef"
            },
            "nullable": true
          },
          "isEditable": {
            "type": "boolean"
          },
          "isAttendanceEditable": {
            "type": "boolean"
          },
          "editRefusalReason": {
            "type": "string",
            "nullable": true
          },
          "attendanceRefusalReason": {
            "type": "string",
            "nullable": true
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "LessonHomeworkPost": {
        "type": "object",
        "properties": {
          "description": {
            "type": "string"
          },
          "dueDate": {
            "type": "string",
            "format": "date"
          },
          "documentIdsToAdd": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "nullable": true
          }
        }
      },
      "LessonPatch": {
        "type": "object",
        "properties": {
          "startDate": {
            "type": "string",
            "format": "date",
            "nullable": true
          },
          "startTime": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string",
            "nullable": true
          },
          "endTime": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string",
            "nullable": true
          },
          "roomId": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "removeRoom": {
            "type": "boolean"
          },
          "teacherId": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "additionalTravelCost": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "removeAdditionalTravelCost": {
            "type": "boolean"
          },
          "attendanceRecordsToAdd": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AttendanceRecordPost"
            },
            "nullable": true
          },
          "attendanceRecordsToUpdate": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AttendanceRecordPatchWithId"
            },
            "nullable": true
          },
          "attendanceRecordIdsToRemove": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "nullable": true
          },
          "grammar": {
            "type": "string",
            "nullable": true
          },
          "removeGrammar": {
            "type": "boolean"
          },
          "notes": {
            "type": "string",
            "nullable": true
          },
          "removeNotes": {
            "type": "boolean"
          }
        }
      },
      "LessonPost": {
        "type": "object",
        "properties": {
          "courseId": {
            "type": "string",
            "format": "uuid"
          },
          "startDate": {
            "type": "string",
            "format": "date"
          },
          "startTime": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string"
          },
          "endTime": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string"
          },
          "roomId": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "teacherId": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "additionalTravelCost": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "grammar": {
            "type": "string",
            "nullable": true
          },
          "notes": {
            "type": "string",
            "nullable": true
          },
          "homeworksToAdd": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LessonHomeworkPost"
            },
            "nullable": true
          }
        }
      },
      "LessonRef": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "displayName": {
            "type": "string"
          },
          "startDate": {
            "type": "string",
            "format": "date"
          },
          "startTime": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string"
          },
          "endTime": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string"
          },
          "isCancelled": {
            "type": "boolean"
          },
          "travelAllowance": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "courseDisplay": {
            "type": "string"
          },
          "lessonPrice": {
            "type": "number",
            "format": "double"
          },
          "status": {
            "$ref": "#/components/schemas/EnumDtoOfELessonStatus"
          },
          "course": {
            "$ref": "#/components/schemas/CourseRef2"
          },
          "teacher": {
            "$ref": "#/components/schemas/TeacherRef"
          },
          "homeworks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HomeworkRef"
            },
            "nullable": true
          }
        }
      },
      "MaterialRef": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "title": {
            "type": "string"
          },
          "isbn": {
            "type": "string"
          },
          "language": {
            "$ref": "#/components/schemas/EnumDtoOfELanguage"
          },
          "level": {
            "$ref": "#/components/schemas/EnumDtoOfEMaterialLevel"
          },
          "price": {
            "type": "number",
            "format": "double"
          },
          "type": {
            "$ref": "#/components/schemas/EnumDtoOfEMaterialType"
          }
        }
      },
      "NullableOfDayOfWeek": {
        "type": "integer",
        "nullable": true
      },
      "NullableOfECountryCode": {
        "type": "integer",
        "nullable": true
      },
      "NullableOfECourseStatus": {
        "type": "integer"
      },
      "NullableOfECourseType": {
        "type": "integer"
      },
      "NullableOfEExpenseClaimStatus": {
        "type": "integer"
      },
      "NullableOfEInterestStatus": {
        "type": "integer"
      },
      "NullableOfEInterestType": {
        "type": "integer"
      },
      "NullableOfEInviteStatus": {
        "type": "integer",
        "nullable": true
      },
      "NullableOfEInviteStatus2": {
        "type": "integer"
      },
      "NullableOfELanguage": {
        "type": "integer",
        "nullable": true
      },
      "NullableOfELanguage2": {
        "type": "integer"
      },
      "NullableOfELessonAttendanceState": {
        "type": "integer"
      },
      "NullableOfELessonStatus": {
        "type": "integer"
      },
      "NullableOfEPreferredLocation": {
        "type": "integer"
      },
      "NullableOfEStudentStatus": {
        "type": "integer"
      },
      "NullableOfETeachingLevel": {
        "type": "integer",
        "nullable": true
      },
      "NullableOfETeachingLevel2": {
        "type": "integer"
      },
      "PayslipBonusDto": {
        "type": "object",
        "properties": {
          "reason": {
            "type": "string"
          },
          "amount": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "PayslipDeductionDto": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string"
          },
          "ratePercent": {
            "type": "number",
            "format": "double"
          },
          "amount": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "PayslipRateGroupDto": {
        "type": "object",
        "properties": {
          "rateGroupName": {
            "type": "string"
          },
          "lessonCount": {
            "type": "integer",
            "format": "int32"
          },
          "hours": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "hourlyRate": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "amountPerLesson": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "lineTotal": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "PendingInviteDto": {
        "type": "object",
        "properties": {
          "course": {
            "$ref": "#/components/schemas/CourseRef"
          },
          "invitedAt": {
            "type": "string",
            "format": "date-time"
          },
          "isYours": {
            "type": "boolean"
          }
        }
      },
      "ProblemDetails": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "nullable": true
          },
          "title": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "detail": {
            "type": "string",
            "nullable": true
          },
          "instance": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "ProposedSlotDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "day": {
            "$ref": "#/components/schemas/DayOfWeek"
          },
          "startTime": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string"
          },
          "endTime": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string"
          },
          "conflictLabel": {
            "type": "string",
            "nullable": true
          },
          "hasConflict": {
            "type": "boolean"
          },
          "durationMinutes": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "RoomAvailabilityDto": {
        "type": "object",
        "properties": {
          "room": {
            "$ref": "#/components/schemas/RoomRef2"
          },
          "occupiedUntil": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string",
            "nullable": true
          },
          "isAvailable": {
            "type": "boolean"
          }
        }
      },
      "RoomAvailabilityResponse": {
        "type": "object",
        "properties": {
          "sites": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RoomAvailabilitySiteDto"
            }
          },
          "totalRooms": {
            "type": "integer",
            "format": "int32"
          },
          "unavailableRooms": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "RoomAvailabilitySiteDto": {
        "type": "object",
        "properties": {
          "locationId": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "locationName": {
            "type": "string"
          },
          "rooms": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RoomAvailabilityDto"
            }
          }
        }
      },
      "RoomRef": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "displayName": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "maxStudents": {
            "type": "integer",
            "format": "int32"
          },
          "status": {
            "$ref": "#/components/schemas/EnumDtoOfERoomStatus"
          }
        },
        "nullable": true
      },
      "RoomRef2": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "displayName": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "maxStudents": {
            "type": "integer",
            "format": "int32"
          },
          "status": {
            "$ref": "#/components/schemas/EnumDtoOfERoomStatus"
          }
        }
      },
      "SpokenLanguageGet": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "language": {
            "$ref": "#/components/schemas/EnumDtoOfELanguage"
          },
          "level": {
            "$ref": "#/components/schemas/EnumDtoOfETeachingLevel"
          }
        }
      },
      "SpokenLanguagePatch": {
        "type": "object",
        "properties": {
          "language": {
            "$ref": "#/components/schemas/NullableOfELanguage"
          },
          "level": {
            "$ref": "#/components/schemas/NullableOfETeachingLevel"
          }
        }
      },
      "SpokenLanguagePatchWithId": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "patch": {
            "$ref": "#/components/schemas/SpokenLanguagePatch"
          }
        }
      },
      "SpokenLanguagePost": {
        "type": "object",
        "properties": {
          "language": {
            "$ref": "#/components/schemas/ELanguage"
          },
          "level": {
            "$ref": "#/components/schemas/ETeachingLevel"
          }
        }
      },
      "StudentGet": {
        "type": "object",
        "properties": {
          "firstName": {
            "type": "string"
          },
          "lastName": {
            "type": "string"
          },
          "age": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "isChild": {
            "type": "boolean",
            "nullable": true
          },
          "nativeLanguage": {
            "$ref": "#/components/schemas/EnumDtoOfELanguage2"
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "phone": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "$ref": "#/components/schemas/EnumDtoOfEStudentStatus"
          },
          "inactive": {
            "type": "boolean"
          },
          "learningWithYou": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LearningSubjectDto"
            }
          },
          "courses": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CourseRef"
            }
          },
          "sharedCourseIds": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "pendingInvites": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PendingInviteDto"
            }
          },
          "materials": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StudentMaterialDto"
            }
          },
          "customerId": {
            "type": "string",
            "format": "uuid"
          },
          "customer": {
            "$ref": "#/components/schemas/CustomerRef"
          },
          "customerEmail": {
            "type": "string",
            "nullable": true
          },
          "customerPhone": {
            "type": "string",
            "nullable": true
          },
          "lessons": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StudentLessonDto"
            }
          },
          "studentNotes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StudentNoteGet"
            },
            "nullable": true
          },
          "examRecords": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExamRecordGet"
            },
            "nullable": true
          },
          "displayName": {
            "type": "string",
            "nullable": true
          },
          "learningDisplay": {
            "type": "string",
            "nullable": true
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "StudentLessonDto": {
        "type": "object",
        "properties": {
          "lesson": {
            "$ref": "#/components/schemas/LessonRef"
          },
          "attendance": {
            "$ref": "#/components/schemas/EnumDtoOfEAttendanceStatus"
          }
        }
      },
      "StudentMaterialDto": {
        "type": "object",
        "properties": {
          "material": {
            "$ref": "#/components/schemas/MaterialRef"
          },
          "courseId": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "StudentNoteGet": {
        "type": "object",
        "properties": {
          "studentId": {
            "type": "string",
            "format": "uuid"
          },
          "authorId": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "authorName": {
            "type": "string"
          },
          "isMine": {
            "type": "boolean"
          },
          "text": {
            "type": "string"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "StudentNotePost": {
        "type": "object",
        "properties": {
          "studentId": {
            "type": "string",
            "format": "uuid"
          },
          "text": {
            "type": "string"
          }
        }
      },
      "StudentRef": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "firstName": {
            "type": "string"
          },
          "lastName": {
            "type": "string"
          },
          "displayName": {
            "type": "string"
          },
          "nativeLanguage": {
            "$ref": "#/components/schemas/EnumDtoOfELanguage2"
          },
          "isChild": {
            "type": "boolean",
            "nullable": true
          },
          "age": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          }
        }
      },
      "StudentRef2": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "firstName": {
            "type": "string"
          },
          "lastName": {
            "type": "string"
          },
          "displayName": {
            "type": "string"
          },
          "nativeLanguage": {
            "$ref": "#/components/schemas/EnumDtoOfELanguage2"
          },
          "isChild": {
            "type": "boolean",
            "nullable": true
          },
          "age": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          }
        },
        "nullable": true
      },
      "TeacherApplicationGet": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "appliedAt": {
            "type": "string",
            "format": "date-time"
          },
          "proposedTimeSlots": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProposedSlotDto"
            }
          },
          "hasSlotConflict": {
            "type": "boolean"
          }
        },
        "nullable": true
      },
      "TeacherApplicationPost": {
        "type": "object",
        "properties": {
          "proposedTimeSlots": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TimeSlotDto"
            }
          }
        },
        "nullable": true
      },
      "TeacherDashboardGet": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "format": "date"
          },
          "lessonsToday": {
            "type": "integer",
            "format": "int32"
          },
          "openApplicationCount": {
            "type": "integer",
            "format": "int32"
          },
          "absencesToday": {
            "type": "integer",
            "format": "int32"
          },
          "lessonsThisMonth": {
            "type": "integer",
            "format": "int32"
          },
          "pendingInviteCount": {
            "type": "integer",
            "format": "int32"
          },
          "attendancesMissingCount": {
            "type": "integer",
            "format": "int32"
          },
          "nextLesson": {
            "$ref": "#/components/schemas/DashboardLessonRow"
          },
          "todaysLessons": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DashboardLessonRow2"
            }
          },
          "absencesReportedToday": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DashboardAbsenceRow"
            }
          }
        }
      },
      "TeacherInviteGet": {
        "type": "object",
        "properties": {
          "courseId": {
            "type": "string",
            "format": "uuid"
          },
          "course": {
            "$ref": "#/components/schemas/CourseRef2"
          },
          "roomId": {
            "type": "string",
            "format": "uuid"
          },
          "room": {
            "$ref": "#/components/schemas/RoomRef"
          },
          "status": {
            "$ref": "#/components/schemas/EnumDtoOfEInviteStatus"
          },
          "invitedAt": {
            "type": "string",
            "format": "date-time"
          },
          "respondedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "coursePlanned": {
            "type": "boolean"
          },
          "slotsOutsideAvailability": {
            "type": "array",
            "items": { }
          },
          "courseInfo": {
            "type": "string",
            "nullable": true
          },
          "isPending": {
            "type": "boolean"
          },
          "acceptedNotYetPlanned": {
            "type": "boolean"
          },
          "fitsAvailability": {
            "type": "boolean"
          },
          "lessonDurationsMinutes": {
            "type": "array",
            "items": {
              "type": "integer",
              "format": "int32"
            },
            "nullable": true
          },
          "weeklyMinutes": {
            "type": "integer",
            "format": "int32"
          },
          "periodInfo": {
            "type": "string",
            "nullable": true
          },
          "invitedAgo": {
            "type": "string",
            "nullable": true
          },
          "answeredAgo": {
            "type": "string",
            "nullable": true
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "TeacherInvitePatch": {
        "type": "object",
        "properties": {
          "status": {
            "$ref": "#/components/schemas/NullableOfEInviteStatus"
          },
          "denyReason": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "TeacherPayslipGet": {
        "type": "object",
        "properties": {
          "periodStart": {
            "type": "string",
            "format": "date"
          },
          "rateGroups": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PayslipRateGroupDto"
            }
          },
          "lessonCount": {
            "type": "integer",
            "format": "int32"
          },
          "basePayLessons": {
            "type": "number",
            "format": "double"
          },
          "basePayFixed": {
            "type": "number",
            "format": "double"
          },
          "bonuses": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PayslipBonusDto"
            }
          },
          "bonusTotal": {
            "type": "number",
            "format": "double"
          },
          "basePayFixedTotal": {
            "type": "number",
            "format": "double"
          },
          "vacationSupplementRate": {
            "type": "number",
            "format": "double"
          },
          "vacationSupplementAmount": {
            "type": "number",
            "format": "double"
          },
          "grossPay": {
            "type": "number",
            "format": "double"
          },
          "deductions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PayslipDeductionDto"
            }
          },
          "bvgAmount": {
            "type": "number",
            "format": "double"
          },
          "bvgMode": {
            "$ref": "#/components/schemas/EnumDtoOfEBvgMode"
          },
          "bvgMonth": {
            "type": "string",
            "format": "date",
            "nullable": true
          },
          "isBvgDueThisPeriod": {
            "type": "boolean"
          },
          "bvgAmountDue": {
            "type": "number",
            "format": "double"
          },
          "quellensteuerRate": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "quellensteuerAmount": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "deductionsTotal": {
            "type": "number",
            "format": "double"
          },
          "netPay": {
            "type": "number",
            "format": "double"
          },
          "travelAllowancePerLesson": {
            "type": "number",
            "format": "double"
          },
          "travelAllowance": {
            "type": "number",
            "format": "double"
          },
          "expenseClaims": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExpenseClaimGet"
            }
          },
          "expensesPaid": {
            "type": "number",
            "format": "double"
          },
          "expenseFlag": {
            "$ref": "#/components/schemas/EnumDtoOfEPayslipExpenseFlag"
          },
          "childAllowances": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ChildAllowanceRef"
            }
          },
          "childAllowanceTotal": {
            "type": "number",
            "format": "double"
          },
          "payout": {
            "type": "number",
            "format": "double"
          },
          "paidOutAt": {
            "type": "string",
            "format": "date",
            "nullable": true
          },
          "isPaidOut": {
            "type": "boolean"
          },
          "payslipDocumentId": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "payslipDocumentSizeBytes": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "hasPayslipDocument": {
            "type": "boolean"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "TeacherProfileGet": {
        "type": "object",
        "properties": {
          "firstName": {
            "type": "string"
          },
          "lastName": {
            "type": "string"
          },
          "displayName": {
            "type": "string",
            "nullable": true
          },
          "initials": {
            "type": "string",
            "nullable": true
          },
          "gender": {
            "$ref": "#/components/schemas/EnumDtoOfEGender"
          },
          "dateOfBirth": {
            "type": "string",
            "format": "date"
          },
          "loginNumber": {
            "type": "string"
          },
          "joinedAt": {
            "type": "string",
            "format": "date"
          },
          "workEmail": {
            "type": "string"
          },
          "privateEmail": {
            "type": "string",
            "nullable": true
          },
          "mobilePhone": {
            "type": "string"
          },
          "landlinePhone": {
            "type": "string",
            "nullable": true
          },
          "street": {
            "type": "string"
          },
          "postalCode": {
            "type": "string"
          },
          "city": {
            "type": "string"
          },
          "country": {
            "$ref": "#/components/schemas/EnumDtoOfECountryCode"
          },
          "iban": {
            "type": "string"
          },
          "accountHolder": {
            "type": "string",
            "nullable": true
          },
          "weeklyAvailabilitySlots": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WeeklyAvailabilitySlotGet"
            }
          },
          "weeklyHours": {
            "type": "number",
            "format": "double"
          },
          "absences": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AbsenceGet"
            }
          },
          "spokenLanguages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SpokenLanguageGet"
            }
          },
          "teachingLanguages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TeachingLanguageDto"
            }
          },
          "lessonsToChildren": {
            "type": "boolean"
          },
          "challengingStudents": {
            "type": "boolean"
          },
          "citizenshipProgramme": {
            "type": "boolean"
          },
          "examPreparation": {
            "type": "boolean"
          },
          "completedTrainings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CompletedTrainingDto"
            }
          },
          "trainingPointsTotal": {
            "type": "integer",
            "format": "int32"
          },
          "children": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ChildAllowanceGet"
            }
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "removed": {
            "type": "boolean"
          }
        }
      },
      "TeacherProfilePatch": {
        "type": "object",
        "properties": {
          "street": {
            "type": "string",
            "nullable": true
          },
          "postalCode": {
            "type": "string",
            "nullable": true
          },
          "city": {
            "type": "string",
            "nullable": true
          },
          "country": {
            "$ref": "#/components/schemas/NullableOfECountryCode"
          },
          "iban": {
            "type": "string",
            "nullable": true
          },
          "accountHolder": {
            "type": "string",
            "nullable": true
          },
          "removeAccountHolder": {
            "type": "boolean"
          },
          "weeklyAvailabilitySlotsToAdd": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WeeklyAvailabilitySlotPost"
            },
            "nullable": true
          },
          "weeklyAvailabilitySlotsToUpdate": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WeeklyAvailabilitySlotPatchWithId"
            },
            "nullable": true
          },
          "weeklyAvailabilitySlotIdsToRemove": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "nullable": true
          },
          "absencesToAdd": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AbsencePost"
            },
            "nullable": true
          },
          "absencesToUpdate": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AbsencePatchWithId"
            },
            "nullable": true
          },
          "absenceIdsToRemove": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "nullable": true
          },
          "spokenLanguagesToAdd": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SpokenLanguagePost"
            },
            "nullable": true
          },
          "spokenLanguagesToUpdate": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SpokenLanguagePatchWithId"
            },
            "nullable": true
          },
          "spokenLanguageIdsToRemove": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "nullable": true
          }
        }
      },
      "TeacherRef": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "displayName": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "mobilePhone": {
            "type": "string"
          },
          "lessonsToChildren": {
            "type": "boolean"
          },
          "inactive": {
            "type": "boolean"
          },
          "teachingLanguages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EnumDtoOfELanguage"
            }
          }
        },
        "nullable": true
      },
      "TeacherRef2": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "displayName": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "mobilePhone": {
            "type": "string"
          },
          "lessonsToChildren": {
            "type": "boolean"
          },
          "inactive": {
            "type": "boolean"
          },
          "teachingLanguages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EnumDtoOfELanguage"
            }
          }
        }
      },
      "TeachingLanguageDto": {
        "type": "object",
        "properties": {
          "language": {
            "$ref": "#/components/schemas/EnumDtoOfELanguage"
          },
          "level": {
            "$ref": "#/components/schemas/EnumDtoOfETeachingLevel"
          },
          "testPreparations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EnumDtoOfETest"
            }
          },
          "testExaminers": {
            "type": "array",
            "items": { }
          }
        }
      },
      "TimeSlotDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "day": {
            "$ref": "#/components/schemas/DayOfWeek"
          },
          "startTime": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string"
          },
          "endTime": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string"
          }
        }
      },
      "TrainingCourseRef": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "points": {
            "type": "integer",
            "format": "int32"
          }
        },
        "nullable": true
      },
      "UploadedDocument": {
        "required": [
          "id",
          "fileName",
          "sizeBytes"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "fileName": {
            "type": "string"
          },
          "sizeBytes": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "UploadedExpenseReceipt": {
        "required": [
          "id",
          "fileName",
          "sizeBytes"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "fileName": {
            "type": "string"
          },
          "sizeBytes": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "UploadedHomeworkDocument": {
        "required": [
          "id",
          "fileName",
          "contentType",
          "sizeBytes"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "fileName": {
            "type": "string"
          },
          "contentType": {
            "type": "string"
          },
          "sizeBytes": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "WeeklyAvailabilitySlotGet": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "day": {
            "$ref": "#/components/schemas/DayOfWeek"
          },
          "startTime": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string"
          },
          "endTime": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string"
          },
          "hours": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "WeeklyAvailabilitySlotPatch": {
        "type": "object",
        "properties": {
          "day": {
            "$ref": "#/components/schemas/NullableOfDayOfWeek"
          },
          "startTime": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string",
            "nullable": true
          },
          "endTime": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string",
            "nullable": true
          }
        }
      },
      "WeeklyAvailabilitySlotPatchWithId": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "patch": {
            "$ref": "#/components/schemas/WeeklyAvailabilitySlotPatch"
          }
        }
      },
      "WeeklyAvailabilitySlotPost": {
        "type": "object",
        "properties": {
          "day": {
            "$ref": "#/components/schemas/DayOfWeek"
          },
          "startTime": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string"
          },
          "endTime": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string"
          }
        }
      },
      "WeeklyScheduleSlotDto": {
        "type": "object",
        "properties": {
          "day": {
            "$ref": "#/components/schemas/DayOfWeek"
          },
          "startTime": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string"
          },
          "endTime": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string"
          }
        }
      }
    },
    "securitySchemes": {
      "keycloak": {
        "type": "oauth2",
        "description": "Log in via Keycloak (Authorization Code + PKCE). Uses the public 'swagger-ui' client.",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://auth.triskela.com/realms/softlanding/protocol/openid-connect/auth",
            "tokenUrl": "https://auth.triskela.com/realms/softlanding/protocol/openid-connect/token",
            "scopes": {
              "openid": "OpenID Connect",
              "profile": "User profile",
              "email": "User email"
            }
          }
        }
      }
    }
  },
  "security": [
    {
      "keycloak": [
        "openid",
        "profile",
        "email"
      ]
    }
  ],
  "tags": [
    {
      "name": "AttendanceDocument (Teacher)"
    },
    {
      "name": "HomeworkDocument (Teacher)"
    },
    {
      "name": "MyProfile (Teacher)"
    },
    {
      "name": "Student (Teacher)"
    },
    {
      "name": "Student Notes (Teacher)"
    },
    {
      "name": "Exam Records (Teacher)"
    },
    {
      "name": "Course (Teacher)"
    },
    {
      "name": "Lesson (Teacher)"
    },
    {
      "name": "Room Availability (Teacher)"
    },
    {
      "name": "Dashboard (Teacher)"
    },
    {
      "name": "Opportunities (Teacher)"
    },
    {
      "name": "Expense Claims (Teacher)"
    },
    {
      "name": "Payslips (Teacher)"
    },
    {
      "name": "Expense Receipts (Teacher)"
    },
    {
      "name": "Homework (Teacher)"
    }
  ]
}