From b7b136be0c27cb0752e0e25bbae2875b3f110dca Mon Sep 17 00:00:00 2001 From: Anton Pomorzin Date: Wed, 6 May 2026 11:40:39 +0500 Subject: [PATCH 1/2] =?UTF-8?q?H-3656:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20Wallet=20admin=20API=20=D0=B2=20v2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Новые эндпоинты: - GET /admin/wallet[/view] — кошельки сотрудников (read-only) - POST /admin/wallet/export-excel - GET /admin/wallet-transaction[/view] — транзакции, admin-вид - POST /admin/wallet-transaction/create — массовое начисление/списание по форме - POST /admin/wallet-transaction/create-from-excel — проведение по результату парсинга - POST /admin/wallet-transaction/excel-processing — парсинг xlsx (file_id + mappings) - POST /admin/wallet-transaction/export-excel - GET /file-processing[/view] — статусы FileProcessing для поллинга Permission: wallets-transactions, требует enableWallet=true у тенанта. Co-Authored-By: Claude Opus 4.7 (1M context) --- v2/swagger.yaml | 520 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 520 insertions(+) diff --git a/v2/swagger.yaml b/v2/swagger.yaml index 7571e4c..72d501f 100644 --- a/v2/swagger.yaml +++ b/v2/swagger.yaml @@ -61,6 +61,12 @@ tags: description: Methods for working with workflow. - name: kedo description: Методы для работы с КЭДО. + - name: admin-wallet + description: Админский API кошельков сотрудников (read-only). Permission `wallets-transactions`, требует `enableWallet=true` у тенанта. + - name: admin-wallet-transaction + description: Админский API транзакций кошелька — проведение начислений/списаний (form/excel) и просмотр. + - name: file-processing + description: Статусы асинхронных обработок файлов (excel-импорт/экспорт, архивы). Видны только записи текущего пользователя. paths: /mobile/bind/{id}/{token}: @@ -6894,6 +6900,316 @@ paths: example: - field: entityId message: Необходимо заполнить «Entity Id». + + /admin/wallet: + get: + tags: [admin-wallet] + summary: Список кошельков сотрудников + operationId: adminWalletIndex + parameters: + - name: page + in: query + schema: { type: integer, minimum: 1, default: 1 } + - name: per-page + in: query + schema: { type: integer, minimum: 1, maximum: 100, default: 20 } + - name: sort + in: query + schema: { type: string } + description: Префикс "-" для DESC. Пример "-balance". + - name: user_id + in: query + schema: { type: string, format: uuid } + - name: status_id + in: query + schema: { type: integer, enum: [1, 2] } + description: 1=Active, 2=Disabled + - name: department_id + in: query + schema: { type: string, format: uuid } + - name: user_list_key + in: query + schema: { type: string, format: uuid } + - name: reg_status_id + in: query + schema: { type: string } + - name: created_at + in: query + schema: { type: string } + description: Диапазон, формат "from|to" (ISO). + responses: + 200: + description: Список кошельков + content: + application/json: + schema: + $ref: '#/components/schemas/WalletList' + + /admin/wallet/view: + get: + tags: [admin-wallet] + summary: Один кошелёк + operationId: adminWalletView + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 200: + description: Кошелёк + content: + application/json: + schema: + $ref: '#/components/schemas/Wallet' + + /admin/wallet/export-excel: + post: + tags: [admin-wallet] + summary: Поставить задачу на excel-экспорт списка кошельков + description: | + Файл готовится асинхронно — статус смотреть через `/file-processing/view`. + operationId: adminWalletExportExcel + requestBody: + required: false + content: + application/x-www-form-urlencoded: + schema: + type: object + additionalProperties: true + description: Параметры фильтра — те же что у `GET /admin/wallet`. + responses: + 200: + description: Задача поставлена + content: + application/json: + schema: + type: object + properties: + success: { type: boolean } + + /admin/wallet-transaction: + get: + tags: [admin-wallet-transaction] + summary: Список транзакций (admin-вид — видны транзакции всех юзеров) + operationId: adminWalletTransactionIndex + parameters: + - name: page + in: query + schema: { type: integer, minimum: 1, default: 1 } + - name: per-page + in: query + schema: { type: integer, minimum: 1, maximum: 100, default: 20 } + - name: sort + in: query + schema: { type: string } + - name: wallet_id + in: query + schema: { type: string, format: uuid } + - name: sender_user_id + in: query + schema: { type: string, format: uuid } + - name: recipient_user_id + in: query + schema: { type: string, format: uuid } + - name: wallet_transaction_type + in: query + schema: { type: integer, enum: [1, 2] } + description: 1=Credit, 2=Debit + - name: wallet_operation_type + in: query + schema: { type: integer } + - name: created_at + in: query + schema: { type: string } + responses: + 200: + description: Список транзакций + content: + application/json: + schema: + $ref: '#/components/schemas/WalletTransactionList' + + /admin/wallet-transaction/view: + get: + tags: [admin-wallet-transaction] + summary: Одна транзакция + operationId: adminWalletTransactionView + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 200: + description: Транзакция + content: + application/json: + schema: + $ref: '#/components/schemas/WalletTransaction' + + /admin/wallet-transaction/create: + post: + tags: [admin-wallet-transaction] + summary: Провести начисление/списание по форме + description: | + Массовая операция через `usersListKey` (ключ закэшированной выборки сотрудников). + Запускается асинхронно через launcher. + + Soft-error состояния возвращаются в `message.type=warning`: + - "Укажите сотрудников" — выборка пустая + - "Невозможно провести транзакцию, у некоторых сотрудников недостаточно средств..." — debit, не хватает баланса (имена в тексте) + operationId: adminWalletTransactionCreate + requestBody: + required: true + content: + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/WalletTransactionFormBody' + responses: + 200: + description: HttpJsonResult + content: + application/json: + schema: + $ref: '#/components/schemas/WalletAdminHttpJsonResult' + + /admin/wallet-transaction/create-from-excel: + post: + tags: [admin-wallet-transaction] + summary: Провести транзакции по результатам excel-обработки + description: | + Принимает `file_processing_id` от `/excel-processing`. Запускает launcher, + который читает `validRows` из FileProcessing.result и проводит транзакции. + + Soft-error состояния: + - "Обработка файла не найдена" — file_processing_id не существует + - "Файл ещё обрабатывается, подождите" — статус не терминальный + - "Ошибка при обработке файла" — статус FATAL/ERROR + - "Нет валидных данных для начисления" — validCount == 0 + operationId: adminWalletTransactionCreateFromExcel + requestBody: + required: true + content: + application/x-www-form-urlencoded: + schema: + type: object + required: [file_processing_id] + properties: + file_processing_id: + type: string + format: uuid + responses: + 200: + description: HttpJsonResult + content: + application/json: + schema: + $ref: '#/components/schemas/WalletAdminHttpJsonResult' + + /admin/wallet-transaction/excel-processing: + post: + tags: [admin-wallet-transaction] + summary: Запустить парсинг xlsx с маппингом колонок + description: | + Создаёт FileProcessing с типом PROCESS_WALLET_EXCEL, ставит задачу на парсинг. + Воркер читает xlsx, валидирует строки, складывает в `result.validRows`/`result.invalidRows` + `result.summary`. + + Возвращает `fileProcessingId` для поллинга через `/file-processing/view`. + operationId: adminWalletTransactionExcelProcessing + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/WalletExcelFormBody' + responses: + 200: + description: Задача поставлена + content: + application/json: + schema: + allOf: + - $ref: '#/components/schemas/WalletAdminHttpJsonResult' + - type: object + properties: + data: + type: object + properties: + fileProcessingId: + type: string + format: uuid + + /admin/wallet-transaction/export-excel: + post: + tags: [admin-wallet-transaction] + summary: Поставить задачу на excel-экспорт списка транзакций + operationId: adminWalletTransactionExportExcel + requestBody: + required: false + content: + application/x-www-form-urlencoded: + schema: + type: object + additionalProperties: true + description: Параметры фильтра — те же что у `GET /admin/wallet-transaction`. + responses: + 200: + description: Задача поставлена + content: + application/json: + schema: + type: object + properties: + success: { type: boolean } + + /file-processing: + get: + tags: [file-processing] + summary: Список асинхронных обработок файлов текущего пользователя + description: Видны только записи, привязанные к файлам с `user_id` = текущий пользователь. + operationId: fileProcessingIndex + parameters: + - name: page + in: query + schema: { type: integer, minimum: 1, default: 1 } + - name: per-page + in: query + schema: { type: integer, minimum: 1, maximum: 10, default: 10 } + - name: file_processing_status_id + in: query + schema: { type: string } + description: Comma-separated FileProcessingStatus + - name: file_processing_type_id + in: query + schema: { type: string } + description: Comma-separated FileProcessingType + responses: + 200: + description: Список + content: + application/json: + schema: + $ref: '#/components/schemas/FileProcessingList' + + /file-processing/view: + get: + tags: [file-processing] + summary: Одна обработка + operationId: fileProcessingView + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 200: + description: Обработка + content: + application/json: + schema: + $ref: '#/components/schemas/FileProcessing' + components: securitySchemes: SessionAuth: @@ -11648,6 +11964,210 @@ components: format: uri example: "https://accounts.google.com/o/oauth2/v2/auth?..." + WalletAdminHttpJsonResult: + type: object + properties: + success: { type: boolean } + data: + oneOf: + - type: object + - type: array + - type: 'null' + errors: + type: array + items: + $ref: '#/components/schemas/WalletAdminFieldError' + message: + oneOf: + - $ref: '#/components/schemas/WalletAdminMessage' + - type: 'null' + + WalletAdminFieldError: + type: object + properties: + attribute: { type: string, example: "amount" } + text: { type: string, example: "Необходимо заполнить «Сумма»." } + + WalletAdminMessage: + type: object + properties: + type: + type: string + enum: [success, info, warning, error] + text: { type: string } + + Wallet: + type: object + properties: + id: { type: string, format: uuid } + created_at: { type: string } + status_id: { type: integer, enum: [1, 2] } + user_id: { type: string, format: uuid } + balance: { type: integer, description: "В единицах корп. валюты" } + createdAt: { type: string, description: "Локализованная дата" } + statusName: { type: string } + sumGiftCredits: { type: integer, description: "Подарочный остаток (auto-credit)" } + user: + $ref: '#/components/schemas/WalletAdminUserShort' + + WalletAdminUserShort: + type: object + properties: + id: { type: string, format: uuid } + name: { type: string } + department: + type: object + properties: + id: { type: string, format: uuid } + name: { type: string } + + WalletList: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/Wallet' + _meta: + $ref: '#/components/schemas/_meta' + + WalletTransaction: + type: object + properties: + id: { type: string, format: uuid } + created_at: { type: string } + wallet_transaction_type: + type: integer + enum: [1, 2] + description: 1=Credit, 2=Debit + wallet_operation_type: + type: integer + description: Подтип операции (Credit, Debit, AutoCredit, BalancePercentGift, Gift и т.д.) + sender_wallet_id: { type: string, format: uuid, nullable: true } + recipient_wallet_id: { type: string, format: uuid, nullable: true } + amount: { type: integer } + entity_id: { type: integer, nullable: true } + reference_id: { type: string, format: uuid, nullable: true } + comment: { type: string, nullable: true } + createdAt: { type: string } + senderUserId: { type: string, format: uuid, nullable: true } + senderName: { type: string, nullable: true } + recipientUserId: { type: string, format: uuid, nullable: true } + recipientName: { type: string, nullable: true } + walletOperationTypeName: { type: string } + + WalletTransactionList: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/WalletTransaction' + _meta: + $ref: '#/components/schemas/_meta' + + WalletTransactionFormBody: + type: object + required: + - usersListKey + - wallet_transaction_type + - amount + - comment + properties: + usersListKey: + type: string + format: uuid + description: Ключ выборки сотрудников (создаётся через `POST /core/user-list-cache/set-user-list`) + wallet_transaction_type: + type: integer + enum: [1, 2] + description: 1=Credit (начисление), 2=Debit (списание) + amount: + type: integer + minimum: 1 + comment: + type: string + maxLength: 400 + + WalletExcelFormBody: + type: object + required: [file_id, mappings] + properties: + file_id: + type: string + format: uuid + description: ID предварительно загруженного xlsx-файла + mappings: + type: array + description: | + Соответствие колонок xlsx и полей транзакции. + items: + type: object + required: [colIndex, attribute] + properties: + colIndex: + type: integer + description: Индекс колонки в xlsx (с 0) + attribute: + type: string + enum: + - id + - org_num + - full_name + - last_name + - first_name + - middle_name + - amount + - transaction_type + - comment + example: + - { colIndex: 0, attribute: id } + - { colIndex: 1, attribute: amount } + - { colIndex: 2, attribute: transaction_type } + - { colIndex: 3, attribute: comment } + + FileProcessing: + type: object + properties: + id: { type: string, format: uuid } + file_id: { type: string, format: uuid } + file_processing_type_id: + type: integer + description: | + Тип обработки. Релевантные: + - 3 — PROCESS_EXCEL_REPORT (excel-экспорт) + - 10 — PROCESS_WALLET_EXCEL (парсинг wallet-excel) + file_processing_status_id: + type: integer + description: | + 1 — NEW, 2 — QUEUED, 3 — STARTED, 4 — FINISHED, 5 — ERROR, 6 — FATAL + arguments: + type: array + result: + type: object + description: | + Результат. Для wallet-excel содержит: + ``` + { + "summary": { "totalRows": 4, "validCount": 1, "invalidCount": 3 }, + "validRows": [...], + "invalidRows": [{ "row": 2, "errors": {...} }, ...] + } + ``` + created_at: { type: string } + started_at: { type: string, nullable: true } + finished_at: { type: string, nullable: true } + + FileProcessingList: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/FileProcessing' + _meta: + $ref: '#/components/schemas/_meta' + parameters: boardDateTypeParam: in: query From 2260bf10664338f40b3174018f7a7099634b9881 Mon Sep 17 00:00:00 2001 From: Denis Date: Fri, 22 May 2026 12:04:09 +0300 Subject: [PATCH 2/2] =?UTF-8?q?H-3656:=20=D1=83=D1=82=D0=BE=D1=87=D0=BD?= =?UTF-8?q?=D0=B8=D0=BB=20Wallet=20admin=20API=20=D0=B2=20v2=20swagger?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - /admin/wallet-transaction: добавил недостающие фильтры (sender_wallet_id, recipient_wallet_id, sender_user_list_key, recipient_user_list_key, wallet_user_list_key, department_id, entity_id, reference_id) + описания. - sort: перечислил реальные сортируемые атрибуты для wallet/wallet-transaction. - reg_status_id / created_at / user_list_key: уточнил формат и поведение. - WalletTransaction + WalletTransactionFormBody + параметры фильтра: заменил инлайн enum [1,2] на $ref walletTransactionType / walletOperationType. - walletOperationType: добавил отсутствующее значение 9 (Отмена покупки), чтобы соответствовать app\models\wallet\enum\WalletOperationType. Co-Authored-By: Claude Opus 4.7 (1M context) --- v2/swagger.yaml | 88 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 70 insertions(+), 18 deletions(-) diff --git a/v2/swagger.yaml b/v2/swagger.yaml index 72d501f..163908a 100644 --- a/v2/swagger.yaml +++ b/v2/swagger.yaml @@ -6915,8 +6915,11 @@ paths: schema: { type: integer, minimum: 1, maximum: 100, default: 20 } - name: sort in: query - schema: { type: string } - description: Префикс "-" для DESC. Пример "-balance". + schema: + type: string + enum: [created_at, "-created_at", status_id, "-status_id", balance, "-balance", name, "-name"] + description: | + Префикс `-` для DESC. По умолчанию `-created_at`. - name: user_id in: query schema: { type: string, format: uuid } @@ -6930,13 +6933,17 @@ paths: - name: user_list_key in: query schema: { type: string, format: uuid } + description: Ключ закэшированной выборки сотрудников (создаётся через core user-list-cache). - name: reg_status_id in: query schema: { type: string } + description: | + Comma-separated значения `RegStatus` (статус участия). Без параметра — + показываются все валидные для отображения статусы. - name: created_at in: query schema: { type: string } - description: Диапазон, формат "from|to" (ISO). + description: 'Диапазон в формате `from|to` (ISO дата/время).' responses: 200: description: Список кошельков @@ -6992,6 +6999,9 @@ paths: get: tags: [admin-wallet-transaction] summary: Список транзакций (admin-вид — видны транзакции всех юзеров) + description: | + Под `wallets-transactions` отдаёт все транзакции тенанта (учётная админ-выборка). + Без права — только транзакции по своему кошельку. operationId: adminWalletTransactionIndex parameters: - name: page @@ -7002,26 +7012,71 @@ paths: schema: { type: integer, minimum: 1, maximum: 100, default: 20 } - name: sort in: query - schema: { type: string } + schema: + type: string + enum: + - created_at + - "-created_at" + - wallet_transaction_type + - "-wallet_transaction_type" + - wallet_operation_type + - "-wallet_operation_type" + - amount + - "-amount" + description: | + Префикс `-` для DESC. По умолчанию `-created_at`. - name: wallet_id in: query schema: { type: string, format: uuid } + description: Транзакции конкретного кошелька (отправитель ИЛИ получатель). + - name: sender_wallet_id + in: query + schema: { type: string, format: uuid } + - name: recipient_wallet_id + in: query + schema: { type: string, format: uuid } - name: sender_user_id in: query schema: { type: string, format: uuid } + description: Транзакции, где этот юзер — отправитель ИЛИ администратор начисления. - name: recipient_user_id in: query schema: { type: string, format: uuid } + - name: sender_user_list_key + in: query + schema: { type: string, format: uuid } + description: Выборка сотрудников-отправителей (см. core user-list-cache). + - name: recipient_user_list_key + in: query + schema: { type: string, format: uuid } + - name: wallet_user_list_key + in: query + schema: { type: string, format: uuid } + description: | + Выборка сотрудников: транзакция учитывается, если кто-то из них — + отправитель, получатель ИЛИ администратор начисления. Полезно для поиска + операций, где одна из сторон NULL (покупка в магазине, авто-начисления). + - name: department_id + in: query + schema: { type: string, format: uuid } - name: wallet_transaction_type in: query - schema: { type: integer, enum: [1, 2] } - description: 1=Credit, 2=Debit + schema: + $ref: '#/components/schemas/walletTransactionType' - name: wallet_operation_type + in: query + schema: + $ref: '#/components/schemas/walletOperationType' + - name: entity_id in: query schema: { type: integer } + - name: reference_id + in: query + schema: { type: string, format: uuid } - name: created_at in: query schema: { type: string } + description: 'Диапазон в формате `from|to` (ISO дата/время).' responses: 200: description: Список транзакций @@ -11731,7 +11786,8 @@ components: * `6` - Автоматическое начисление валюты * `7` - Подарок (автоматическое начисление) * `8` - Подарок (процент от баланса) - enum: [1, 2, 3, 4, 5, 6, 7, 8] + * `9` - Отмена покупки + enum: [1, 2, 3, 4, 5, 6, 7, 8, 9] example: 3 walletTransaction: @@ -12037,24 +12093,21 @@ components: id: { type: string, format: uuid } created_at: { type: string } wallet_transaction_type: - type: integer - enum: [1, 2] - description: 1=Credit, 2=Debit + $ref: '#/components/schemas/walletTransactionType' wallet_operation_type: - type: integer - description: Подтип операции (Credit, Debit, AutoCredit, BalancePercentGift, Gift и т.д.) + $ref: '#/components/schemas/walletOperationType' sender_wallet_id: { type: string, format: uuid, nullable: true } recipient_wallet_id: { type: string, format: uuid, nullable: true } amount: { type: integer } entity_id: { type: integer, nullable: true } reference_id: { type: string, format: uuid, nullable: true } comment: { type: string, nullable: true } - createdAt: { type: string } + createdAt: { type: string, description: 'Локализованная дата для отображения.' } senderUserId: { type: string, format: uuid, nullable: true } senderName: { type: string, nullable: true } recipientUserId: { type: string, format: uuid, nullable: true } recipientName: { type: string, nullable: true } - walletOperationTypeName: { type: string } + walletOperationTypeName: { type: string, description: 'Человекочитаемое название операции.' } WalletTransactionList: type: object @@ -12077,14 +12130,13 @@ components: usersListKey: type: string format: uuid - description: Ключ выборки сотрудников (создаётся через `POST /core/user-list-cache/set-user-list`) + description: Ключ выборки сотрудников (создаётся через core user-list-cache). wallet_transaction_type: - type: integer - enum: [1, 2] - description: 1=Credit (начисление), 2=Debit (списание) + $ref: '#/components/schemas/walletTransactionType' amount: type: integer minimum: 1 + description: Сумма в единицах корп. валюты. На каждого сотрудника выборки. comment: type: string maxLength: 400