From 9820f97216044536c39cc7a2431a360524663f14 Mon Sep 17 00:00:00 2001 From: Anton Pomorzin Date: Fri, 26 Jun 2026 12:34:55 +0500 Subject: [PATCH 1/3] =?UTF-8?q?H-2626:=20admin=20shop=20API=20v2=20=D0=B2?= =?UTF-8?q?=20swagger?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 28 эндпоинтов под /admin/shop/* с 4 новыми тегами (admin-shop-product, admin-shop-product-option, admin-shop-order, admin-shop-delivery-address). Эндпоинты: - product: index/items/view + create/update/delete + export-excel + категории через legacy CategoryAction'ы (view-/update-/delete-category) - product-option: index (с обязательным shop_product_id) / view / CRUD - order: index/view + process/cancel + позиции (remove/restore/change-comment) + export-excel - delivery-address: CRUD Схемы AdminShopProduct/ProductOption/Order/DeliveryAddress (+List + SaveRequest) и HttpJsonResult для обёрток process/cancel. --- v2/swagger.yaml | 925 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 925 insertions(+) diff --git a/v2/swagger.yaml b/v2/swagger.yaml index f7cca68..9a03507 100644 --- a/v2/swagger.yaml +++ b/v2/swagger.yaml @@ -79,6 +79,23 @@ 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-shop-product + description: | + Управление товарами корпоративного магазина (admin). Требуется право `shop-items` + и флаг тенанта `enableShop`. Action `items` доступен и менеджеру заказов (`shop-orders`). + - name: admin-shop-product-option + description: | + Варианты (опции) товаров магазина: точечный CRUD по одной опции. + Пакетное сохранение опций — через `POST /admin/shop/product/update`. + Требуется право `shop-items`. + - name: admin-shop-order + description: | + Обработка заказов магазина: подтверждение, отмена, действия с позициями. + Требуется право `shop-orders`. + - name: admin-shop-delivery-address + description: | + Справочник адресов доставки для самовывоза/курьерской доставки. Требуется + право `shop-orders`. paths: /mobile/bind/{id}/{token}: @@ -8264,6 +8281,675 @@ paths: Запись не найдена. Включает случаи обращения к записям, принадлежащим другим тенантам. + # ============================================================ + # Admin Shop API (H-2626) + # ============================================================ + + /admin/shop/product: + get: + tags: [admin-shop-product] + summary: Список товаров магазина (admin) + operationId: adminShopProductIndex + 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. Поддерживается `ShopProductSearch::sort()`. + - name: title + in: query + schema: { type: string } + description: Поиск по подстроке в названии. + - name: status_id + in: query + schema: { type: integer } + description: По умолчанию `Status::ACTIVE=1`. + - name: category_id + in: query + schema: { type: string, format: uuid } + responses: + 200: + description: Список товаров + content: + application/json: + schema: + $ref: '#/components/schemas/AdminShopProductList' + 403: + description: Нет права `shop-items` или флаг `enableShop` выключен. + + /admin/shop/product/items: + get: + tags: [admin-shop-product] + summary: Лёгкий справочник активных товаров + description: | + Возвращает только `{id, title}` для использования в фильтрах админ-страниц + (например, фильтр по товару на странице обработки заказов). Доступно + дополнительно роли `shop-orders`. + operationId: adminShopProductItems + parameters: + - name: title + in: query + schema: { type: string } + responses: + 200: + description: Справочник + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + type: object + properties: + id: { type: string, format: uuid } + title: { type: string } + _meta: + $ref: '#/components/schemas/_meta' + + /admin/shop/product/view: + get: + tags: [admin-shop-product] + summary: Карточка товара (admin) + operationId: adminShopProductView + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 200: + description: Товар + content: + application/json: + schema: + $ref: '#/components/schemas/AdminShopProduct' + 400: + description: Параметр `id` имеет некорректный формат. + 404: + description: Товар не найден. + + /admin/shop/product/create: + post: + tags: [admin-shop-product] + summary: Создать товар вместе с опциями + description: | + Сохраняет товар и массив его опций одной транзакцией. Опции, отсутствующие + в `ShopProductOption[]`, помечаются `status_id = DELETED`. + + Сначала валидируется товар; затем сохраняется с `refresh()` (чтобы + вернуть defaults из БД); затем сохраняются опции (валидируется на + save — `shop_product_id` имеет правило `exist`, которое отрабатывает + только после insert товара). + operationId: adminShopProductCreate + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AdminShopProductSaveRequest' + responses: + 200: + description: Сохранённый товар + content: + application/json: + schema: + $ref: '#/components/schemas/AdminShopProduct' + 422: + description: Ошибка валидации — пустой `ShopProductOption[]` или валидация модели не прошла. + + /admin/shop/product/update: + post: + tags: [admin-shop-product] + summary: Обновить товар вместе с опциями + operationId: adminShopProductUpdate + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AdminShopProductSaveRequest' + responses: + 200: + description: Обновлённый товар + content: + application/json: + schema: + $ref: '#/components/schemas/AdminShopProduct' + 404: { description: Товар не найден. } + 422: { description: Ошибка валидации. } + + /admin/shop/product/delete: + delete: + tags: [admin-shop-product] + summary: Soft-delete товара + description: | + Через override `BaseModel::deleteAll → softDeleteAll`. Физического удаления + записи не происходит — переводится в `status_id = DELETED`. + operationId: adminShopProductDelete + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 204: { description: Удалено. } + 400: { description: Параметр `id` имеет некорректный формат. } + 404: { description: Товар не найден. } + + /admin/shop/product/export-excel: + post: + tags: [admin-shop-product] + summary: Поставить задачу на excel-экспорт списка товаров + description: Файл готовится асинхронно — статус смотреть через `/file-processing/view`. + operationId: adminShopProductExportExcel + requestBody: + required: false + content: + application/x-www-form-urlencoded: + schema: + type: object + additionalProperties: true + responses: + 200: { description: Задача поставлена. } + + /admin/shop/product/view-category: + get: + tags: [admin-shop-product] + summary: Получить категорию товаров магазина + description: | + Реюз legacy `app\custom\actions\category\ViewAction`, параметризованного + `CategoryRoot::ROOT_SHOP_PRODUCT`. + operationId: adminShopProductViewCategory + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 200: + description: Категория + content: + application/json: + schema: + $ref: '#/components/schemas/HttpJsonResult' + + /admin/shop/product/update-category: + post: + tags: [admin-shop-product] + summary: Создать/обновить категорию товаров магазина + operationId: adminShopProductUpdateCategory + parameters: + - name: id + in: query + required: false + schema: { type: string, format: uuid } + description: Без `id` — создание; с `id` — обновление. + requestBody: + required: true + content: + application/json: + schema: + type: object + additionalProperties: true + description: Поля категории (title, parent_id, image и т.д. — см. CatalogManager). + responses: + 200: + description: Категория + content: + application/json: + schema: + $ref: '#/components/schemas/HttpJsonResult' + 201: + description: Создана. + + /admin/shop/product/delete-category: + delete: + tags: [admin-shop-product] + summary: Удалить категорию товаров магазина + operationId: adminShopProductDeleteCategory + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 204: { description: Удалено. } + 400: { description: Параметр `id` имеет некорректный формат. } + + /admin/shop/product-option: + get: + tags: [admin-shop-product-option] + summary: Варианты товара (admin) + description: | + `shop_product_id` обязателен — его требует `ShopProductOptionSearch`. + Дефолтная сортировка `sort_index ASC` через `defaultOrder` search-модели. + operationId: adminShopProductOptionIndex + parameters: + - name: shop_product_id + in: query + required: true + schema: { type: string, format: uuid } + - name: status_id + in: query + schema: { type: integer } + - name: title + in: query + schema: { type: string } + - name: sort + in: query + schema: + type: string + enum: [sort_index, "-sort_index", name, "-name", created_at, "-created_at"] + - name: per-page + in: query + schema: { type: integer, minimum: 1, maximum: 100, default: 100 } + responses: + 200: + description: Список опций + content: + application/json: + schema: + $ref: '#/components/schemas/AdminShopProductOptionList' + + /admin/shop/product-option/view: + get: + tags: [admin-shop-product-option] + summary: Одна опция + operationId: adminShopProductOptionView + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 200: + description: Опция + content: + application/json: + schema: + $ref: '#/components/schemas/AdminShopProductOption' + 404: { description: Опция не найдена. } + + /admin/shop/product-option/create: + post: + tags: [admin-shop-product-option] + summary: Создать одну опцию + description: | + Для пакетного сохранения опций вместе с товаром — `POST /admin/shop/product/update`. + Этот эндпоинт нужен для точечных операций. + operationId: adminShopProductOptionCreate + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AdminShopProductOptionSaveRequest' + responses: + 200: + description: Созданная опция + content: + application/json: + schema: + $ref: '#/components/schemas/AdminShopProductOption' + + /admin/shop/product-option/update: + post: + tags: [admin-shop-product-option] + summary: Обновить одну опцию + operationId: adminShopProductOptionUpdate + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AdminShopProductOptionSaveRequest' + responses: + 200: + description: Обновлённая опция + content: + application/json: + schema: + $ref: '#/components/schemas/AdminShopProductOption' + 404: { description: Опция не найдена. } + + /admin/shop/product-option/delete: + delete: + tags: [admin-shop-product-option] + summary: Soft-delete опции + operationId: adminShopProductOptionDelete + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 204: { description: Удалено. } + 404: { description: Опция не найдена. } + + /admin/shop/order: + get: + tags: [admin-shop-order] + summary: Список заказов (admin) + operationId: adminShopOrderIndex + 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: order_status_id + in: query + schema: { type: integer } + description: | + Статусы заказа из `ShopOrderStatus`: 1=NEW, 2=PROCESSED, + 3=CANCELED_USER, 4=CANCELED_MANAGER. + - name: created_user_id + in: query + schema: { type: string, format: uuid } + - name: approver_user_id + in: query + schema: { type: string, format: uuid } + - name: shop_item_id + in: query + schema: { type: string, format: uuid } + description: Фильтр по товару (через JOIN на shopCart). + - name: created_at + in: query + schema: { type: string } + description: Диапазон `<начало>|<конец>` в формате `yyyy-MM-dd`. + - name: sort + in: query + schema: { type: string } + responses: + 200: + description: Список заказов + content: + application/json: + schema: + $ref: '#/components/schemas/AdminShopOrderList' + + /admin/shop/order/view: + get: + tags: [admin-shop-order] + summary: Детализация заказа + operationId: adminShopOrderView + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 200: + description: Заказ с расширенным составом (shopCart) + content: + application/json: + schema: + $ref: '#/components/schemas/AdminShopOrder' + + /admin/shop/order/process: + post: + tags: [admin-shop-order] + summary: Подтвердить заказ менеджером + description: | + Переводит заказ из STATUS_NEW в STATUS_PROCESSED. Если есть позиции + с `status_id = DELETED` — возвращает их количество на склад и проводит + refund-транзакцию на сумму отменённых позиций. + + Внутри транзакции: `lock()` + `refresh()` + повторная проверка статуса + NEW — защита от race condition двойного refund. + operationId: adminShopOrderProcess + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AdminShopOrderActionRequest' + responses: + 200: + description: Заказ обработан + content: + application/json: + schema: + $ref: '#/components/schemas/HttpJsonResult' + 422: + description: | + Ошибка валидации формы либо заказ уже не в статусе NEW + (`ShopOrderException::ALREADY_PROCESSED`). + + /admin/shop/order/cancel: + post: + tags: [admin-shop-order] + summary: Отменить заказ менеджером + description: | + Переводит заказ в STATUS_CANCELED_MANAGER, возвращает все позиции + на склад и проводит полный refund баланса покупателя. Уведомляет + покупателя об отмене. + operationId: adminShopOrderCancel + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AdminShopOrderActionRequest' + responses: + 200: + description: Заказ отменён + content: + application/json: + schema: + $ref: '#/components/schemas/HttpJsonResult' + 422: + description: Заказ уже не в статусе NEW или другая ошибка валидации. + + /admin/shop/order/position-remove: + post: + tags: [admin-shop-order] + summary: Удалить позицию заказа + operationId: adminShopOrderPositionRemove + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [id, comment] + properties: + id: { type: string, format: uuid, description: ID позиции (ShopCart). } + comment: { type: string, description: Причина удаления. } + responses: + 200: + description: Результат + content: + application/json: + schema: + $ref: '#/components/schemas/HttpJsonResult' + + /admin/shop/order/position-restore: + post: + tags: [admin-shop-order] + summary: Восстановить удалённую позицию заказа + operationId: adminShopOrderPositionRestore + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [id] + properties: + id: { type: string, format: uuid } + responses: + 200: + description: Результат + content: + application/json: + schema: + $ref: '#/components/schemas/HttpJsonResult' + + /admin/shop/order/position-change-comment: + post: + tags: [admin-shop-order] + summary: Изменить комментарий к позиции заказа + operationId: adminShopOrderPositionChangeComment + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [id, comment] + properties: + id: { type: string, format: uuid } + comment: { type: string } + responses: + 200: + description: Результат + content: + application/json: + schema: + $ref: '#/components/schemas/HttpJsonResult' + + /admin/shop/order/export-excel: + post: + tags: [admin-shop-order] + summary: Поставить задачу на excel-экспорт списка заказов + description: Файл готовится асинхронно — статус смотреть через `/file-processing/view`. + operationId: adminShopOrderExportExcel + requestBody: + required: false + content: + application/x-www-form-urlencoded: + schema: + type: object + additionalProperties: true + responses: + 200: { description: Задача поставлена. } + + /admin/shop/delivery-address: + get: + tags: [admin-shop-delivery-address] + summary: Список адресов доставки + operationId: adminShopDeliveryAddressIndex + 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: title + in: query + schema: { type: string } + responses: + 200: + description: Список + content: + application/json: + schema: + $ref: '#/components/schemas/AdminShopDeliveryAddressList' + + /admin/shop/delivery-address/view: + get: + tags: [admin-shop-delivery-address] + summary: Один адрес + operationId: adminShopDeliveryAddressView + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 200: + description: Адрес + content: + application/json: + schema: + $ref: '#/components/schemas/AdminShopDeliveryAddress' + + /admin/shop/delivery-address/create: + post: + tags: [admin-shop-delivery-address] + summary: Создать адрес + operationId: adminShopDeliveryAddressCreate + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [title] + properties: + title: { type: string, maxLength: 255 } + responses: + 200: + description: Адрес + content: + application/json: + schema: + $ref: '#/components/schemas/AdminShopDeliveryAddress' + + /admin/shop/delivery-address/update: + post: + tags: [admin-shop-delivery-address] + summary: Обновить адрес + operationId: adminShopDeliveryAddressUpdate + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [title] + properties: + title: { type: string, maxLength: 255 } + responses: + 200: + description: Адрес + content: + application/json: + schema: + $ref: '#/components/schemas/AdminShopDeliveryAddress' + + /admin/shop/delivery-address/delete: + delete: + tags: [admin-shop-delivery-address] + summary: Удалить адрес + description: | + Hard-delete (у модели нет soft-delete-цепочки). На исторические заказы + удаление не влияет — `ShopOrder.delivery_address` хранит текстовую копию. + operationId: adminShopDeliveryAddressDelete + parameters: + - name: id + in: query + required: true + schema: { type: string, format: uuid } + responses: + 204: { description: Удалено. } + 404: { description: Не найден. } + components: securitySchemes: SessionAuth: @@ -14013,6 +14699,245 @@ components: $ref: '#/components/schemas/GoalItem' description: Цели которые не были обработаны + # ============================================================ + # Admin Shop API (H-2626) + # ============================================================ + + HttpJsonResult: + type: object + description: | + Стандартная обёртка ответа: `app\logic\core\Entities\HttpJsonResult`. + properties: + success: { type: boolean } + data: + oneOf: + - { type: object, additionalProperties: true } + - { type: 'null' } + errors: + type: array + items: + type: object + properties: + field: { type: string } + message: { type: string } + message: + type: object + nullable: true + properties: + type: + type: string + enum: [success, info, warning, error] + text: { type: string } + + AdminShopProduct: + type: object + properties: + id: { type: string, format: uuid } + created_at: { type: string } + updated_at: { type: string } + status_id: + type: integer + description: 1=Active, 2=Inactive, 3=Deleted + preview_file_id: { type: string, format: uuid, nullable: true } + title: { type: string } + description: { type: string, nullable: true } + price: { type: integer } + createdAt: { type: string, description: Локализованная дата для UI. } + statusName: { type: string } + totalCount: + type: integer + description: Сумма `count` по всем активным опциям. + preview: { type: string, description: URL ресайз-превью. } + images: + type: array + items: { type: object, additionalProperties: true } + options: + type: array + items: + $ref: '#/components/schemas/AdminShopProductOption' + entityId: { type: integer, description: 405 (ShopProduct в Entity.php). } + # forView=true: + content: { type: object, additionalProperties: true, description: JSON-блоки EditorJS. } + categoriesName: { type: object, additionalProperties: true } + categoriesText: { type: string, nullable: true } + + AdminShopProductList: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/AdminShopProduct' + _links: + $ref: '#/components/schemas/_links' + _meta: + $ref: '#/components/schemas/_meta' + + AdminShopProductSaveRequest: + type: object + required: [title, price, options] + properties: + title: { type: string } + description: { type: string } + price: { type: integer, minimum: 0, maximum: 999999 } + preview_file_id: { type: string, format: uuid, nullable: true } + status_id: { type: integer } + options: + type: array + minItems: 1 + description: | + Полный массив опций товара. Опции, отсутствующие в массиве, помечаются + `status_id = DELETED`. Для существующих опций передаётся `id`. + items: + type: object + required: [name, count, price] + properties: + id: { type: string, format: uuid, description: Для обновления существующей опции. } + name: { type: string, maxLength: 128 } + count: { type: integer, minimum: 0, maximum: 999999 } + price: { type: integer, minimum: 0, maximum: 999999 } + preview_file_id: { type: string, format: uuid, nullable: true } + images: + type: array + items: { type: object, additionalProperties: true } + images: + oneOf: + - { type: array, items: { type: object, additionalProperties: true } } + - { type: string, description: JSON-encoded массив (legacy). } + content: + oneOf: + - { type: object, additionalProperties: true } + - { type: string, description: JSON-encoded блоки (legacy). } + + AdminShopProductOption: + type: object + properties: + id: { type: string, format: uuid } + created_at: { type: string } + updated_at: { type: string } + shop_product_id: { type: string, format: uuid } + status_id: { type: integer } + sort_index: { type: integer } + name: { type: string } + count: { type: integer } + price: { type: integer } + preview_file_id: { type: string, format: uuid, nullable: true } + images: + type: array + items: { type: object, additionalProperties: true } + entityId: { type: integer } + + AdminShopProductOptionList: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/AdminShopProductOption' + _links: + $ref: '#/components/schemas/_links' + _meta: + $ref: '#/components/schemas/_meta' + + AdminShopProductOptionSaveRequest: + type: object + description: | + Поля `id`, `created_user_id`, `updated_user_id`, `tenant_id` подставляются + автоматически в `BaseModel::beforeSave` — попытка передать их в payload + игнорируется (поля убраны из `safeAttributes`). + properties: + shop_product_id: { type: string, format: uuid } + status_id: { type: integer } + sort_index: { type: integer } + name: { type: string, maxLength: 128 } + count: { type: integer, minimum: 0, maximum: 999999 } + price: { type: integer, minimum: 0, maximum: 999999 } + preview_file_id: { type: string, format: uuid, nullable: true } + images: + type: array + items: { type: object, additionalProperties: true } + + AdminShopOrder: + type: object + properties: + id: { type: string, format: uuid } + created_at: { type: string } + updated_at: { type: string } + created_user_id: { type: string, format: uuid, description: Покупатель. } + approver_user_id: { type: string, format: uuid, nullable: true, description: Менеджер-аппрувер. } + num: { type: integer, description: Номер заказа. } + order_status_id: + type: integer + enum: [1, 2, 3, 4] + description: 1=NEW, 2=PROCESSED, 3=CANCELED_USER, 4=CANCELED_MANAGER + delivery_address: { type: string, nullable: true } + count_cart_for_sorting: { type: integer } + sum_cart_for_sorting: { type: integer } + createdAt: { type: string, description: Локализованная дата. } + orderStatusName: { type: string } + countCartPositions: { type: integer } + countCartTotal: { type: integer } + sumCart: { type: integer } + user: + type: object + additionalProperties: true + description: Профиль покупателя. + entityId: { type: integer, description: 406 (ShopOrder в Entity.php). } + # forView=true expand: + shopCart: + type: array + description: Состав заказа. + items: + type: object + additionalProperties: true + orderContent: + type: string + description: Форматированный текст состава заказа. + + AdminShopOrderList: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/AdminShopOrder' + _links: + $ref: '#/components/schemas/_links' + _meta: + $ref: '#/components/schemas/_meta' + + AdminShopOrderActionRequest: + type: object + required: [id] + properties: + id: { type: string, format: uuid, description: ID заказа. } + message: + type: string + maxLength: 512 + description: Комментарий к действию (сохраняется как Comment к заказу). + + AdminShopDeliveryAddress: + type: object + properties: + id: { type: string, format: uuid } + created_at: { type: string } + updated_at: { type: string } + created_user_id: { type: string, format: uuid } + updated_user_id: { type: string, format: uuid, nullable: true } + title: { type: string, maxLength: 255 } + + AdminShopDeliveryAddressList: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/AdminShopDeliveryAddress' + _links: + $ref: '#/components/schemas/_links' + _meta: + $ref: '#/components/schemas/_meta' + security: - SessionAuth: [ ] - ApiKeyAuth: [ ] -- 2.54.0 From 6c8980162c7c9cdf85467563ae65c5baff51300c Mon Sep 17 00:00:00 2001 From: kirill Date: Fri, 14 Aug 2026 10:15:27 +0600 Subject: [PATCH 2/3] =?UTF-8?q?H-2626:=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D1=82=D1=8C=20=D1=81=D1=82=D0=B0=D1=82=D1=83=D1=81?= =?UTF-8?q?=D1=8B=20=D0=B7=D0=B0=D0=BA=D0=B0=D0=B7=D0=BE=D0=B2=20=D0=B2=20?= =?UTF-8?q?Swagger?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- v2/swagger.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/v2/swagger.yaml b/v2/swagger.yaml index 9a03507..331cd1b 100644 --- a/v2/swagger.yaml +++ b/v2/swagger.yaml @@ -8660,7 +8660,7 @@ paths: schema: { type: integer } description: | Статусы заказа из `ShopOrderStatus`: 1=NEW, 2=PROCESSED, - 3=CANCELED_USER, 4=CANCELED_MANAGER. + 3=CANCELED_MANAGER, 4=CANCELED_USER. - name: created_user_id in: query schema: { type: string, format: uuid } @@ -14869,7 +14869,7 @@ components: order_status_id: type: integer enum: [1, 2, 3, 4] - description: 1=NEW, 2=PROCESSED, 3=CANCELED_USER, 4=CANCELED_MANAGER + description: 1=NEW, 2=PROCESSED, 3=CANCELED_MANAGER, 4=CANCELED_USER delivery_address: { type: string, nullable: true } count_cart_for_sorting: { type: integer } sum_cart_for_sorting: { type: integer } -- 2.54.0 From 278463e61169ea683685d7d9ac9d37af9d6e88b5 Mon Sep 17 00:00:00 2001 From: Anton Pomorzin Date: Thu, 20 Aug 2026 13:06:12 +0500 Subject: [PATCH 3/3] =?UTF-8?q?H-2626:=20=D0=9F=D1=80=D0=B0=D0=B2=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=20=D1=80=D0=B5=D0=B2?= =?UTF-8?q?=D1=8C=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- v2/swagger.yaml | 48 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/v2/swagger.yaml b/v2/swagger.yaml index 331cd1b..6736164 100644 --- a/v2/swagger.yaml +++ b/v2/swagger.yaml @@ -8535,6 +8535,7 @@ paths: description: | `shop_product_id` обязателен — его требует `ShopProductOptionSearch`. Дефолтная сортировка `sort_index ASC` через `defaultOrder` search-модели. + По умолчанию отдаются только активные (status_id=ACTIVE); чтобы увидеть удалённые — явно передать `status_id`. operationId: adminShopProductOptionIndex parameters: - name: shop_product_id @@ -8544,8 +8545,9 @@ paths: - name: status_id in: query schema: { type: integer } - - name: title + - name: name in: query + description: LIKE-фильтр по названию варианта. schema: { type: string } - name: sort in: query @@ -8608,6 +8610,8 @@ paths: post: tags: [admin-shop-product-option] summary: Обновить одну опцию + description: | + Поле `shop_product_id` игнорируется — привязку к товару менять нельзя. operationId: adminShopProductOptionUpdate parameters: - name: id @@ -8677,7 +8681,23 @@ paths: description: Диапазон `<начало>|<конец>` в формате `yyyy-MM-dd`. - name: sort in: query - schema: { type: string } + description: | + Поддерживаемые поля: `created_at`, `num`, `order_status_id`, + `sum_cart_for_sorting`, `count_cart_for_sorting`. + Префикс `-` — сортировка по убыванию. Дефолт — `-created_at`. + schema: + type: string + enum: + - created_at + - "-created_at" + - num + - "-num" + - order_status_id + - "-order_status_id" + - sum_cart_for_sorting + - "-sum_cart_for_sorting" + - count_cart_for_sorting + - "-count_cart_for_sorting" responses: 200: description: Список заказов @@ -8763,6 +8783,8 @@ paths: post: tags: [admin-shop-order] summary: Удалить позицию заказа + description: | + Операция допустима только на заказе в статусе NEW; для обработанного/отменённого — 422. operationId: adminShopOrderPositionRemove requestBody: required: true @@ -8781,11 +8803,15 @@ paths: application/json: schema: $ref: '#/components/schemas/HttpJsonResult' + 404: { description: Позиция не найдена. } + 422: { description: Ошибка валидации формы либо заказ уже не в статусе NEW. } /admin/shop/order/position-restore: post: tags: [admin-shop-order] summary: Восстановить удалённую позицию заказа + description: | + Операция допустима только на заказе в статусе NEW; для обработанного/отменённого — 422. operationId: adminShopOrderPositionRestore requestBody: required: true @@ -8803,11 +8829,16 @@ paths: application/json: schema: $ref: '#/components/schemas/HttpJsonResult' + 400: { description: Параметр `id` не передан или имеет некорректный формат. } + 404: { description: Позиция не найдена. } + 422: { description: Заказ уже не в статусе NEW. } /admin/shop/order/position-change-comment: post: tags: [admin-shop-order] summary: Изменить комментарий к позиции заказа + description: | + Операция допустима только на заказе в статусе NEW; для обработанного/отменённого — 422. operationId: adminShopOrderPositionChangeComment requestBody: required: true @@ -8826,6 +8857,8 @@ paths: application/json: schema: $ref: '#/components/schemas/HttpJsonResult' + 404: { description: Позиция не найдена. } + 422: { description: Ошибка валидации формы либо заказ уже не в статусе NEW. } /admin/shop/order/export-excel: post: @@ -14808,6 +14841,12 @@ components: oneOf: - { type: object, additionalProperties: true } - { type: string, description: JSON-encoded блоки (legacy). } + categoriesId: + type: string + description: | + Список UUID категорий через запятую (например `uuid1,uuid2`). + Обрабатывается `CategoryTreeItemModelBehavior::afterSave`. Пустая строка + снимает все привязки. Без категории товар не будет виден в витрине покупателя. AdminShopProductOption: type: object @@ -14843,8 +14882,9 @@ components: type: object description: | Поля `id`, `created_user_id`, `updated_user_id`, `tenant_id` подставляются - автоматически в `BaseModel::beforeSave` — попытка передать их в payload - игнорируется (поля убраны из `safeAttributes`). + автоматически behavior'ами модели — попытка передать их в payload + перезаписывается серверными значениями. + При `update` поле `shop_product_id` игнорируется — привязку к товару менять нельзя. properties: shop_product_id: { type: string, format: uuid } status_id: { type: integer } -- 2.54.0