diff --git a/v2/swagger.yaml b/v2/swagger.yaml index 113e52d..072bef1 100644 --- a/v2/swagger.yaml +++ b/v2/swagger.yaml @@ -79,6 +79,33 @@ tags: description: Methods for admin oversight of personal API tokens. Requires "api-tokens-admin" permission. - name: admin-employment description: Methods for administrative read-only access to employee employments, including external identifiers used by integrations. Requires "user-edit" permission. + - name: admin-lms-content + description: | + Админский CRUD учебных материалов СДО (LMS Content). Требуется право `learning-controls` для чтения и `learning-edit` для записи. + - name: admin-lms-assignment + description: | + Админский API назначений учебных материалов (LMS Assignment). Требуется право `learning-controls` или `learning-assign` для чтения и `learning-assign` для записи. + - name: admin-lms-assignment-set + description: | + Админский API наборов назначений (LMS Assignment Set). Требуется право `learning-controls` или `learning-assign`. + - name: admin-lms-auto-assignment + description: | + Админский API авто-назначений обучения (LMS Auto Assignment). Чтение — `learning-controls` или `learning-assign`, запись — `learning-assign`. + - name: admin-lms-attempt + description: | + Админский API попыток прохождения LMS. Чтение/удаление — `learning-controls`. Просмотр оценки (`assessment`) — `learning-controls`, `learning-assign` либо назначенный эксперт по конкретной попытке. + - name: admin-lms-category + description: | + Админский API дерева категорий обучения. Чтение — `learning-edit` или `learning-controls`, изменение — `learning-edit`. + - name: admin-lms-report + description: | + Админские отчёты СДО (данные + асинхронный экспорт в xlsx через `/file-processing`). Требуется право `learning-reports`. + - name: admin-lms-certificate-editor + description: | + Админский API редактора шаблонов сертификатов LMS. Полный доступ — `certificate-edit`. Право `certificate-assign` даёт доступ только к `index`, `field-types` и `names`. + - name: lms + description: | + Пользовательский LMS — каталог, кабинет, запуск материала и просмотр своих попыток. Доступ — авторизованный пользователь (`@`). paths: /mobile/bind/{id}/{token}: @@ -8233,6 +8260,1694 @@ paths: Запись не найдена. Включает случаи обращения к записям, принадлежащим другим тенантам. + # ========================================================================= + # LMS — Учебные материалы (admin) — H-3869 + # ========================================================================= + /admin/lms/lms-content: + get: + tags: [admin-lms-content] + summary: Список учебных материалов + description: | + Требуется право `learning-controls`. Ответ — yii DataProvider envelope + (`data` + `_links` + `_meta`). + operationId: adminLmsContentIndex + parameters: + - name: page + in: query + schema: { type: integer, minimum: 1, default: 1 } + - name: per-page + in: query + schema: { type: integer, minimum: 1, default: 20 } + - name: sort + in: query + schema: { type: string } + description: | + Поле сортировки. Префикс `-` для DESC. Допустимые поля смотри в + `LmsContentSearch::sort()`. + - name: LmsContentSearch[name] + in: query + schema: { type: string } + - name: LmsContentSearch[status_id] + in: query + schema: { type: integer } + - name: LmsContentSearch[lms_content_type_id] + in: query + schema: { type: integer } + - name: LmsContentSearch[lms_content_provider_id] + in: query + schema: { type: integer } + - name: LmsContentSearch[created_user_id] + in: query + schema: { type: string, format: uuid } + - name: LmsContentSearch[created_at] + in: query + schema: { type: string } + description: Диапазон `yyyy-MM-dd|yyyy-MM-dd`. + responses: + 200: + description: Список материалов + content: + application/json: + schema: + $ref: '#/components/schemas/LmsContentList' + + /admin/lms/lms-content/view: + get: + tags: [admin-lms-content] + summary: Один учебный материал + operationId: adminLmsContentView + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 200: + description: Материал + content: + application/json: + schema: + $ref: '#/components/schemas/LmsContent' + 404: + description: Материал не найден. + + /admin/lms/lms-content/items: + get: + tags: [admin-lms-content] + summary: Облегчённый список (id + name) для селекторов + description: | + Возвращает только `{id, name}` для всех материалов, отсортированных + по имени. Принимает те же фильтры, что и `index`. + operationId: adminLmsContentItems + parameters: + - name: page + in: query + schema: { type: integer, minimum: 1, default: 1 } + - name: per-page + in: query + schema: { type: integer, minimum: 1, default: 10 } + responses: + 200: + description: Список + content: + application/json: + schema: + $ref: '#/components/schemas/LmsContentItemsList' + + /admin/lms/lms-content/create: + post: + tags: [admin-lms-content] + summary: Создать учебный материал + description: | + Тело — поля `LmsContentForm`. Требуется право `learning-edit`. + operationId: adminLmsContentCreate + parameters: + - name: lms_content_type_id + in: query + required: false + schema: { type: integer } + description: Тип создаваемого материала (LmsContentType). + requestBody: + required: true + content: + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/LmsContentFormBody' + responses: + 200: + description: HttpJsonResult с id созданного материала. + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAdminHttpJsonResultWithId' + + /admin/lms/lms-content/update: + post: + tags: [admin-lms-content] + summary: Обновить учебный материал + description: | + Тело — поля `LmsContentForm`. Требуется право `learning-edit`. + operationId: adminLmsContentUpdate + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + description: UUID существующего материала. + requestBody: + required: true + content: + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/LmsContentFormBody' + responses: + 200: + description: HttpJsonResult с id обновлённого материала. + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAdminHttpJsonResultWithId' + + /admin/lms/lms-content/delete: + delete: + tags: [admin-lms-content] + summary: Удалить учебный материал + description: | + Soft-delete. Возвращает `HttpJsonResult` с `success=false` и + `message`, если материал нельзя удалить (есть активные назначения / + дочерние материалы / другие guards внутри `LmsContentManager::delete`). + operationId: adminLmsContentDelete + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 200: + description: HttpJsonResult + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAdminHttpJsonResult' + + /admin/lms/lms-content/create-from-file: + post: + tags: [admin-lms-content] + summary: Создать материал из загруженного файла + description: | + Принимает `fileId` (UUID файла, загруженного через + `/file/prepare-upload` + `/file/finish-upload`). Распаковывает архив, + парсит manifest (SCORM / xAPI / Quiz / iSpring), создаёт материал + либо возрождает удалённый по `activity_id`. + operationId: adminLmsContentCreateFromFile + requestBody: + required: true + content: + application/x-www-form-urlencoded: + schema: + type: object + required: [fileId] + properties: + fileId: + type: string + format: uuid + description: UUID файла после двухэтапной загрузки. + categoryTreeItemId: + type: string + format: uuid + description: | + UUID узла дерева категорий LMS, куда добавить материал. + Опционально. + responses: + 200: + description: HttpJsonResult + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAdminHttpJsonResultWithId' + + /admin/lms/lms-content/copy: + post: + tags: [admin-lms-content] + summary: Клонировать материал + description: | + Создаёт копию HRBOX-материала с обнулённым `activity_id` и префиксом + «(копия)» в имени. + operationId: adminLmsContentCopy + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 200: + description: HttpJsonResult с id копии. + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAdminHttpJsonResultWithId' + + # ========================================================================= + # LMS — Назначения (admin) + # ========================================================================= + /admin/lms/lms-assignment: + get: + tags: [admin-lms-assignment] + summary: Список назначений + description: Чтение — `learning-controls` или `learning-assign`. + operationId: adminLmsAssignmentIndex + parameters: + - name: page + in: query + schema: { type: integer, minimum: 1, default: 1 } + - name: per-page + in: query + schema: { type: integer, minimum: 1, default: 20 } + - name: sort + in: query + schema: { type: string } + - name: LmsAssignmentSearch[user_id] + in: query + schema: { type: string, format: uuid } + - name: LmsAssignmentSearch[lms_assignment_set_id] + in: query + schema: { type: string, format: uuid } + - name: LmsAssignmentSearch[user_group_id] + in: query + schema: { type: string, format: uuid } + - name: LmsAssignmentSearch[department_id] + in: query + schema: { type: string, format: uuid } + - name: LmsAssignmentSearch[status] + in: query + schema: { type: string } + description: Кабинетный статус (LmsAssignmentStatusCabinet). + - name: LmsAssignmentSearch[type_id] + in: query + schema: { type: integer } + - name: LmsAssignmentSearch[user_list_key] + in: query + schema: { type: string, format: uuid } + description: Закэшированная выборка пользователей. + - name: LmsAssignmentSearch[created_at] + in: query + schema: { type: string } + description: Диапазон `yyyy-MM-dd|yyyy-MM-dd`. + responses: + 200: + description: Список назначений + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAssignmentList' + + /admin/lms/lms-assignment/view: + get: + tags: [admin-lms-assignment] + summary: Одно назначение + operationId: adminLmsAssignmentView + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 200: + description: Назначение + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAssignment' + + /admin/lms/lms-assignment/create: + post: + tags: [admin-lms-assignment] + summary: Создать набор назначений + description: | + Создаёт `LmsAssignmentSet` + ставит фоновую задачу `enqueueCreateAssignments`, + которая раздаёт назначения выбранным пользователям. Тело — поля + `LmsAssignmentForm`. + + Требуется право `learning-assign`. + operationId: adminLmsAssignmentCreate + requestBody: + required: true + content: + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/LmsAssignmentFormBody' + responses: + 200: + description: HttpJsonResult + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAdminHttpJsonResult' + + /admin/lms/lms-assignment/update: + post: + tags: [admin-lms-assignment] + summary: Обновить набор назначений + description: | + Обновляет `LmsAssignmentSet` (имя и параметры) и ставит фоновую + задачу `enqueueUpdateAssignments`, которая пересчитывает дочерние + назначения по новым параметрам. + operationId: adminLmsAssignmentUpdate + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + description: UUID `LmsAssignmentSet`. + requestBody: + required: true + content: + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/LmsAssignmentFormBody' + responses: + 200: + description: HttpJsonResult + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAdminHttpJsonResult' + + /admin/lms/lms-assignment/update-assignment: + post: + tags: [admin-lms-assignment] + summary: Массово обновить параметры выбранных назначений + description: | + Применяет общие параметры (`available_date`, `deadline_at`, + `attempts_max`, `allow_submit_grace`) к выборке назначений по + `cache_key`. Выборка заранее кэшируется через + `/user-list-cache/set-user-list` либо аналогичный механизм + в админке. + + Особенность: `attempts_max` прибавляется к существующему значению + попыток (`col = col + val`); NULL остаётся NULL. + operationId: adminLmsAssignmentUpdateAssignment + requestBody: + required: true + content: + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/LmsUpdateAssignmentsFormBody' + responses: + 200: + description: HttpJsonResult + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAdminHttpJsonResult' + + /admin/lms/lms-assignment/delete-assignment: + post: + tags: [admin-lms-assignment] + summary: Удалить выбранные назначения + description: Удаляет все назначения из выборки по `cache_key`. + operationId: adminLmsAssignmentDeleteAssignment + parameters: + - name: cache_key + in: query + required: true + schema: { type: string, format: uuid } + responses: + 200: + description: HttpJsonResult + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAdminHttpJsonResult' + + # ========================================================================= + # LMS — Наборы назначений (admin) + # ========================================================================= + /admin/lms/lms-assignment-set: + get: + tags: [admin-lms-assignment-set] + summary: Список наборов назначений + operationId: adminLmsAssignmentSetIndex + parameters: + - name: page + in: query + schema: { type: integer, minimum: 1, default: 1 } + - name: per-page + in: query + schema: { type: integer, minimum: 1, default: 20 } + - name: sort + in: query + schema: { type: string } + - name: LmsAssignmentSetSearch[name] + in: query + schema: { type: string } + - name: LmsAssignmentSetSearch[created_user_id] + in: query + schema: { type: string, format: uuid } + - name: LmsAssignmentSetSearch[created_at] + in: query + schema: { type: string } + - name: LmsAssignmentSetSearch[lms_content_name] + in: query + schema: { type: string } + responses: + 200: + description: Список наборов + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAssignmentSetList' + + /admin/lms/lms-assignment-set/view: + get: + tags: [admin-lms-assignment-set] + summary: Один набор назначений + operationId: adminLmsAssignmentSetView + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 200: + description: Набор + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAssignmentSet' + + /admin/lms/lms-assignment-set/items: + get: + tags: [admin-lms-assignment-set] + summary: Список наборов в формате {id, name} для селекторов + operationId: adminLmsAssignmentSetItems + responses: + 200: + description: Список + content: + application/json: + schema: + $ref: '#/components/schemas/LmsItemsList' + + /admin/lms/lms-assignment-set/delete: + delete: + tags: [admin-lms-assignment-set] + summary: Удалить набор назначений + description: | + Soft-delete всего набора вместе с дочерними назначениями. Может + вернуть `success=false` с описанием причины (есть незавершённые + активные назначения). + operationId: adminLmsAssignmentSetDelete + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 200: + description: HttpJsonResult + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAdminHttpJsonResult' + + # ========================================================================= + # LMS — Авто-назначения (admin) + # ========================================================================= + /admin/lms/lms-auto-assignment: + get: + tags: [admin-lms-auto-assignment] + summary: Список авто-назначений + operationId: adminLmsAutoAssignmentIndex + parameters: + - name: page + in: query + schema: { type: integer, minimum: 1, default: 1 } + - name: per-page + in: query + schema: { type: integer, minimum: 1, default: 20 } + - name: sort + in: query + schema: { type: string } + - name: LmsAutoAssignmentSearch[name] + in: query + schema: { type: string } + - name: LmsAutoAssignmentSearch[type_id] + in: query + schema: { type: integer } + description: Тип авто-назначения (`LmsAutoAssignmentType`). + - name: LmsAutoAssignmentSearch[created_user_id] + in: query + schema: { type: string, format: uuid } + responses: + 200: + description: Список + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAutoAssignmentList' + + /admin/lms/lms-auto-assignment/view: + get: + tags: [admin-lms-auto-assignment] + summary: Одно авто-назначение + operationId: adminLmsAutoAssignmentView + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 200: + description: Авто-назначение + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAutoAssignment' + + /admin/lms/lms-auto-assignment/create: + post: + tags: [admin-lms-auto-assignment] + summary: Создать авто-назначение + description: | + Сценарий `auto-assignment`: тип и периодичность обязательны. + Воркер раздаёт назначения по расписанию. + operationId: adminLmsAutoAssignmentCreate + requestBody: + required: true + content: + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/LmsAutoAssignmentFormBody' + responses: + 200: + description: HttpJsonResult + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAdminHttpJsonResult' + + /admin/lms/lms-auto-assignment/update: + post: + tags: [admin-lms-auto-assignment] + summary: Обновить авто-назначение + operationId: adminLmsAutoAssignmentUpdate + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + requestBody: + required: true + content: + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/LmsAutoAssignmentFormBody' + responses: + 200: + description: HttpJsonResult + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAdminHttpJsonResult' + + /admin/lms/lms-auto-assignment/delete: + delete: + tags: [admin-lms-auto-assignment] + summary: Удалить авто-назначение + operationId: adminLmsAutoAssignmentDelete + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 200: + description: HttpJsonResult + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAdminHttpJsonResult' + + # ========================================================================= + # LMS — Попытки (admin) + # ========================================================================= + /admin/lms/lms-attempt: + get: + tags: [admin-lms-attempt] + summary: Список попыток прохождения + operationId: adminLmsAttemptIndex + parameters: + - name: page + in: query + schema: { type: integer, minimum: 1, default: 1 } + - name: per-page + in: query + schema: { type: integer, minimum: 1, default: 20 } + - name: sort + in: query + schema: { type: string } + - name: LmsAttemptSearch[user_id] + in: query + schema: { type: string, format: uuid } + - name: LmsAttemptSearch[lms_assignment_id] + in: query + schema: { type: string, format: uuid } + - name: LmsAttemptSearch[status] + in: query + schema: { type: string } + description: Comma-separated значения `LmsAttemptStatus`. + - name: LmsAttemptSearch[need_assessment] + in: query + schema: { type: boolean } + - name: LmsAttemptSearch[expert_user_id] + in: query + schema: { type: string, format: uuid } + - name: LmsAttemptSearch[lms_content_type_id] + in: query + schema: { type: integer } + - name: LmsAttemptSearch[user_list_key] + in: query + schema: { type: string, format: uuid } + - name: LmsAttemptSearch[started_at] + in: query + schema: { type: string } + description: Диапазон `yyyy-MM-dd|yyyy-MM-dd`. + - name: LmsAttemptSearch[finished_at] + in: query + schema: { type: string } + responses: + 200: + description: Список попыток + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAttemptList' + + /admin/lms/lms-attempt/view: + get: + tags: [admin-lms-attempt] + summary: Одна попытка + operationId: adminLmsAttemptView + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 200: + description: Попытка + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAttempt' + + /admin/lms/lms-attempt/delete: + delete: + tags: [admin-lms-attempt] + summary: Сбросить (удалить) попытку + description: | + Soft-delete попытки. Если попытка ещё завершается (статус + `finishing`, фоновый воркер может её менять) — возвращается + HTTP 422 с `HttpJsonResult` (`success: false`, + `message.error = "Попытка сейчас завершается, попробуйте позже"`). + operationId: adminLmsAttemptDelete + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 200: + description: HttpJsonResult + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAdminHttpJsonResult' + 404: + description: Попытка не найдена. + 422: + description: Попытка ещё завершается — сброс невозможен. + + /admin/lms/lms-attempt/assessment: + get: + tags: [admin-lms-attempt] + summary: Получить попытку для оценки экспертом + description: | + Доступно для: + - админов с правом `learning-controls` или `learning-assign`, + - назначенного эксперта (по `LmsAttemptLogic::canAssessment`). + + Если попытка уже не в статусе `submitted` — возвращает + `success=false` + `message.type="info"` («Попытка была проверена + ранее!»). + operationId: adminLmsAttemptAssessment + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 200: + description: HttpJsonResult с попыткой в `data.attempt`. + content: + application/json: + schema: + allOf: + - $ref: '#/components/schemas/LmsAdminHttpJsonResult' + - type: object + properties: + data: + type: object + properties: + attempt: + $ref: '#/components/schemas/LmsAttempt' + + # ========================================================================= + # LMS — Категории каталога обучения (admin) + # ========================================================================= + /admin/lms/lms-category/tree: + get: + tags: [admin-lms-category] + summary: Иерархическое дерево категорий обучения + operationId: adminLmsCategoryTree + responses: + 200: + description: Дерево + content: + application/json: + schema: + $ref: '#/components/schemas/LmsCategoryTree' + + /admin/lms/lms-category/items: + get: + tags: [admin-lms-category] + summary: Узлы (категории + сущности) одного уровня + description: | + Без `id` — корень дерева. С `id` — содержимое выбранной категории + (поддеревья + привязанные сущности). + operationId: adminLmsCategoryItems + parameters: + - name: id + in: query + required: false + schema: { type: string, format: uuid } + responses: + 200: + description: Список узлов + content: + application/json: + schema: + type: array + items: + type: object + additionalProperties: true + + /admin/lms/lms-category/create: + post: + tags: [admin-lms-category] + summary: Создать категорию + description: | + Тело — поля `CategoryForm` + опциональный `parent_id` (UUID + родительского узла дерева). + operationId: adminLmsCategoryCreate + requestBody: + required: true + content: + application/x-www-form-urlencoded: + schema: + type: object + additionalProperties: true + required: [name] + properties: + name: { type: string } + parent_id: { type: string, format: uuid, nullable: true } + description: { type: string, nullable: true } + show_in_menu: { type: boolean, nullable: true } + responses: + 200: + description: HttpJsonResult с созданной категорией в `data`. + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAdminHttpJsonResult' + + /admin/lms/lms-category/update: + post: + tags: [admin-lms-category] + summary: Обновить узел дерева (категорию) + operationId: adminLmsCategoryUpdate + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + description: UUID узла дерева (CategoryTreeItem). + requestBody: + required: true + content: + application/x-www-form-urlencoded: + schema: + type: object + additionalProperties: true + responses: + 200: + description: HttpJsonResult + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAdminHttpJsonResult' + + /admin/lms/lms-category/delete: + delete: + tags: [admin-lms-category] + summary: Удалить категорию (рекурсивно с потомками) + operationId: adminLmsCategoryDelete + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 200: + description: HttpJsonResult + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAdminHttpJsonResult' + + /admin/lms/lms-category/create-items: + post: + tags: [admin-lms-category] + summary: Привязать сущности к категориям пачкой + description: | + Body — массив `{parent_id, entity_id, item_id}`. Все привязки + создаются в одной транзакции. + operationId: adminLmsCategoryCreateItems + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + type: object + properties: + parent_id: { type: string, format: uuid, nullable: true } + entity_id: { type: string, format: uuid } + item_id: { type: string, format: uuid } + responses: + 200: + description: HttpJsonResult + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAdminHttpJsonResult' + + /admin/lms/lms-category/move-item: + post: + tags: [admin-lms-category] + summary: Переместить привязку сущности в другую категорию + operationId: adminLmsCategoryMoveItem + parameters: + - name: category_id + in: query + required: true + schema: { type: string, format: uuid } + description: Целевая категория. + - name: entity_id + in: query + required: true + schema: { type: string, format: uuid } + requestBody: + required: false + content: + application/x-www-form-urlencoded: + schema: + type: object + properties: + item_id: + type: string + format: uuid + description: UUID конкретной привязки (опционально). + responses: + 200: + description: HttpJsonResult + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAdminHttpJsonResult' + + /admin/lms/lms-category/delete-item: + delete: + tags: [admin-lms-category] + summary: Удалить привязку сущности из дерева категорий + operationId: adminLmsCategoryDeleteItem + parameters: + - name: entity_id + in: query + required: true + schema: { type: string, format: uuid } + - name: item_id + in: query + required: false + schema: { type: string, format: uuid } + description: UUID конкретной привязки (опционально). + responses: + 200: + description: HttpJsonResult + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAdminHttpJsonResult' + + /admin/lms/lms-category/update-tree: + post: + tags: [admin-lms-category] + summary: Сменить родителя узла дерева + operationId: adminLmsCategoryUpdateTree + requestBody: + required: true + content: + application/x-www-form-urlencoded: + schema: + type: object + required: [childId] + properties: + childId: + type: string + format: uuid + parentId: + type: string + format: uuid + nullable: true + description: | + UUID нового родителя. Пусто — переместить в корень. + responses: + 200: + description: HttpJsonResult + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAdminHttpJsonResult' + + /admin/lms/lms-category/sort: + post: + tags: [admin-lms-category] + summary: Обновить порядок узлов дерева + operationId: adminLmsCategorySort + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + sort: + type: array + description: | + Структура сортировки в формате, ожидаемом + `CatalogManager::updateSort`. + items: + type: object + additionalProperties: true + responses: + 200: + description: HttpJsonResult + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAdminHttpJsonResult' + + # ========================================================================= + # LMS — Отчёты (admin) + # ========================================================================= + /admin/lms/lms-report/assignment-set-data: + get: + tags: [admin-lms-report] + summary: Данные отчёта по наборам назначений + description: | + Возвращает данные таблицы отчёта. Параметры фильтра передаются как + query-параметры и проксируются в соответствующий `ReportService`. + operationId: adminLmsReportAssignmentSetData + parameters: + - name: page + in: query + schema: { type: integer, minimum: 1, default: 1 } + - name: per-page + in: query + schema: { type: integer, minimum: 1, default: 20 } + - name: sort + in: query + schema: { type: string } + - name: ReportSearch[created_at] + in: query + schema: { type: string } + description: Диапазон `yyyy-MM-dd|yyyy-MM-dd`. + - name: ReportSearch[lms_assignment_set_id] + in: query + schema: { type: string, format: uuid } + - name: ReportSearch[user_id] + in: query + schema: { type: string, format: uuid } + - name: ReportSearch[department_id] + in: query + schema: { type: string, format: uuid } + responses: + 200: + description: Данные отчёта + content: + application/json: + schema: + $ref: '#/components/schemas/LmsReportData' + + /admin/lms/lms-report/content-data: + get: + tags: [admin-lms-report] + summary: Данные отчёта по учебным материалам + operationId: adminLmsReportContentData + parameters: + - name: page + in: query + schema: { type: integer, minimum: 1, default: 1 } + - name: per-page + in: query + schema: { type: integer, minimum: 1, default: 20 } + - name: sort + in: query + schema: { type: string } + - name: ReportSearch[lms_content_id] + in: query + schema: { type: string, format: uuid } + - name: ReportSearch[lms_content_type_id] + in: query + schema: { type: integer } + - name: ReportSearch[created_at] + in: query + schema: { type: string } + description: Диапазон `yyyy-MM-dd|yyyy-MM-dd`. + responses: + 200: + description: Данные отчёта + content: + application/json: + schema: + $ref: '#/components/schemas/LmsReportData' + + /admin/lms/lms-report/assignment-data: + get: + tags: [admin-lms-report] + summary: Данные отчёта по назначениям + operationId: adminLmsReportAssignmentData + parameters: + - name: page + in: query + schema: { type: integer, minimum: 1, default: 1 } + - name: per-page + in: query + schema: { type: integer, minimum: 1, default: 20 } + - name: sort + in: query + schema: { type: string } + - name: ReportSearch[user_id] + in: query + schema: { type: string, format: uuid } + - name: ReportSearch[lms_content_id] + in: query + schema: { type: string, format: uuid } + - name: ReportSearch[lms_assignment_set_id] + in: query + schema: { type: string, format: uuid } + - name: ReportSearch[department_id] + in: query + schema: { type: string, format: uuid } + - name: ReportSearch[status] + in: query + schema: { type: string } + - name: ReportSearch[created_at] + in: query + schema: { type: string } + description: Диапазон `yyyy-MM-dd|yyyy-MM-dd`. + - name: ReportSearch[deadline_at] + in: query + schema: { type: string } + description: Диапазон `yyyy-MM-dd|yyyy-MM-dd`. + responses: + 200: + description: Данные отчёта + content: + application/json: + schema: + $ref: '#/components/schemas/LmsReportData' + + /admin/lms/lms-report/learning-coverage-data: + get: + tags: [admin-lms-report] + summary: Данные отчёта «Охват обучения» + operationId: adminLmsReportLearningCoverageData + parameters: + - name: page + in: query + schema: { type: integer, minimum: 1, default: 1 } + - name: per-page + in: query + schema: { type: integer, minimum: 1, default: 20 } + - name: sort + in: query + schema: { type: string } + - name: ReportSearch[department_id] + in: query + schema: { type: string, format: uuid } + - name: ReportSearch[user_id] + in: query + schema: { type: string, format: uuid } + - name: ReportSearch[lms_content_id] + in: query + schema: { type: string, format: uuid } + responses: + 200: + description: Данные отчёта + content: + application/json: + schema: + $ref: '#/components/schemas/LmsReportData' + + /admin/lms/lms-report/quiz-choices-data: + get: + tags: [admin-lms-report] + summary: Данные отчёта «Распределение ответов по тестам» + operationId: adminLmsReportQuizChoicesData + parameters: + - name: page + in: query + schema: { type: integer, minimum: 1, default: 1 } + - name: per-page + in: query + schema: { type: integer, minimum: 1, default: 20 } + - name: sort + in: query + schema: { type: string } + - name: ReportSearch[lms_content_id] + in: query + schema: { type: string, format: uuid } + - name: ReportSearch[lms_assignment_set_id] + in: query + schema: { type: string, format: uuid } + responses: + 200: + description: Данные отчёта + content: + application/json: + schema: + $ref: '#/components/schemas/LmsReportData' + + /admin/lms/lms-report/assignment-set-excel: + post: + tags: [admin-lms-report] + summary: Поставить задачу на excel-экспорт отчёта по наборам назначений + description: | + Файл готовится асинхронно — опрашивать через `/file-processing/view`. + operationId: adminLmsReportAssignmentSetExcel + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/LmsReportExcelBody' + responses: + 200: + description: Задача поставлена + content: + application/json: + schema: + $ref: '#/components/schemas/LmsReportExcelResponse' + + /admin/lms/lms-report/content-excel: + post: + tags: [admin-lms-report] + summary: Excel-экспорт отчёта по учебным материалам + operationId: adminLmsReportContentExcel + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/LmsReportExcelBody' + responses: + 200: + description: Задача поставлена + content: + application/json: + schema: + $ref: '#/components/schemas/LmsReportExcelResponse' + + /admin/lms/lms-report/assignment-excel: + post: + tags: [admin-lms-report] + summary: Excel-экспорт отчёта по назначениям + operationId: adminLmsReportAssignmentExcel + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/LmsReportExcelBody' + responses: + 200: + description: Задача поставлена + content: + application/json: + schema: + $ref: '#/components/schemas/LmsReportExcelResponse' + + /admin/lms/lms-report/learning-coverage-excel: + post: + tags: [admin-lms-report] + summary: Excel-экспорт отчёта «Охват обучения» + operationId: adminLmsReportLearningCoverageExcel + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/LmsReportExcelBody' + responses: + 200: + description: Задача поставлена + content: + application/json: + schema: + $ref: '#/components/schemas/LmsReportExcelResponse' + + /admin/lms/lms-report/quiz-choices-excel: + post: + tags: [admin-lms-report] + summary: Excel-экспорт отчёта по ответам на тесты + operationId: adminLmsReportQuizChoicesExcel + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/LmsReportExcelBody' + responses: + 200: + description: Задача поставлена + content: + application/json: + schema: + $ref: '#/components/schemas/LmsReportExcelResponse' + + # ========================================================================= + # LMS — Редактор шаблонов сертификатов (admin) + # ========================================================================= + /admin/lms-certificate-editor: + get: + tags: [admin-lms-certificate-editor] + summary: Список шаблонов сертификатов + description: | + Доступно при правах `certificate-edit` или `certificate-assign`. + operationId: adminLmsCertificateEditorIndex + parameters: + - name: page + in: query + schema: { type: integer, minimum: 1, default: 1 } + - name: per-page + in: query + schema: { type: integer, minimum: 1, default: 20 } + responses: + 200: + description: Список шаблонов + content: + application/json: + schema: + $ref: '#/components/schemas/LmsCertificateTemplateList' + + /admin/lms-certificate-editor/view: + get: + tags: [admin-lms-certificate-editor] + summary: Один шаблон + operationId: adminLmsCertificateEditorView + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 200: + description: Шаблон сертификата + content: + application/json: + schema: + $ref: '#/components/schemas/LmsCertificateTemplate' + 404: + description: Шаблон сертификата не найден. + + /admin/lms-certificate-editor/create: + post: + tags: [admin-lms-certificate-editor] + summary: Создать шаблон сертификата + description: Требуется право `certificate-edit`. + operationId: adminLmsCertificateEditorCreate + requestBody: + required: true + content: + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/LmsCertificateTemplateBody' + responses: + 200: + description: Созданный шаблон (или `HttpJsonResult` с ошибками валидации). + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/LmsCertificateTemplate' + - $ref: '#/components/schemas/LmsAdminHttpJsonResult' + + /admin/lms-certificate-editor/update: + post: + tags: [admin-lms-certificate-editor] + summary: Обновить шаблон сертификата + operationId: adminLmsCertificateEditorUpdate + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + requestBody: + required: true + content: + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/LmsCertificateTemplateBody' + responses: + 200: + description: Обновлённый шаблон (или `HttpJsonResult` с ошибками валидации). + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/LmsCertificateTemplate' + - $ref: '#/components/schemas/LmsAdminHttpJsonResult' + 404: + description: Шаблон не найден. + + /admin/lms-certificate-editor/delete: + delete: + tags: [admin-lms-certificate-editor] + summary: Удалить шаблон сертификата + operationId: adminLmsCertificateEditorDelete + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 200: + description: Успешный ответ + content: + application/json: + schema: + type: object + properties: + success: { type: boolean, example: true } + 404: + description: Шаблон не найден. + + /admin/lms-certificate-editor/field-types: + get: + tags: [admin-lms-certificate-editor] + summary: Доступные типы полей для шаблонов сертификатов + description: | + Доступно при правах `certificate-edit` или `certificate-assign`. + operationId: adminLmsCertificateEditorFieldTypes + responses: + 200: + description: "Карта типов полей `{code: label}`." + content: + application/json: + schema: + type: object + additionalProperties: + type: string + + /admin/lms-certificate-editor/names: + get: + tags: [admin-lms-certificate-editor] + summary: Список названий шаблонов для фильтра + operationId: adminLmsCertificateEditorNames + responses: + 200: + description: "Карта `{id: name}`." + content: + application/json: + schema: + type: object + additionalProperties: + type: string + + # ========================================================================= + # LMS — Пользовательский API (cabinet + catalog) + # ========================================================================= + /lms/catalog: + get: + tags: [lms] + summary: Каталог учебных материалов для сотрудника + description: | + Возвращает текущий узел каталога LMS — категории + материалы, + доступные пользователю. + operationId: lmsCatalog + parameters: + - name: q + in: query + schema: { type: string } + description: Полнотекстовый поиск. + - name: id + in: query + schema: { type: string, format: uuid } + description: UUID категории. Без параметра — корень каталога. + responses: + 200: + description: Каталог + content: + application/json: + schema: + type: object + additionalProperties: true + + /lms/cabinet: + get: + tags: [lms] + summary: Назначения сотрудника (личный кабинет) + description: | + Список текущих назначений авторизованного пользователя + (DataProvider envelope). + operationId: lmsCabinet + parameters: + - name: page + in: query + schema: { type: integer, minimum: 1, default: 1 } + - name: per-page + in: query + schema: { type: integer, minimum: 1, default: 20 } + responses: + 200: + description: Список назначений + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAssignmentList' + + /lms/cabinet-info: + get: + tags: [lms] + summary: Вкладки/счётчики для кабинета + description: | + Структура вкладок кабинета (активные, обязательные, в работе и т. д.) + с количеством назначений по каждой. + operationId: lmsCabinetInfo + responses: + 200: + description: Структура вкладок + content: + application/json: + schema: + type: array + items: + type: object + additionalProperties: true + + /lms/info: + get: + tags: [lms] + summary: Информация о материале/назначении и доступности запуска + description: | + Возвращает данные `LmsLaunchInfo`: есть ли доступ, можно ли + запустить, локализованные сообщения, оставшиеся попытки и т. д. + + Допустимо передать `lms_content_id`, `lms_assignment_id` либо оба; + если передан только `lms_assignment_id`, `lms_content_id` будет + вычислен от назначения. + operationId: lmsInfo + parameters: + - name: lms_content_id + in: query + schema: { type: string, format: uuid } + - name: lms_assignment_id + in: query + schema: { type: string, format: uuid } + responses: + 200: + description: LmsLaunchInfo + content: + application/json: + schema: + type: object + additionalProperties: true + 404: + description: | + Материал не найден либо у пользователя нет к нему доступа + и нет активного назначения. + + /lms/start: + post: + tags: [lms] + summary: Старт прохождения — создаёт self-назначение и launch-URL + description: | + Проверяет права доступа и валидность запуска через `LmsLaunch`. + + - Если у пользователя нет назначения, но материал доступен по + группам, создаётся self-назначение. + - Если запуск запрещён (`canLaunch=false`), возвращается + `{success:false, message: <текст>}` без ошибки HTTP. + operationId: lmsStart + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [lms_content_id] + properties: + lms_content_id: + type: string + format: uuid + lms_assignment_id: + type: string + format: uuid + nullable: true + responses: + 200: + description: | + Результат запуска. + content: + application/json: + schema: + type: object + properties: + success: { type: boolean } + message: + oneOf: + - $ref: '#/components/schemas/LmsAdminMessage' + - type: string + - type: 'null' + data: + type: object + properties: + message: + $ref: '#/components/schemas/LmsAdminMessage' + url: + type: string + description: | + Подписанный launch-URL для открытия плеера + (обычно `/lms/launch/index?...`). + + /lms/lms-attempts: + get: + tags: [lms] + summary: Попытки авторизованного пользователя по назначению + description: | + Возвращает только попытки текущего пользователя. Запрещено для + назначений, у которых `canViewAttempt() === false` (HTTP 400). + operationId: lmsLmsAttempts + parameters: + - name: lms_assignment_id + in: query + required: true + schema: { type: string, format: uuid } + - name: page + in: query + schema: { type: integer, minimum: 1, default: 1 } + - name: per-page + in: query + schema: { type: integer, minimum: 1, default: 20 } + responses: + 200: + description: Список попыток + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAttemptList' + 400: + description: Попытки нельзя посмотреть для этого назначения. + 404: + description: Назначение не найдено либо принадлежит другому пользователю. + + /lms/lms-attempt-view: + get: + tags: [lms] + summary: Одна попытка авторизованного пользователя + operationId: lmsLmsAttemptView + parameters: + - name: lms_attempt_id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 200: + description: Попытка с расширенными полями. + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAttempt' + 404: + description: Попытка не найдена либо принадлежит другому пользователю. + + /lms/lms-content-view: + get: + tags: [lms] + summary: Один учебный материал (для пользователя) + description: | + Доступно, если у пользователя есть назначение на этот материал + либо материал доступен через `isAvailableByUserGroups()`. + operationId: lmsLmsContentView + parameters: + - name: lms_content_id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 200: + description: Материал + content: + application/json: + schema: + $ref: '#/components/schemas/LmsContent' + 404: + description: Материал недоступен. + + /lms/lms-assignment-view: + get: + tags: [lms] + summary: Одно назначение авторизованного пользователя + operationId: lmsLmsAssignmentView + parameters: + - name: lms_assignment_id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 200: + description: Назначение + content: + application/json: + schema: + $ref: '#/components/schemas/LmsAssignment' + 404: + description: Назначение не найдено. + + # ========================================================================= + # LMS — Прокси-маршруты плеера (не /api/v2, оставлены для справки) + # ========================================================================= + # /lms/launch/index?lms_content_id=&lms_assignment_id= — страница запуска плеера + # (HTML, не API). + # /lms/launch/proxy/{id}/{path} — статический контент SCORM/xAPI + # (CDN-style проксирование). + # /lms/lms-content/content-render?... — HTML-рендер материала для + # внутреннего фрейма. + # Эти эндпоинты возвращают HTML/бинарные данные и не покрываются OpenAPI-схемой. + components: securitySchemes: SessionAuth: @@ -13773,6 +15488,500 @@ components: $ref: '#/components/schemas/_links' _meta: $ref: '#/components/schemas/_meta' + # ===================================================================== + # LMS — общие envelope-схемы + # ===================================================================== + LmsAdminFieldError: + type: object + properties: + attribute: { type: string, example: name } + text: { type: string, example: "Необходимо заполнить «Название»." } + + LmsAdminMessage: + type: object + properties: + type: + type: string + enum: [success, info, warning, error] + text: { type: string } + + LmsAdminHttpJsonResult: + type: object + description: | + Стандартная обёртка ответов для write-эндпоинтов LMS + (`HttpJsonResult`). Структура: `success` + опциональный `data` + + массив `errors` (валидация формы) + опциональный `message` + (доменное предупреждение/информация). + properties: + success: { type: boolean, example: true } + data: + oneOf: + - type: object + - type: array + - type: 'null' + nullable: true + errors: + type: array + items: + $ref: '#/components/schemas/LmsAdminFieldError' + message: + oneOf: + - $ref: '#/components/schemas/LmsAdminMessage' + - type: 'null' + + LmsAdminHttpJsonResultWithId: + allOf: + - $ref: '#/components/schemas/LmsAdminHttpJsonResult' + - type: object + properties: + data: + type: object + properties: + id: + type: string + format: uuid + + # ===================================================================== + # LMS — Content (учебный материал) + # ===================================================================== + LmsContent: + type: object + properties: + id: { type: string, format: uuid } + name: { type: string } + description: { type: string, nullable: true } + file_id: { type: string, format: uuid, nullable: true } + activity_id: { type: string, nullable: true, description: "SCORM/xAPI activity id" } + status_id: { type: integer } + max_attempts: { type: integer, nullable: true } + deadline_days: { type: integer, nullable: true } + time_limit_sec: { type: integer, nullable: true } + lms_content_type_id: { type: integer } + lms_api_type_id: { type: integer, nullable: true } + lms_content_provider_id: { type: integer, nullable: true } + success_score_scaled: { type: number, format: float, nullable: true } + success_score: { type: number, format: float, nullable: true } + success_progress: { type: number, format: float, nullable: true } + created_at: { type: string, format: date-time } + updated_at: { type: string, format: date-time, nullable: true } + created_user_id: { type: string, format: uuid, nullable: true } + updated_user_id: { type: string, format: uuid, nullable: true } + thumb_file_id: { type: string, format: uuid, nullable: true } + feedback_survey_template_id: { type: string, format: uuid, nullable: true } + need_assessment: { type: boolean } + deadlineDays: { type: string, description: "Локализованный текст" } + lmsContentType: { type: string } + lmsApiType: { type: string, nullable: true } + lmsContentProvider: { type: string, nullable: true } + status: { type: string } + iconUrl: { type: string, nullable: true } + thumbUrl: { type: string, nullable: true } + imageUrl: { type: string, nullable: true } + url: { type: string, nullable: true } + + LmsContentList: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/LmsContent' + _links: + $ref: '#/components/schemas/_links' + _meta: + $ref: '#/components/schemas/_meta' + + LmsItemsList: + type: object + properties: + data: + type: array + items: + type: object + properties: + id: { type: string, format: uuid } + name: { type: string } + _links: + $ref: '#/components/schemas/_links' + _meta: + $ref: '#/components/schemas/_meta' + + LmsContentItemsList: + $ref: '#/components/schemas/LmsItemsList' + + LmsContentFormBody: + type: object + description: | + Поля формы `LmsContentForm`. Передаются под префиксом + `LmsContentForm[]` (yii-style). + properties: + name: { type: string } + description: { type: string } + statusId: { type: integer } + maxAttempts: { type: integer, minimum: 0, maximum: 100 } + deadlineDays: { type: integer, minimum: 0, maximum: 32767 } + successProgress: { type: number, minimum: 0, maximum: 1 } + thumbFileId: { type: string, format: uuid, nullable: true } + feedbackSurveyTemplateId: { type: string, format: uuid, nullable: true } + certificateId: { type: string, format: uuid, nullable: true } + showInProfile: { type: boolean } + needAssessment: { type: boolean } + expiredInDays: { type: integer, nullable: true } + expiredInMonths: { type: integer, nullable: true } + expiredInYears: { type: integer, nullable: true } + organizationId: { type: string, format: uuid, nullable: true } + categoryTreeItemId: { type: string, format: uuid, nullable: true } + isRefreshAttempt: { type: boolean } + isRefreshAssignment: { type: boolean } + + # ===================================================================== + # LMS — Assignment / AssignmentSet / AutoAssignment / Attempt + # ===================================================================== + LmsAssignment: + type: object + properties: + id: { type: string, format: uuid } + lms_content_id: { type: string, format: uuid } + user_id: { type: string, format: uuid } + lms_assignment_set_id: { type: string, format: uuid, nullable: true } + attempts_max: { type: integer, nullable: true } + attempts_left: { type: integer, nullable: true } + created_at: { type: string, format: date-time } + created_user_id: { type: string, format: uuid, nullable: true } + deadline_at: { type: string, format: date-time, nullable: true } + is_active: { type: boolean } + is_mandatory: { type: boolean } + available_date: { type: string, format: date, nullable: true } + parent_id: { type: string, format: uuid, nullable: true } + parent_program_id: { type: string, format: uuid, nullable: true } + allow_submit_grace: { type: boolean } + type_id: { type: integer } + progress: { type: number, format: float, nullable: true } + status: { type: string } + typeName: { type: string } + isProgramPart: { type: boolean } + createdAtLocalized: { type: string } + availableDateLocalized: { type: string, nullable: true } + deadlineAtLocalized: { type: string, nullable: true } + bestScore: { type: number, nullable: true } + bestScoreScaled: { type: number, nullable: true } + bestScoreScaledText: { type: string, nullable: true } + bestScoreScaledFormatted: { type: string, nullable: true } + progressFormatted: { type: string } + statusText: { type: string } + attemptsText: { type: string } + daysInterval: { type: integer, nullable: true } + daysIntervalText: { type: string, nullable: true } + canLaunch: { type: boolean } + canViewAttempt: { type: boolean } + + LmsAssignmentList: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/LmsAssignment' + _links: + $ref: '#/components/schemas/_links' + _meta: + $ref: '#/components/schemas/_meta' + + LmsAssignmentFormBody: + type: object + description: Поля `LmsAssignmentForm` для назначений и наборов. + required: [name, content] + properties: + name: { type: string, maxLength: 255 } + content: + type: object + additionalProperties: true + description: JSONB — выбранные курсы/материалы. + users: + type: object + additionalProperties: true + description: JSONB — выбранные пользователи. + user_groups: + type: object + additionalProperties: true + description: JSONB — выбранные группы. + content_params: + type: object + additionalProperties: true + description: JSONB — параметры прохождения курсов. + start_at: + type: string + nullable: true + description: Дата первого назначения (`yyyy-MM-dd`). + type_id: { type: integer, nullable: true } + allow_submit_grace: { type: boolean } + send_notification: { type: boolean } + notification_weekdays: + type: array + items: { type: integer } + notification_hours: + type: array + items: { type: integer } + groupRemoveOldUsers: { type: boolean } + params: + type: object + additionalProperties: true + description: JSONB `LmsAssignmentSetParams`. + + LmsUpdateAssignmentsFormBody: + type: object + description: Поля формы `LmsUpdateAssignmentsForm`. + required: [cache_key] + properties: + cache_key: + type: string + format: uuid + description: Ключ закэшированной выборки назначений. + allow_submit_grace: { type: boolean, nullable: true } + available_date: { type: string, nullable: true } + deadline_at: { type: string, nullable: true } + attempts_max: + type: integer + nullable: true + minimum: 1 + maximum: 100 + description: | + Прибавляется (а не заменяет) к существующему значению попыток. + NULL остаётся NULL. + + LmsAssignmentSet: + type: object + properties: + id: { type: string, format: uuid } + name: { type: string } + created_at: { type: string, format: date-time } + created_user_id: { type: string, format: uuid, nullable: true } + is_active: { type: boolean } + lms_assignment_set_status_id: { type: integer } + users: + type: object + additionalProperties: true + nullable: true + user_groups: + type: object + additionalProperties: true + nullable: true + auto_assignment_id: { type: string, format: uuid, nullable: true } + deadline_at: { type: string, format: date-time, nullable: true } + allow_submit_grace: { type: boolean } + send_notification: { type: boolean } + notification_weekdays: + type: array + items: { type: integer } + notification_hours: + type: array + items: { type: integer } + created_from: { type: string, nullable: true } + created_at_localized: { type: string } + created_user_name: { type: string, nullable: true } + + LmsAssignmentSetList: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/LmsAssignmentSet' + _links: + $ref: '#/components/schemas/_links' + _meta: + $ref: '#/components/schemas/_meta' + + LmsAutoAssignment: + type: object + properties: + id: { type: string, format: uuid } + name: { type: string } + users: + type: object + additionalProperties: true + nullable: true + user_groups: + type: object + additionalProperties: true + nullable: true + created_at: { type: string, format: date-time } + created_user_id: { type: string, format: uuid, nullable: true } + is_active: { type: boolean } + start_at: { type: string, format: date, nullable: true } + type_id: { type: integer } + period: + type: object + additionalProperties: true + next_assign_at: { type: string, format: date-time, nullable: true } + last_assign_at: { type: string, format: date-time, nullable: true } + allow_submit_grace: { type: boolean } + send_notification: { type: boolean } + notification_weekdays: + type: array + items: { type: integer } + notification_hours: + type: array + items: { type: integer } + created_at_localized: { type: string } + created_user_name: { type: string, nullable: true } + type_name: { type: string } + + LmsAutoAssignmentList: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/LmsAutoAssignment' + _links: + $ref: '#/components/schemas/_links' + _meta: + $ref: '#/components/schemas/_meta' + + LmsAutoAssignmentFormBody: + allOf: + - $ref: '#/components/schemas/LmsAssignmentFormBody' + - type: object + required: [type_id] + properties: + period: + type: object + additionalProperties: true + description: | + JSONB `AutoAssignmentPeriod` — режим периодичности. + + LmsAttempt: + type: object + properties: + id: { type: string, format: uuid } + user_id: { type: string, format: uuid } + activity_id: { type: string, nullable: true } + score: { type: number, nullable: true } + score_scaled: { type: number, nullable: true } + max_possible_score: { type: number, nullable: true } + progress: { type: number, nullable: true } + started_at: { type: string, format: date-time, nullable: true } + finished_at: { type: string, format: date-time, nullable: true } + expire_at: { type: string, format: date-time, nullable: true } + status: { type: string } + need_assessment: { type: boolean } + expert_user_id: { type: string, format: uuid, nullable: true } + scoreScaledFormatted: { type: string, nullable: true } + scoreScaledFormattedSymbol: { type: string, nullable: true } + progressFormatted: { type: string, nullable: true } + progressFormattedSymbol: { type: string, nullable: true } + statusName: { type: string } + started: { type: boolean } + finished: { type: boolean } + durationSeconds: { type: integer, nullable: true } + durationSecondsText: { type: string, nullable: true } + durationSecondsFormatted: { type: string, nullable: true } + isStatusFinishing: { type: boolean } + + LmsAttemptList: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/LmsAttempt' + _links: + $ref: '#/components/schemas/_links' + _meta: + $ref: '#/components/schemas/_meta' + + # ===================================================================== + # LMS — Category tree / reports / certificates + # ===================================================================== + LmsCategoryTree: + type: array + description: | + Древовидный список узлов каталога LMS. Элементы — JSON-объекты + категорий c вложенными `children` (см. `CatalogTreeBuilder`). + items: + type: object + additionalProperties: true + + LmsReportData: + type: object + description: | + Результат `LmsReportPresenter::getData` — поля и структура зависят + от конкретного `ReportService`. Обычно включает `rows`, `columns`, + `summary`/`totals`. + additionalProperties: true + + LmsReportExcelBody: + type: object + properties: + columns: + type: array + items: { type: string } + description: | + Список ключей колонок, которые попадают в xlsx. Если пусто — + берётся дефолт сервиса. + + LmsReportExcelResponse: + type: object + description: | + Задача на генерацию Excel поставлена в очередь. Клиент поллит статус + файла через `GET /api/v2/file/view?id=`. + properties: + success: + type: boolean + example: true + file_id: + type: string + format: uuid + description: UUID созданного файла (статус NEEDS_PROCESSING). + + LmsCertificateTemplate: + type: object + properties: + id: { type: string, format: uuid } + name: { type: string } + file_id: { type: string, format: uuid } + created_at: { type: string, format: date-time } + updated_at: { type: string, format: date-time, nullable: true } + text_fields: + type: array + items: + type: object + additionalProperties: true + description: Массив описаний текстовых полей шаблона. + background_mode: { type: string, nullable: true } + formattedCreatedAt: { type: string } + createdBy: { type: string, nullable: true } + createdUserName: { type: string, nullable: true } + created_user_id: { type: string, format: uuid, nullable: true } + + LmsCertificateTemplateList: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/LmsCertificateTemplate' + _links: + $ref: '#/components/schemas/_links' + _meta: + $ref: '#/components/schemas/_meta' + + LmsCertificateTemplateBody: + type: object + description: | + Поля модели `Certificate` (`name`, `file_id`, `text_fields`, + `background_mode`). + properties: + name: { type: string } + file_id: { type: string, format: uuid } + text_fields: + type: array + items: + type: object + additionalProperties: true + background_mode: { type: string, nullable: true } + parameters: boardDateTypeParam: