Author SHA1 Message Date
kirill 7a50001f0b описание основного апи 2026-10-05 15:09:53 +06:00
kirill 56a357009c visibility_target_id 2026-06-22 14:41:40 +06:00
denis e4e34d595c Merge branch 'feature/api-doc-date-format' into 'master'
api-doc: уточнил формат created_at и др. date-range фильтров

See merge request hrbox-public/api!40
2026-06-15 06:29:46 +00:00
DenisandClaude Opus 4.7 bf13d71699 api-doc: уточнил формат created_at и др. date-range фильтров
Алекс (sokolove) сообщил, что фильтр created_at в
/admin/wallet-transaction возвращает 422 при передаче значения
с временем суток. ValidationRules::ruleDateRange использует
format yyyy-MM-dd; время не поддерживается, формат значения —
yyyy-MM-dd|yyyy-MM-dd.

Обновлены формулировки описаний фильтров и полей схем:

- /user/index: created_at, last_login_at
- /admin/wallet: created_at
- /admin/wallet-transaction: created_at
- /admin/employment: created_at, employment_date, fired_date
- AdminEmployment schema: employment_date, fired_date

Везде явно указан формат yyyy-MM-dd. Для диапазонов добавлена
пометка, что указание времени суток не поддерживается.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-15 09:24:47 +03:00
Кирилл Голодаев 02e4440b68 Merge branch 'feature/H-953' into 'master'
feature/H-953

See merge request hrbox-public/api!39
2026-06-09 05:26:57 +00:00
mitrikov b680b8e73e feat: добавил инфу по открыткам 2026-06-09 17:01:51 +12:00
denis 1037669ab3 Merge branch 'feature/H-3657' into 'master'
H-3657: задокументировал user-list-cache (источник usersListKey)

See merge request hrbox-public/api!36
2026-05-28 14:02:47 +00:00
DenisandClaude Opus 4.7 58a32b1768 H-3657: вычитка стиля и корректности данных в MR !36
Привёл описания /user/index, /user/search, /file/prepare-upload,
/file/finish-upload, /user-list-cache/* и связанных схем
(UserListForm, UserListData, File, FilePrepareUploadBody,
FilePrepareUploadResponse) к единому нейтральному документационному
стилю — как в H-3821.

Убраны: разговорные обороты («юзер», «флоу», «грабли», «отдаёте»,
«придумываете», «протух», «дефолт», «компактный»), эмодзи в
заголовках секций, ###-маркеры разделов внутри description.
Все формулировки переведены в третье лицо.

Поправлены данные:
- is_public в FilePrepareUploadBody: integer enum [0,1] → boolean
  (соответствует @property boolean is_public в File model).
- /user/search?limit: убран искусственный maximum: 100, в контроллере
  верхнего предела нет (только default = 10).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 17:00:40 +03:00
denis d1caea1cfa Merge branch 'feature/H-3821' into 'master'
H-3821: задокументировал /admin/employment в v2 swagger

See merge request hrbox-public/api!37
2026-05-28 13:45:35 +00:00
DenisandClaude Opus 4.7 0ce01297a7 H-3821: переписал описание /admin/employment в нейтральный документационный стиль
Убрал разговорные обороты («главный кейс», «уволенные», «совместительства»,
«юзер», «UUID юзера», «то самое значение», «cross-tenant», «нет права»,
«ilike-поиск»). Описания параметров, полей схемы и ответов
переведены в нейтральный документационный регистр без жаргона
и эмоциональной разметки.

Технический смысл сохранён полностью — изменения только стилистические.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 16:35:46 +03:00
DenisandClaude Opus 4.7 6ad75bdd1e H-3821: задокументировал /admin/employment в v2 swagger
Новый admin read-only API трудоустройств. Основной кейс —
маппинг (origin_id, origin_organization_id) → user_id для
интеграторов (web-zaim, sokolove и др.).

- Тег admin-employment (Methods for admin read-only access...).
- GET /admin/employment: index с полным набором фильтров
  EmploymentSearch (origin_id[], origin_organization_id, user_id[],
  department_id, chief_id, is_main, status_id, reg_status_id,
  employment_date/fired_date/created_at range, name/position ilike,
  user_list_key, chief_only*, multipleEmployment).
- GET /admin/employment/view?id=<uuid>: одна запись.
- Доступ: user-edit (тот же perm что в legacy /api/employment v1).
- Схемы AdminEmployment, AdminEmploymentList, AdminEmploymentUserShort,
  AdminEmploymentChiefUserShort, AdminEmploymentDepartmentShort.
- В описании метода — главный кейс маппинга origin → user_id,
  совместительства, поведение uvol'нённых, батч origin_id[].

Источники: контроллер app\controllers\api\v2\admin\EmploymentController,
testrix tests/v2/admin/test_admin_employment.py +
hrbox/models/v2/AdminEmploymentModel.py (pydantic).
Проверено живьём на denis.hrbox.io: totalCount=9393, все поля
схемы совпадают с реальным ответом.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 16:01:35 +03:00
DenisandClaude Opus 4.7 37203aee1b H-3657: задокументировал /file/prepare-upload и /file/finish-upload
Без этих эндпоинтов excel-import flow для wallet-транзакций
неполный — интегратор не понимает откуда взять file_id для
POST /admin/wallet-transaction/excel-processing.

- Новый тег `file` (Methods for uploading files via signed-URL...).
- POST /file/prepare-upload: создаёт File-запись + возвращает signedUrl
  для PUT-загрузки бинарника напрямую в S3.
- POST /file/finish-upload?id=<uuid>: помечает файл как UPLOADED, после
  чего file_id можно использовать в downstream-флоу.
- Подробная описание двухшагового флоу (prepare → PUT signedUrl → finish)
  в описании prepare-upload.
- Идемпотентность через повторный prepare-upload с тем же id.
- Схемы File (полная), FilePrepareUploadBody, FilePrepareUploadResponse.
- В WalletExcelFormBody.file_id ссылка на этот upload-флоу — раньше
  было просто «UUID предварительно загруженного xlsx».

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 16:49:54 +03:00
DenisandClaude Opus 4.7 b8d17240ab H-3657: задокументировал /user/index и /user/search
Источник user_id для дальнейшей передачи в user-list-cache.
Раньше в swagger был только /user/profile (один по id) и /user/items
(минимальный список), но не было пагинированного индекса
с фильтрами — а именно через /user/index интегратор собирает
получателей для массового начисления валюты.

- GET /user/index: пагинация (per-page 1..20), сортировка, фильтры
  по основным атрибутам UserSearch (id, email, name, first_name,
  last_name, department_id, reg_status_id, group_id, position, ...),
  expand-поля.
- GET /user/search?q=&limit=&offset=: быстрый компактный поиск
  по ФИО/email/должности. Возвращает {q, users:[{id, name, position,
  departmentName, isBoss, ...}]}. Требует право show-structure-names —
  иначе users:[].

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 16:06:44 +03:00
DenisandClaude Opus 4.7 1032e5b522 H-3657: задокументировал user-list-cache (источник usersListKey)
Без этого интегратор не понимает откуда взять usersListKey для
POST /admin/wallet-transaction/create.

- Тег user-list-cache (Methods for caching ad-hoc employee selections...).
- POST /user-list-cache/set-user-list: тело {key, userList:{usersId,...}}.
  В описании явно прописал что Content-Type обязательно application/json —
  через form-urlencoded вложенный JsonModel не парсится, и сервер
  молча сохраняет пустую выборку (грабли которые я сам и наступил
  во время smoke-теста).
- GET /user-list-cache/user-list-data?key=<key>: возвращает развёрнутую
  выборку (users, departments, userGroups, ...). Схема ответа проверена
  живьём на denis.hrbox.io — все ключи совпадают.
- Схемы UserListForm, UserListCacheSetBody, UserListData.
- В описании POST /admin/wallet-transaction/create добавил секцию
  «Как получить usersListKey» с пошаговым флоу и ссылкой.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 15:51:23 +03:00
denis f86becd7ff Merge branch 'feature/H-3657' into 'master'
H-3657: PAT how-to → описание метода create, тэги/info → короткие EN

See merge request hrbox-public/api!35
2026-05-22 12:42:08 +00:00
DenisandClaude Opus 4.7 92d9c73b0c H-3657: description/summary метода create — обратно на русский
Соглашение: info.description и теги — короткое EN (как workflow,
wallet и др.), а внутри самого метода (summary + description) —
русский, потому что туда смотрит уже сам интегратор и важно дать
максимально понятный how-to. Возвращаю русский для
POST /user-api-token/create.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 15:39:40 +03:00
DenisandClaude Opus 4.7 161dc83b21 H-3657: PAT how-to → описание метода create, тэги/info → короткие EN
- info.description: убрал большой блок «Авторизация по личному API-токену»
  (он висел на стартовой странице Swagger UI). Вместо него — одна
  английская строка-указатель на user-api-token methods, в стиле
  остального вступления.
- BearerAuth securityScheme: однострочное EN-описание.
- Теги admin-wallet, admin-wallet-transaction, file-processing,
  user-api-token, admin-user-api-token: переведены в формат
  «Methods for ...» (как workflow, wallet, shop и т.д.) — короткая
  английская строка на тег.
- POST /user-api-token/create description: подробный how-to (создание,
  Bearer-header, tenant-резолв, отсутствие scopes, lifecycle,
  isValidForDisplay-caveat, запрет на управление под Bearer) — теперь
  лежит здесь, на английском, и сворачивается в UI вместе с эндпоинтом.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 15:17:47 +03:00
2 changed files with 2308 additions and 17 deletions
+680
View File
@@ -0,0 +1,680 @@
openapi: 3.0.3
info:
title: HRBox API
version: 1.0.0
description: |
API для чтения подразделений, трудоустройств и пользователей.
Все методы требуют авторизованную сессию HRBox и соответствующее право доступа.
Ответ содержит массив `data` и метаданные пагинации `_meta`.
servers:
- url: /api
tags:
- name: department
description: Подразделения организационной структуры
- name: employment
description: Трудоустройства пользователей
- name: user
description: Пользователи
paths:
/department:
get:
tags: [department]
summary: Получить список подразделений
operationId: getDepartments
description: Возвращает активные подразделения и организации.
x-permissions:
- show-structure-page
parameters:
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/PerPage'
- $ref: '#/components/parameters/Sort'
- $ref: '#/components/parameters/Fields'
- $ref: '#/components/parameters/Expand'
- name: id
in: query
description: ID подразделений через запятую
style: form
explode: false
schema:
type: array
items:
type: string
format: uuid
- name: name
in: query
description: Поиск по названию
schema:
type: string
- name: parent_id
in: query
description: ID родительского подразделения
schema:
type: string
format: uuid
- name: chief_id
in: query
description: ID руководителя
schema:
type: string
format: uuid
- name: is_organization
in: query
description: Признак организации
schema:
type: boolean
- name: is_null_parent_id
in: query
description: Только корневые подразделения
schema:
type: boolean
- name: status_id
in: query
description: Статусы подразделений через запятую
style: form
explode: false
schema:
type: array
items:
type: integer
- name: chief_only
in: query
description: Только подразделения текущего руководителя
schema:
type: boolean
- name: for_boss
in: query
description: Только управляемые текущим пользователем поддеревья
schema:
type: boolean
responses:
'200':
description: Список подразделений
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/PaginatedResponse'
- type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Department'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
/employment:
get:
tags: [employment]
summary: Получить список трудоустройств
operationId: getEmployments
x-permissions:
- user-edit
parameters:
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/PerPage'
- $ref: '#/components/parameters/Sort'
- $ref: '#/components/parameters/Fields'
- $ref: '#/components/parameters/Expand'
- name: id
in: query
description: ID трудоустройства
schema:
type: string
format: uuid
- name: user_id
in: query
description: ID пользователя
schema:
type: string
format: uuid
- name: department_id
in: query
description: ID подразделения; учитывается его поддерево
schema:
type: string
format: uuid
- name: chief_id
in: query
description: ID трудоустройства руководителя
schema:
type: string
format: uuid
- name: position
in: query
description: Поиск по должности
schema:
type: string
- name: is_main
in: query
description: Только основное трудоустройство
schema:
type: boolean
- name: status_id
in: query
description: Статус трудоустройства
schema:
type: integer
- name: org_num
in: query
description: Табельные номера через запятую
style: form
explode: false
schema:
type: array
items:
type: string
- name: created_at
in: query
description: Дата или диапазон дат создания в формате `from|to`
schema:
type: string
- name: first_name
in: query
description: Поиск по имени
schema:
type: string
- name: last_name
in: query
description: Поиск по фамилии
schema:
type: string
- name: name
in: query
description: Поиск по имени и фамилии пользователя
schema:
type: string
- name: employment_date
in: query
description: Дата трудоустройства
schema:
type: string
format: date
- name: fired_date
in: query
description: Дата увольнения
schema:
type: string
format: date
- name: origin_id
in: query
description: Внешние ID через запятую
style: form
explode: false
schema:
type: array
items:
type: string
- name: origin_organization_id
in: query
description: Внешний ID организации
schema:
type: string
- name: reg_status_id
in: query
description: Регистрационные статусы пользователей через запятую
style: form
explode: false
schema:
type: array
items:
type: integer
- name: user_list_key
in: query
description: Ключ сохранённого списка пользователей
schema:
type: string
format: uuid
- name: chief_only
in: query
description: Текущий пользователь и его прямые подчинённые
schema:
type: boolean
- name: chief_only_all
in: query
description: Текущий пользователь и все его подчинённые
schema:
type: boolean
- name: multipleEmployment
in: query
description: Фильтр по наличию нескольких трудоустройств
schema:
type: boolean
- name: searchInAllSubDepartments
in: query
description: Искать во всех вложенных подразделениях
schema:
type: boolean
responses:
'200':
description: Список трудоустройств
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/PaginatedResponse'
- type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Employment'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
/user:
get:
tags: [user]
summary: Получить список пользователей
operationId: getUsers
x-permissions:
anyOf:
- user-list
- show-user-page
- user-invite
- authenticated user with reports
parameters:
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/PerPage'
- $ref: '#/components/parameters/Sort'
- $ref: '#/components/parameters/Fields'
- $ref: '#/components/parameters/Expand'
- name: searchQuery
in: query
description: Сквозной полнотекстовый поиск пользователей
schema:
type: string
- name: q
in: query
description: Поиск по имени
schema:
type: string
- name: id
in: query
description: ID пользователей через запятую
style: form
explode: false
schema:
type: array
items:
type: string
format: uuid
- name: not_id
in: query
description: Исключить пользователя по ID
schema:
type: string
format: uuid
- name: email
in: query
description: Поиск по электронной почте
schema:
type: string
- name: phone_auth
in: query
description: Поиск по телефону авторизации
schema:
type: string
- name: name
in: query
description: Поиск по имени, фамилии и отчеству
schema:
type: string
- name: first_name
in: query
description: Поиск по имени
schema:
type: string
- name: middle_name
in: query
description: Поиск по отчеству
schema:
type: string
- name: last_name
in: query
description: Поиск по фамилии
schema:
type: string
- name: department_id
in: query
description: ID подразделения; учитывается его поддерево
schema:
type: string
format: uuid
- name: chief_id
in: query
description: ID руководителя
schema:
type: string
format: uuid
- name: position
in: query
description: Поиск по должности
schema:
type: string
- name: is_external
in: query
description: Признак внешнего пользователя
schema:
type: boolean
- name: reg_status_id
in: query
description: Регистрационные статусы через запятую
style: form
explode: false
schema:
type: array
items:
type: integer
- name: gender_id
in: query
description: Пол пользователя; несколько значений через запятую
style: form
explode: false
schema:
type: array
items:
type: integer
- name: duty_id
in: query
description: ID внутренней услуги
schema:
type: string
format: uuid
- name: birthday_date
in: query
description: Дата или диапазон дат рождения
schema:
type: string
- name: created_at
in: query
description: Дата или диапазон дат создания в формате `from|to`
schema:
type: string
- name: updated_at
in: query
description: Дата или диапазон дат изменения
schema:
type: string
- name: employment_date
in: query
description: Дата или диапазон дат трудоустройства
schema:
type: string
- name: is_boss
in: query
description: Признак руководителя
schema:
type: boolean
- name: group_id
in: query
description: ID группы пользователей
schema:
type: string
format: uuid
- name: status
in: query
description: ID персональных статусов через запятую
style: form
explode: false
schema:
type: array
items:
type: string
format: uuid
- name: survey_id
in: query
description: ID опроса
schema:
type: string
format: uuid
- name: survey_360_matrix_is_approved
in: query
description: Статус согласования матрицы 360
schema:
type: boolean
- name: company
in: query
description: Поиск по компании
schema:
type: string
- name: spec_id
in: query
description: ID профессиональной области
schema:
type: string
format: uuid
- name: chief_only
in: query
description: Текущий пользователь и его прямые подчинённые
schema:
type: boolean
- name: chief_only_all
in: query
description: Текущий пользователь и все его подчинённые
schema:
type: boolean
- name: user_list_key
in: query
description: Ключ сохранённого списка пользователей
schema:
type: string
format: uuid
- name: withoutEmployment
in: query
description: Только пользователи без трудоустройств
schema:
type: boolean
- name: searchInAllSubDepartments
in: query
description: Искать во всех вложенных подразделениях
schema:
type: boolean
responses:
'200':
description: Список пользователей
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/PaginatedResponse'
- type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/User'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
components:
parameters:
Page:
name: page
in: query
description: Номер страницы, начиная с 1
schema:
type: integer
minimum: 1
default: 1
PerPage:
name: per-page
in: query
description: Количество элементов на странице
schema:
type: integer
minimum: 1
default: 20
Sort:
name: sort
in: query
description: Поля сортировки через запятую; префикс `-` задаёт сортировку по убыванию
schema:
type: string
Fields:
name: fields
in: query
description: Возвращаемые поля через запятую
schema:
type: string
Expand:
name: expand
in: query
description: Дополнительные связанные данные через запятую
schema:
type: string
responses:
Unauthorized:
description: Пользователь не авторизован
Forbidden:
description: Недостаточно прав
schemas:
PaginatedResponse:
type: object
required: [data, _meta]
properties:
data:
type: array
items: {}
_meta:
$ref: '#/components/schemas/PaginationMeta'
PaginationMeta:
type: object
required: [totalCount, pageCount, currentPage, perPage]
properties:
totalCount:
type: integer
example: 42
pageCount:
type: integer
example: 3
currentPage:
type: integer
example: 1
perPage:
type: integer
example: 20
Department:
type: object
properties:
id:
type: string
format: uuid
name:
type: string
description:
type: string
nullable: true
parent_id:
type: string
format: uuid
nullable: true
chief_id:
type: string
format: uuid
nullable: true
is_organization:
type: boolean
status_id:
type: integer
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
Employment:
type: object
properties:
id:
type: string
format: uuid
user_id:
type: string
format: uuid
department_id:
type: string
format: uuid
nullable: true
chief_id:
type: string
format: uuid
nullable: true
position:
type: string
nullable: true
is_main:
type: boolean
employment_date:
type: string
format: date
nullable: true
fired_date:
type: string
format: date
nullable: true
status_id:
type: integer
org_num:
type: string
nullable: true
User:
type: object
properties:
id:
type: string
format: uuid
first_name:
type: string
middle_name:
type: string
nullable: true
last_name:
type: string
name:
type: string
birthday_date:
type: string
format: date
nullable: true
reg_status_id:
type: integer
gender_id:
type: integer
nullable: true
city_id:
type: string
format: uuid
nullable: true
company:
type: string
nullable: true
is_external:
type: boolean
photo_file_id:
type: string
format: uuid
nullable: true
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
+1628 -17
View File
File diff suppressed because it is too large Load Diff