{
  "openapi": "3.0.0",
  "info": {
    "title": "Loyalty API",
    "version": "1.0.0"
  },
  "paths": {
    "/user/web": {
      "post": {
        "summary": "Регистрация пользователя по имени пользователя и паролю",
        "tags": [
          "User"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CredentialsForm"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Успешно",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            }
          },
          "409": {
            "description": "Пользователь с таким именем уже существует"
          },
          "422": {
            "description": "Неверный запрос"
          }
        }
      }
    },
    "/user/login": {
      "post": {
        "summary": "Логин",
        "tags": [
          "User"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CredentialsForm"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Успешный вход",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccessToken"
                }
              }
            }
          },
          "403": {
            "description": "Ошибка входа (неправильные учетные данные)"
          },
          "422": {
            "description": "Неверный запрос"
          }
        }
      }
    },
    "/user/": {
      "get": {
        "summary": "Информация о пользователе (нужна авторизация)",
        "tags": [
          "User"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Информация о пользователе",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            }
          },
          "401": {
            "description": "Не авторизован"
          }
        }
      }
    },
    "/user/logout": {
      "delete": {
        "summary": "Логаут пользователя (удаление всех токенов доступа, нужна авторизация)",
        "tags": [
          "User"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "responses": {
          "204": {
            "description": "Пользователь вышел"
          },
          "401": {
            "description": "Не авторизован"
          }
        }
      }
    },
    "/client/": {
      "get": {
        "summary": "Информация о клиенте",
        "description": "Требуемая роль: Client",
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": [
          "Client"
        ],
        "responses": {
          "200": {
            "description": "Информация о клиенте",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Client"
                }
              }
            }
          },
          "401": {
            "description": "Не авторизован"
          },
          "403": {
            "description": "Доступ запрещен (недоступна роль Client)"
          }
        }
      },
      "post": {
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Создать нового клиента (нужна авторизация)",
        "tags": [
          "Client"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClientForm"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Клиент успешно создан"
          },
          "401": {
            "description": "Не авторизован"
          },
          "422": {
            "description": "Неверный запрос"
          }
        }
      }
    },
    "/business/": {
      "post": {
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Создать новый бизнес (нужна авторизация)",
        "tags": [
          "Business"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BusinessForm"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Бизнес успешно создан"
          },
          "401": {
            "description": "Не авторизован"
          },
          "409": {
            "description": "Бизнес с таким названием уже существует"
          },
          "422": {
            "description": "Неверный запрос"
          }
        }
      }
    },
    "/business/{business_id}": {
      "get": {
        "summary": "Информация о бизнесе",
        "description": "Требуемая роль: Business или Client (бизнес может читать лишь свой бизнес)",
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "business_id",
            "in": "path",
            "required": true
          }
        ],
        "tags": [
          "Business"
        ],
        "responses": {
          "200": {
            "description": "Информация о бизнесе",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Business"
                }
              }
            }
          },
          "401": {
            "description": "Не авторизован"
          },
          "403": {
            "description": "Доступ запрещен"
          },
          "404": {
            "description": "Бизнес не найден"
          }
        }
      }
    },
    "/business/attach/": {
      "put": {
        "summary": "Прикрепить аватарку к бизнесу",
        "description": "Требуемая роль: Business",
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": [
          "Business"
        ],
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "image": {
                    "type": "string",
                    "format": "binary",
                    "description": "Файл изображения для загрузки"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Файл успешно загружен"
          },
          "401": {
            "description": "Не авторизован"
          },
          "403": {
            "description": "Доступ запрещен (вы не бизнес)"
          },
          "422": {
            "description": "Ошибка загрузки файла"
          }
        }
      },
      "delete": {
        "summary": "Убрать аватарку у бизнеса",
        "description": "Требуемая роль: Business",
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": [
          "Business"
        ],
        "responses": {
          "204": {
            "description": "Аватар убран"
          },
          "401": {
            "description": "Не авторизован"
          },
          "403": {
            "description": "Доступ запрещен (вы не бизнес)"
          }
        }
      }
    },
    "/business/stats/": {
      "get": {
        "summary": "Статистика бизнеса",
        "description": "Требуемая роль: Business",
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": [
          "Business"
        ],
        "responses": {
          "200": {
            "description": "Статистика бизнеса",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BusinessStats"
                }
              }
            }
          },
          "401": {
            "description": "Не авторизован"
          },
          "403": {
            "description": "Доступ запрещен"
          }
        }
      }
    },
    "/branch": {
      "post": {
        "summary": "Создать новый филиал для текущего бизнеса",
        "description": "Требуемая роль: Business",
        "tags": [
          "Branch"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BusinessBranchForm"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Филиал успешно создан"
          },
          "401": {
            "description": "Не авторизован"
          },
          "403": {
            "description": "Доступ запрещен (вы не бизнес)"
          },
          "422": {
            "description": "Неверный запрос"
          }
        }
      }
    },
    "/branch/{business_branch_id}": {
      "put": {
        "summary": "Обновить филиал (нужно быть бизнесом который владеет этим филиалом)",
        "description": "Требуемая роль: Business",
        "tags": [
          "Branch"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "business_branch_id",
            "in": "path",
            "required": true,
            "description": "ID филиала для обновления",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BusinessBranchForm"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Филиал успешно обновлен"
          },
          "401": {
            "description": "Не авторизован"
          },
          "403": {
            "description": "Доступ запрещен"
          },
          "404": {
            "description": "Филиал не найден"
          }
        }
      },
      "delete": {
        "summary": "Удалить филиал (нужно быть владельцем филиала)",
        "description": "Требуемая роль: Business",
        "tags": [
          "Branch"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "business_branch_id",
            "in": "path",
            "required": true,
            "description": "ID филиала для удаления",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Филиал успешно удален"
          },
          "401": {
            "description": "Не авторизован"
          },
          "403": {
            "description": "Доступ запрещен"
          },
          "404": {
            "description": "Филиал не найден"
          }
        }
      },
      "get": {
        "summary": "Получить информацию о филиале",
        "description": "Требуемая роль: Client или Business",
        "tags": [
          "Branch"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "business_branch_id",
            "in": "path",
            "required": true,
            "description": "ID филиала",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Информация о филиале",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BusinessBranch"
                }
              }
            }
          },
          "401": {
            "description": "Не авторизован"
          },
          "403": {
            "description": "Доступ запрещен"
          },
          "404": {
            "description": "Филиал не найден"
          }
        }
      }
    },
    "/business/{business_id}/branch": {
      "get": {
        "summary": "Получить все филиалы бизнеса",
        "description": "Требуемая роль: Client или Business",
        "tags": [
          "Branch"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "business_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Смещение пагинации",
            "schema": {
              "type": "integer",
              "default": 0
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Максимальное количество возвращаемых элементов",
            "schema": {
              "type": "integer",
              "default": 10
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Список филиалов бизнеса",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "branches": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/BusinessBranch"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Не авторизован"
          },
          "403": {
            "description": "Доступ запрещен"
          }
        }
      }
    },
    "/loyalty/": {
      "post": {
        "summary": "Создать новую программу лояльности",
        "description": "Требуемая роль: Business",
        "tags": [
          "Loyalty"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LoyaltyForm"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Программа лояльности успешно создана",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "loyalty_id": {
                      "type": "string",
                      "format": "uuid",
                      "example": "550e8400-e29b-41d4-a716-446655440000"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Неверные параметры даты. Дата окончания раньше даты начала"
          },
          "401": {
            "description": "Не авторизован"
          },
          "403": {
            "description": "Доступ запрещен"
          },
          "409": {
            "description": "Программа лояльности уже существует"
          },
          "422": {
            "description": "Ошибка валидации"
          }
        }
      },
      "get": {
        "summary": "Получить список программ лояльности",
        "description": "Авторизация: не требуется. Требуемая роль для возможности фильтрации программ: Client или Business",
        "tags": [
          "Loyalty"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "offset",
            "in": "query",
            "description": "Смещение пагинации",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Лимит пагинации",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 10
            }
          },
          {
            "name": "active",
            "in": "query",
            "description": "Фильтр по статусу активности. Доступно только для программ вашего бизнеса",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "time_frame",
            "in": "query",
            "description": "Фильтр по временному периоду (АКТУАЛЬНЫЕ/ВСЕ)",
            "schema": {
              "type": "string",
              "enum": [
                "CURRENT",
                "ALL"
              ],
              "default": "ALL"
            }
          },
          {
            "name": "business_id",
            "in": "query",
            "description": "Фильтр по ID бизнеса. Бизнес может просматривать только свои программы",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Список программ лояльности",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "loyalties": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Loyalty"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Не авторизован"
          },
          "403": {
            "description": "Доступ запрещен"
          },
          "422": {
            "description": "Неверная пагинация"
          }
        }
      }
    },
    "/loyalty/{loyalty_id}": {
      "get": {
        "summary": "Получить детали программы лояльности (для клиентов и программ вашего бизнеса)",
        "description": "Требуемая роль: Client или Business",
        "tags": [
          "Loyalty"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "loyalty_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Детали программы лояльности",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Loyalty"
                }
              }
            }
          },
          "401": {
            "description": "Не авторизован"
          },
          "403": {
            "description": "Доступ запрещен"
          },
          "404": {
            "description": "Программа лояльности не найдена"
          }
        }
      },
      "put": {
        "summary": "Обновить программу лояльности вашего бизнеса",
        "description": "Требуемая роль: Business",
        "tags": [
          "Loyalty"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "loyalty_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateLoyaltyForm"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Программа лояльности успешно обновлена"
          },
          "400": {
            "description": "Неверные параметры даты. Дата окончания раньше даты начала"
          },
          "401": {
            "description": "Не авторизован"
          },
          "403": {
            "description": "Доступ запрещен"
          },
          "404": {
            "description": "Программа лояльности не найдена"
          },
          "409": {
            "description": "Программа лояльности с таким названием уже существует в пределах вашего бизнеса"
          },
          "422": {
            "description": "Ошибка валидации"
          }
        }
      },
      "delete": {
        "summary": "Удалить программу лояльности вашего бизнеса",
        "description": "Требуемая роль: Business",
        "tags": [
          "Loyalty"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "loyalty_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Программа лояльности успешно удалена"
          },
          "401": {
            "description": "Не авторизован"
          },
          "403": {
            "description": "Доступ запрещен"
          },
          "404": {
            "description": "Программа лояльности не найдена"
          }
        }
      }
    },
    "/membership/": {
      "post": {
        "summary": "Создать новое участие в программе лояльности (только для клиента)",
        "description": "Требуемая роль: Client",
        "tags": [
          "Membership"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MembershipForm"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Участие успешно создано",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "membership_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Не авторизован"
          },
          "403": {
            "description": "Клиент не соответствует таргетингу"
          },
          "404": {
            "description": "Программа лояльности не существует"
          },
          "409": {
            "description": "Участие уже существует"
          },
          "422": {
            "description": "Ошибка валидации"
          }
        }
      },
      "get": {
        "summary": "Получить список текущих участий клиента (только для клиента)",
        "description": "Требуемая роль: Client",
        "tags": [
          "Membership"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "offset",
            "in": "query",
            "description": "Смещение пагинации",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Лимит пагинации",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 10
            }
          },
          {
            "name": "business_id",
            "in": "query",
            "description": "Фильтрация по бизнесу",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Список участий клиента",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "loyalties": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/LoyaltyMembership"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Не авторизован"
          },
          "403": {
            "description": "Доступ запрещен"
          },
          "422": {
            "description": "Неверная пагинация (limit < 0 или offset < 0) или limit превышает максимальный лимит"
          }
        }
      }
    },
    "/membership/{membership_id}/": {
      "delete": {
        "summary": "Удалить участие (только для клиента и только в тех программах, где он участвует)",
        "description": "Требуемая роль: Client",
        "tags": [
          "Membership"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "membership_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Участие успешно удалено"
          },
          "401": {
            "description": "Не авторизован"
          },
          "403": {
            "description": "Доступ запрещен"
          },
          "404": {
            "description": "Участие не найдено"
          }
        }
      },
      "get": {
        "summary": "Получить информацию об участии (только для клиента и только в тех программах, где он участвует)",
        "description": "Требуемая роль: Client",
        "tags": [
          "Membership"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "membership_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Детали участия",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LoyaltyMembership"
                }
              }
            }
          },
          "401": {
            "description": "Не авторизован"
          },
          "403": {
            "description": "Доступ запрещен"
          },
          "404": {
            "description": "Участие не найдено"
          }
        }
      }
    },
    "/payment/": {
      "post": {
        "summary": "Создать новый платёж",
        "description": "Требуемая роль: Business",
        "tags": [
          "Payment"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PaymentForm"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Платёж создан",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "payment_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Не авторизован"
          },
          "403": {
            "description": "Переданный клиент не участвует в программе / бизнес не владеет переданной программой / платёж не может быть совершен в этом филиале (из-за ограничений при создании программы лояльности)"
          },
          "404": {
            "description": "Обьект с одним из переданных идентификатор не существует"
          },
          "422": {
            "description": "Ошибка валидации"
          }
        }
      }
    },
    "/payment/{payment_id}/": {
      "delete": {
        "summary": "Удалить платёж",
        "description": "Требуемая роль: Business",
        "tags": [
          "Payment"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "payment_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Успешно удалено"
          },
          "401": {
            "description": "Не авторизован"
          },
          "403": {
            "description": "Доступ запрещен"
          },
          "404": {
            "description": "Обьект не найден"
          }
        }
      },
      "get": {
        "summary": "Получить информацию о платеже",
        "description": "Требуемая роль: Business",
        "tags": [
          "Payment"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "payment_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Информация о платеже",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                }
              }
            }
          },
          "401": {
            "description": "Не авторизован"
          },
          "403": {
            "description": "Доступ запрещен"
          },
          "404": {
            "description": "Обьект не найден"
          }
        }
      }
    },
    "/bonus/{membership_id}/": {
      "get": {
        "summary": "Подсчёт кол-ва бонусов у клиента в программе лояльности",
        "description": "Требуемая роль: Client",
        "tags": [
          "Bonus"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "membership_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Кол-во бонусов",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "balance"
                  ],
                  "properties": {
                    "balance": {
                      "type": "number",
                      "format": "float"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Не авторизован"
          },
          "403": {
            "description": "Клиент не состоит в программе лояльности"
          },
          "404": {
            "description": "Участие с переданным айди не найдено"
          }
        }
      }
    },
    "/bonus/discount/": {
      "get": {
        "summary": "Рассчитать новую сумму покупки с учетом скидки",
        "description": "Требуемая роль: Business",
        "tags": [
          "Bonus"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "membership_id",
            "in": "query",
            "description": "Идентификатор участия",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "purchase_amount",
            "in": "query",
            "description": "Сумма покупки",
            "required": true,
            "schema": {
              "type": "number",
              "format": "float",
              "minimum": 0.1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Информация о скидке",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Discount"
                }
              }
            }
          },
          "401": {
            "description": "Не авторизован"
          },
          "403": {
            "description": "Доступ запрещен (бизнес не владеет программой лояльности)"
          },
          "404": {
            "description": "Участие с переданным айди не найдено"
          },
          "422": {
            "description": "Ошибка валидации"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Токен авторизации (доступа)"
      }
    },
    "schemas": {
      "CredentialsForm": {
        "type": "object",
        "description": "Учетные данные пользователя",
        "required": [
          "username",
          "password"
        ],
        "properties": {
          "username": {
            "type": "string",
            "minLength": 3,
            "maxLength": 100,
            "example": "business"
          },
          "password": {
            "type": "string",
            "minLength": 6,
            "maxLength": 100,
            "example": "securePassword123",
            "format": "password"
          }
        }
      },
      "ClientForm": {
        "type": "object",
        "description": "Форма создания клиента",
        "required": [
          "full_name",
          "age",
          "gender",
          "phone",
          "lon",
          "lat"
        ],
        "properties": {
          "full_name": {
            "type": "string",
            "minLength": 4,
            "maxLength": 250,
            "example": "Иван Иванов"
          },
          "age": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "example": 30
          },
          "gender": {
            "type": "string",
            "enum": [
              "MALE",
              "FEMALE",
              "OTHER"
            ],
            "example": "MALE"
          },
          "phone": {
            "type": "string",
            "example": "+79281859225"
          },
          "lon": {
            "type": "number",
            "format": "float",
            "minimum": -90,
            "maximum": 90,
            "example": 37.6156,
            "description": "Долгота"
          },
          "lat": {
            "type": "number",
            "format": "float",
            "minimum": -180,
            "maximum": 180,
            "example": 55.7522,
            "description": "Широта"
          }
        }
      },
      "BusinessForm": {
        "type": "object",
        "description": "Форма создания бизнеса",
        "required": [
          "name",
          "contact_email"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 2,
            "maxLength": 250,
            "example": "ООО БНАЛ"
          },
          "contact_phone": {
            "type": "string",
            "example": "+79281659225",
            "description": "Контактный номер телефона бизнеса"
          },
          "contact_email": {
            "type": "string",
            "format": "email",
            "example": "structnull@yandex.ru",
            "description": "Контактная электронная почта бизнеса"
          }
        }
      },
      "Client": {
        "type": "object",
        "description": "Информация о клиенте",
        "required": [
          "client_id",
          "full_name",
          "age",
          "gender",
          "phone",
          "lon",
          "lat",
          "created_at"
        ],
        "properties": {
          "client_id": {
            "type": "string",
            "format": "uuid",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "full_name": {
            "type": "string",
            "example": "Иван Иванов"
          },
          "age": {
            "type": "integer",
            "example": 30
          },
          "gender": {
            "type": "string",
            "enum": [
              "MALE",
              "FEMALE"
            ],
            "example": "MALE"
          },
          "phone": {
            "type": "string",
            "example": "+79281559535"
          },
          "lon": {
            "type": "number",
            "format": "float",
            "example": 37.6156
          },
          "lat": {
            "type": "number",
            "format": "float",
            "example": 55.7522
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Business": {
        "type": "object",
        "description": "Информация о бизнесе",
        "required": [
          "business_id",
          "name",
          "contact_email",
          "contact_phone",
          "created_at"
        ],
        "properties": {
          "business_id": {
            "type": "string",
            "format": "uuid",
            "example": "550e8400-e29b-49d4-a716-446655440000"
          },
          "name": {
            "type": "string",
            "example": "ООО Бнал"
          },
          "contact_phone": {
            "type": "string",
            "nullable": true,
            "example": "+79281559535"
          },
          "contact_email": {
            "type": "string",
            "format": "email",
            "example": "+79281559535"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "User": {
        "type": "object",
        "description": "Информация о пользователе",
        "required": [
          "client",
          "user_id",
          "business"
        ],
        "properties": {
          "client": {
            "$ref": "#/components/schemas/Client"
          },
          "business": {
            "$ref": "#/components/schemas/Business"
          },
          "user_id": {
            "type": "string",
            "format": "uuid",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          }
        }
      },
      "AccessToken": {
        "type": "object",
        "description": "Токен доступа",
        "required": [
          "token",
          "user_id"
        ],
        "properties": {
          "user_id": {
            "type": "string",
            "format": "uuid",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "token": {
            "type": "string"
          }
        }
      },
      "BusinessBranchForm": {
        "type": "object",
        "description": "Форма создания филиала",
        "required": [
          "name",
          "lon",
          "lat"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 2,
            "maxLength": 250,
            "example": "Название филиала"
          },
          "lon": {
            "type": "number",
            "format": "float",
            "example": 37.6156,
            "description": "Долгота"
          },
          "lat": {
            "type": "number",
            "format": "float",
            "example": 55.7522,
            "description": "Широта"
          },
          "contact_phone": {
            "type": "string",
            "example": "+79281659225"
          }
        }
      },
      "BusinessBranch": {
        "type": "object",
        "description": "Филиал",
        "required": [
          "business_branch_id",
          "business_id",
          "name",
          "lon",
          "lat",
          "created_at"
        ],
        "properties": {
          "business_branch_id": {
            "type": "string",
            "format": "uuid",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "business_id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "example": "Название филиала"
          },
          "contact_phone": {
            "type": "string",
            "nullable": true,
            "example": "+79281659225"
          },
          "lon": {
            "type": "number",
            "format": "float",
            "example": 37.6156
          },
          "lat": {
            "type": "number",
            "format": "float",
            "example": 55.7522
          }
        }
      },
      "Loyalty": {
        "type": "object",
        "required": [
          "name",
          "description",
          "starts_at",
          "ends_at",
          "money_per_bonus",
          "min_age",
          "max_age",
          "is_active",
          "business_branches_id_list"
        ],
        "description": "Программа лояльности",
        "properties": {
          "loyalty_id": {
            "type": "string",
            "format": "uuid",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "name": {
            "type": "string",
            "example": "Программа лояльности"
          },
          "description": {
            "type": "string",
            "example": "Описание программы"
          },
          "starts_at": {
            "type": "string",
            "format": "date-time",
            "description": "Программа не активна, если текущая дата меньше этого поля"
          },
          "ends_at": {
            "type": "string",
            "format": "date-time",
            "description": "Программа не активна, если текущая дата больше или равна дате этого поля"
          },
          "money_per_bonus": {
            "type": "number",
            "format": "float",
            "minimum": 0.1,
            "example": 1,
            "description": "За сколько рублей клиент получает один бонус"
          },
          "money_for_bonus": {
            "type": "number",
            "format": "float",
            "minimum": 0.1,
            "example": 1,
            "description": "Cколько рублей скидки клиент получает за 1 бонус"
          },
          "min_age": {
            "type": "integer",
            "example": 18,
            "description": "Минимальный возраст клиента, при котором он может просматривать данную программу"
          },
          "max_age": {
            "type": "integer",
            "example": 99,
            "description": "Максимальный возраст клиента, при котором он может просматривать данную программу"
          },
          "is_active": {
            "type": "boolean",
            "example": true,
            "description": "Доступна ли сейчас программа к просмотру пользователем"
          },
          "gender": {
            "type": "string",
            "nullable": true,
            "enum": [
              "MALE",
              "FEMALE",
              null
            ],
            "example": "MALE",
            "description": "Пол клиентов, которые могут просматривать эту программу лояльности. При значении null программу можно просматривать вне зависимости от пола пользователя"
          },
          "business": {
            "$ref": "#/components/schemas/Business"
          },
          "business_branches": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BusinessBranch"
            },
            "description": "Список филиалов бизнеса, которые участвуют в данной программе лояльности"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "LoyaltyForm": {
        "type": "object",
        "description": "Форма создания программы лояльности",
        "required": [
          "name",
          "description",
          "starts_at",
          "ends_at",
          "money_per_bonus",
          "money_for_bonus",
          "min_age",
          "max_age",
          "business_branches_id_list"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 2,
            "maxLength": 100,
            "example": "Программа лояльности"
          },
          "description": {
            "type": "string",
            "maxLength": 950,
            "example": "Описание программы"
          },
          "starts_at": {
            "type": "string",
            "format": "date-time",
            "description": "Программа не активна, если текущая дата меньше этого поля"
          },
          "ends_at": {
            "type": "string",
            "format": "date-time",
            "description": "Программа не активна, если текущая дата больше или равна дате этого поля",
            "example": "2030-05-10T19:26:32.586Z"
          },
          "money_per_bonus": {
            "type": "number",
            "format": "float",
            "minimum": 0.1,
            "example": 1,
            "description": "За сколько рублей клиент получает один бонус"
          },
          "money_for_bonus": {
            "type": "number",
            "format": "float",
            "minimum": 0.1,
            "example": 1,
            "description": "Cколько рублей скидки клиент получает за 1 бонус"
          },
          "min_age": {
            "type": "integer",
            "minimum": 14,
            "maximum": 120,
            "example": 18,
            "description": "Минимальный возраст клиента, при котором он может просматривать данную программу"
          },
          "max_age": {
            "type": "integer",
            "minimum": 14,
            "maximum": 120,
            "example": 99,
            "description": "Максимальный возраст клиента, при котором он может просматривать данную программу"
          },
          "business_branches_id_list": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "example": [],
            "description": "Список ID филиалов бизнеса, которые участвуют в данной программе лояльности (если передан пустой список то ограничения нет)"
          },
          "gender": {
            "type": "string",
            "nullable": true,
            "enum": [
              "MALE",
              "FEMALE",
              null
            ],
            "example": "MALE",
            "description": "Пол клиентов, которые могут просматривать эту программу лояльности. При значении null программу можно просматривать вне зависимости от пола пользователя"
          }
        }
      },
      "UpdateLoyaltyForm": {
        "type": "object",
        "description": "Форма обновления программы лояльности",
        "required": [
          "name",
          "description",
          "starts_at",
          "ends_at",
          "is_active",
          "money_per_bonus",
          "business_branches_id_list"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 2,
            "maxLength": 100,
            "example": "Обновленная программа"
          },
          "description": {
            "type": "string",
            "maxLength": 950,
            "example": "Новое описание"
          },
          "starts_at": {
            "type": "string",
            "format": "date-time",
            "description": "Программа не активна, если текущая дата меньше этого поля"
          },
          "ends_at": {
            "type": "string",
            "format": "date-time",
            "description": "Программа не активна, если текущая дата больше или равна дате этого поля",
            "example": "2030-05-10T19:26:32.586Z"
          },
          "is_active": {
            "type": "boolean",
            "example": true,
            "description": "Доступна ли сейчас программа к просмотру пользователем"
          },
          "money_per_bonus": {
            "type": "number",
            "format": "float",
            "minimum": 0.1,
            "example": 1,
            "description": "За сколько рублей клиент получает один бонус"
          },
          "money_for_bonus": {
            "type": "number",
            "format": "float",
            "minimum": 0.1,
            "example": 1,
            "description": "Cколько рублей скидки клиент получает за 1 бонус"
          },
          "business_branches_id_list": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "example": [
              "550e8400-e29b-41d4-a716-446655440000"
            ],
            "description": "Список ID филиалов бизнеса, которые участвуют в данной программе лояльности"
          }
        }
      },
      "ErrorResponse": {
        "description": "Ошибка запроса",
        "type": "object",
        "properties": {
          "description": {
            "type": "string",
            "example": "Программа лояльности не существует"
          },
          "unique_code": {
            "type": "string",
            "example": "LOYALTY_DOES_NOT_EXIST"
          }
        }
      },
      "ValidationError": {
        "description": "Ошибка валидации",
        "type": "object",
        "properties": {
          "detail": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "loc": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "msg": {
                  "type": "string"
                },
                "type": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "MembershipForm": {
        "description": "Форма участия в программе лояльности",
        "type": "object",
        "required": [
          "loyalty_id"
        ],
        "properties": {
          "loyalty_id": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "LoyaltyMembership": {
        "description": "Участие в программе лояльности",
        "type": "object",
        "required": [
          "membership_id",
          "loyalty",
          "client",
          "created_at"
        ],
        "properties": {
          "membership_id": {
            "type": "string",
            "format": "uuid"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "client": {
            "$ref": "#/components/schemas/Client"
          },
          "loyalty": {
            "$ref": "#/components/schemas/Loyalty"
          }
        }
      },
      "PaymentForm": {
        "description": "Форма платежа",
        "type": "object",
        "required": [
          "payment_sum",
          "membership_id",
          "business_branch_id",
          "client_id"
        ],
        "properties": {
          "membership_id": {
            "type": "string",
            "format": "uuid",
            "description": "Идентификатор участия клиента, который совершает покупку"
          },
          "business_branch_id": {
            "type": "string",
            "format": "uuid",
            "description": "Идентификатор филиала, в котором совершается покупка"
          },
          "client_id": {
            "type": "string",
            "format": "uuid",
            "description": "Идентификатор клиента, совершающего покупку"
          },
          "payment_sum": {
            "type": "number",
            "format": "float",
            "minimum": 0.1,
            "example": 50.05,
            "description": "Сумма платежа"
          },
          "apply_discount": {
            "type": "boolean",
            "default": false,
            "description": "Потратить бонусы на скидку?"
          }
        }
      },
      "Discount": {
        "description": "Информация о скидке",
        "type": "object",
        "required": [
          "bonus_spent",
          "new_amount"
        ],
        "properties": {
          "bonus_spent": {
            "type": "number",
            "format": "float",
            "description": "Сколько будет потрачено бонусов"
          },
          "new_amount": {
            "type": "number",
            "format": "float",
            "description": "Новая сумма покупки с учетом скидки"
          }
        }
      },
      "Payment": {
        "description": "Платёж",
        "type": "object",
        "required": [
          "payment_id",
          "payment_sum",
          "service_income",
          "bonus_income",
          "bonus_spent",
          "discount_sum",
          "created_at",
          "client_id",
          "business_id",
          "loyalty_id",
          "membership_id",
          "business_branch_id"
        ],
        "properties": {
          "payment_id": {
            "type": "string",
            "format": "uuid"
          },
          "payment_sum": {
            "type": "number",
            "format": "float",
            "description": "Сумма платежа"
          },
          "client_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "business_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "loyalty_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "business_branch_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "membership_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "service_income": {
            "type": "number",
            "format": "float",
            "description": "Заработок сервиса за операцию"
          },
          "bonus_income": {
            "type": "number",
            "format": "float",
            "description": "Бонусы, полученные клиентом за операцию"
          },
          "bonus_spent": {
            "type": "number",
            "format": "float",
            "description": "Бонусы, потраченные клиентом за операцию (на скидку)"
          },
          "discount_sum": {
            "type": "number",
            "format": "float",
            "description": "Скидка"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "BusinessStats": {
        "description": "Статистика бизнеса",
        "type": "object",
        "required": [
          "payments_amount",
          "waste_amount",
          "bonus_given_amount",
          "loyalties_count",
          "memberships_count"
        ],
        "properties": {
          "payments_amount": {
            "type": "number",
            "format": "float",
            "description": "Общая сумма всех платежей"
          },
          "waste_amount": {
            "type": "number",
            "format": "float",
            "description": "Общая сумма всех трат (заработок нашего сервиса)"
          },
          "bonus_given_amount": {
            "type": "number",
            "format": "float",
            "description": "Общая сумма всех выданных бонусов"
          },
          "loyalties_count": {
            "type": "number",
            "description": "Кол-во созданных программ лояльности"
          },
          "memberships_count": {
            "type": "number",
            "description": "Кол-во клиентов которые участвуют в ваших программах"
          }
        }
      }
    }
  }
}