├── README.md ├── lombok.config ├── .github └── workflows │ ├── api-tests.yml │ └── wait-for-it.sh ├── docker-compose.yml ├── suppressions.xml ├── .gitignore ├── ewm-stats-service-spec.json ├── pom.xml ├── checkstyle.xml └── ewm-main-service-spec.json /README.md: -------------------------------------------------------------------------------- 1 | # java-explore-with-me 2 | Template repository for ExploreWithMe project. 3 | -------------------------------------------------------------------------------- /lombok.config: -------------------------------------------------------------------------------- 1 | config.stopBubbling = true 2 | lombok.anyconstructor.addconstructorproperties = false 3 | lombok.addLombokGeneratedAnnotation = true 4 | lombok.addSuppressWarnings = false -------------------------------------------------------------------------------- /.github/workflows/api-tests.yml: -------------------------------------------------------------------------------- 1 | name: Explore With Me API Tests 2 | 3 | on: 4 | pull_request: 5 | 6 | jobs: 7 | build: 8 | uses: yandex-praktikum/java-explore-with-me/.github/workflows/api-tests.yml@ci -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | stats-server: 3 | ports: 4 | - "9090:9090" 5 | 6 | stats-db: 7 | image: postgres:16.1 8 | 9 | ewm-service: 10 | ports: 11 | - "8080:8080" 12 | 13 | ewm-db: 14 | image: postgres:16.1 15 | -------------------------------------------------------------------------------- /suppressions.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | *.log 3 | *.jar 4 | *.war 5 | *.nar 6 | *.ear 7 | *.zip 8 | *.tar.gz 9 | *.rar 10 | hs_err_pid* 11 | replay_pid* 12 | out/ 13 | target/ 14 | !.mvn/wrapper/maven-wrapper.jar 15 | !**/src/main/**/target/ 16 | !**/src/test/**/target/ 17 | 18 | ### IntelliJ IDEA ### 19 | .idea 20 | *.iws 21 | *.iml 22 | *.ipr 23 | -------------------------------------------------------------------------------- /ewm-stats-service-spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.0.1", 3 | "info": { 4 | "title": "Stat service API", 5 | "version": "v0" 6 | }, 7 | "servers": [ 8 | { 9 | "url": "http://localhost:9090", 10 | "description": "Generated server url" 11 | } 12 | ], 13 | "tags": [ 14 | { 15 | "name": "StatsController", 16 | "description": "API для работы со статистикой посещений" 17 | } 18 | ], 19 | "paths": { 20 | "/hit": { 21 | "post": { 22 | "tags": [ 23 | "StatsController" 24 | ], 25 | "summary": "Сохранение информации о том, что к эндпоинту был запрос", 26 | "description": "Сохранение информации о том, что на uri конкретного сервиса был отправлен запрос пользователем. Название сервиса, uri и ip пользователя указаны в теле запроса.", 27 | "operationId": "hit", 28 | "requestBody": { 29 | "description": "данные запроса", 30 | "content": { 31 | "application/json": { 32 | "schema": { 33 | "$ref": "#/components/schemas/EndpointHit" 34 | } 35 | } 36 | }, 37 | "required": true 38 | }, 39 | "responses": { 40 | "201": { 41 | "description": "Информация сохранена" 42 | } 43 | } 44 | } 45 | }, 46 | "/stats": { 47 | "get": { 48 | "tags": [ 49 | "StatsController" 50 | ], 51 | "summary": "Получение статистики по посещениям. Обратите внимание: значение даты и времени нужно закодировать (например используя java.net.URLEncoder.encode) ", 52 | "operationId": "getStats", 53 | "parameters": [ 54 | { 55 | "name": "start", 56 | "in": "query", 57 | "description": "Дата и время начала диапазона за который нужно выгрузить статистику (в формате \"yyyy-MM-dd HH:mm:ss\")", 58 | "required": true, 59 | "schema": { 60 | "type": "string" 61 | } 62 | }, 63 | { 64 | "name": "end", 65 | "in": "query", 66 | "description": "Дата и время конца диапазона за который нужно выгрузить статистику (в формате \"yyyy-MM-dd HH:mm:ss\")", 67 | "required": true, 68 | "schema": { 69 | "type": "string" 70 | } 71 | }, 72 | { 73 | "name": "uris", 74 | "in": "query", 75 | "description": "Список uri для которых нужно выгрузить статистику", 76 | "required": false, 77 | "schema": { 78 | "type": "array", 79 | "items": { 80 | "type": "string" 81 | } 82 | } 83 | }, 84 | { 85 | "name": "unique", 86 | "in": "query", 87 | "description": "Нужно ли учитывать только уникальные посещения (только с уникальным ip)", 88 | "required": false, 89 | "schema": { 90 | "type": "boolean", 91 | "default": false 92 | } 93 | } 94 | ], 95 | "responses": { 96 | "200": { 97 | "description": "Статистика собрана", 98 | "content": { 99 | "application/json": { 100 | "schema": { 101 | "type": "array", 102 | "items": { 103 | "$ref": "#/components/schemas/ViewStats" 104 | } 105 | } 106 | } 107 | } 108 | } 109 | } 110 | } 111 | } 112 | }, 113 | "components": { 114 | "schemas": { 115 | "EndpointHit": { 116 | "type": "object", 117 | "properties": { 118 | "id": { 119 | "type": "integer", 120 | "description": "Идентификатор записи", 121 | "format": "int64", 122 | "readOnly": true, 123 | "example": 1 124 | }, 125 | "app": { 126 | "type": "string", 127 | "description": "Идентификатор сервиса для которого записывается информация", 128 | "example": "ewm-main-service" 129 | }, 130 | "uri": { 131 | "type": "string", 132 | "description": "URI для которого был осуществлен запрос", 133 | "example": "/events/1" 134 | }, 135 | "ip": { 136 | "type": "string", 137 | "description": "IP-адрес пользователя, осуществившего запрос", 138 | "example": "192.163.0.1" 139 | }, 140 | "timestamp": { 141 | "type": "string", 142 | "description": "Дата и время, когда был совершен запрос к эндпоинту (в формате \"yyyy-MM-dd HH:mm:ss\")", 143 | "example": "2022-09-06 11:00:23" 144 | } 145 | } 146 | }, 147 | "ViewStats": { 148 | "type": "object", 149 | "properties": { 150 | "app": { 151 | "type": "string", 152 | "description": "Название сервиса", 153 | "example": "ewm-main-service" 154 | }, 155 | "uri": { 156 | "type": "string", 157 | "description": "URI сервиса", 158 | "example": "/events/1" 159 | }, 160 | "hits": { 161 | "type": "integer", 162 | "description": "Количество просмотров", 163 | "format": "int64", 164 | "example": 6 165 | } 166 | } 167 | } 168 | } 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | 7 | org.springframework.boot 8 | spring-boot-starter-parent 9 | 3.3.2 10 | 11 | 12 | 13 | Explore With Me 14 | 15 | ru.practicum 16 | explore-with-me 17 | 0.0.1-SNAPSHOT 18 | pom 19 | 20 | 21 | 21 22 | UTF-8 23 | 24 | 25 | 26 | 27 | 28 | 29 | org.apache.maven.plugins 30 | maven-surefire-plugin 31 | 32 | 33 | test 34 | 35 | 36 | 37 | 38 | org.apache.maven.plugins 39 | maven-checkstyle-plugin 40 | 3.1.2 41 | 42 | checkstyle.xml 43 | true 44 | true 45 | true 46 | 47 | 48 | 49 | 50 | check 51 | 52 | compile 53 | 54 | 55 | 56 | 57 | com.puppycrawl.tools 58 | checkstyle 59 | 10.3 60 | 61 | 62 | 63 | 64 | com.github.spotbugs 65 | spotbugs-maven-plugin 66 | 4.8.5.0 67 | 68 | Max 69 | High 70 | 71 | 72 | 73 | 74 | check 75 | 76 | 77 | 78 | 79 | 80 | org.jacoco 81 | jacoco-maven-plugin 82 | 0.8.12 83 | 84 | file 85 | 86 | 87 | 88 | jacoco-initialize 89 | 90 | prepare-agent 91 | 92 | 93 | 94 | jacoco-check 95 | 96 | check 97 | 98 | 99 | 100 | 101 | BUNDLE 102 | 103 | 104 | INSTRUCTION 105 | COVEREDRATIO 106 | 0.01 107 | 108 | 109 | LINE 110 | COVEREDRATIO 111 | 0.2 112 | 113 | 114 | BRANCH 115 | COVEREDRATIO 116 | 0.2 117 | 118 | 119 | COMPLEXITY 120 | COVEREDRATIO 121 | 0.2 122 | 123 | 124 | METHOD 125 | COVEREDRATIO 126 | 0.2 127 | 128 | 129 | CLASS 130 | MISSEDCOUNT 131 | 1 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | jacoco-site 140 | install 141 | 142 | report 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | check 153 | 154 | 155 | 156 | org.apache.maven.plugins 157 | maven-checkstyle-plugin 158 | 159 | 160 | com.github.spotbugs 161 | spotbugs-maven-plugin 162 | 163 | 164 | 165 | 166 | 167 | 168 | com.github.spotbugs 169 | spotbugs-maven-plugin 170 | 171 | 172 | 173 | 174 | 175 | coverage 176 | 177 | 178 | 179 | org.jacoco 180 | jacoco-maven-plugin 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | -------------------------------------------------------------------------------- /.github/workflows/wait-for-it.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Use this script to test if a given TCP host/port are available 3 | 4 | WAITFORIT_cmdname=${0##*/} 5 | 6 | echoerr() { if [[ $WAITFORIT_QUIET -ne 1 ]]; then echo "$@" 1>&2; fi } 7 | 8 | usage() 9 | { 10 | cat << USAGE >&2 11 | Usage: 12 | $WAITFORIT_cmdname host:port [-s] [-t timeout] [-- command args] 13 | -h HOST | --host=HOST Host or IP under test 14 | -p PORT | --port=PORT TCP port under test 15 | Alternatively, you specify the host and port as host:port 16 | -s | --strict Only execute subcommand if the test succeeds 17 | -q | --quiet Don't output any status messages 18 | -t TIMEOUT | --timeout=TIMEOUT 19 | Timeout in seconds, zero for no timeout 20 | -- COMMAND ARGS Execute command with args after the test finishes 21 | USAGE 22 | exit 1 23 | } 24 | 25 | wait_for() 26 | { 27 | if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then 28 | echoerr "$WAITFORIT_cmdname: waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT" 29 | else 30 | echoerr "$WAITFORIT_cmdname: waiting for $WAITFORIT_HOST:$WAITFORIT_PORT without a timeout" 31 | fi 32 | WAITFORIT_start_ts=$(date +%s) 33 | while : 34 | do 35 | if [[ $WAITFORIT_ISBUSY -eq 1 ]]; then 36 | nc -z $WAITFORIT_HOST $WAITFORIT_PORT 37 | WAITFORIT_result=$? 38 | else 39 | # (echo -n > /dev/tcp/$WAITFORIT_HOST/$WAITFORIT_PORT) >/dev/null 2>&1 40 | (curl --fail --silent $WAITFORIT_HOST:$WAITFORIT_PORT/actuator/health | grep UP) >/dev/null 2>&1 41 | WAITFORIT_result=$? 42 | fi 43 | if [[ $WAITFORIT_result -eq 0 ]]; then 44 | WAITFORIT_end_ts=$(date +%s) 45 | echoerr "$WAITFORIT_cmdname: $WAITFORIT_HOST:$WAITFORIT_PORT is available after $((WAITFORIT_end_ts - WAITFORIT_start_ts)) seconds" 46 | break 47 | fi 48 | sleep 1 49 | done 50 | return $WAITFORIT_result 51 | } 52 | 53 | wait_for_wrapper() 54 | { 55 | # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692 56 | if [[ $WAITFORIT_QUIET -eq 1 ]]; then 57 | timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --quiet --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT & 58 | else 59 | timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT & 60 | fi 61 | WAITFORIT_PID=$! 62 | trap "kill -INT -$WAITFORIT_PID" INT 63 | wait $WAITFORIT_PID 64 | WAITFORIT_RESULT=$? 65 | if [[ $WAITFORIT_RESULT -ne 0 ]]; then 66 | echoerr "$WAITFORIT_cmdname: timeout occurred after waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT" 67 | fi 68 | return $WAITFORIT_RESULT 69 | } 70 | 71 | # process arguments 72 | while [[ $# -gt 0 ]] 73 | do 74 | case "$1" in 75 | *:* ) 76 | WAITFORIT_hostport=(${1//:/ }) 77 | WAITFORIT_HOST=${WAITFORIT_hostport[0]} 78 | WAITFORIT_PORT=${WAITFORIT_hostport[1]} 79 | shift 1 80 | ;; 81 | --child) 82 | WAITFORIT_CHILD=1 83 | shift 1 84 | ;; 85 | -q | --quiet) 86 | WAITFORIT_QUIET=1 87 | shift 1 88 | ;; 89 | -s | --strict) 90 | WAITFORIT_STRICT=1 91 | shift 1 92 | ;; 93 | -h) 94 | WAITFORIT_HOST="$2" 95 | if [[ $WAITFORIT_HOST == "" ]]; then break; fi 96 | shift 2 97 | ;; 98 | --host=*) 99 | WAITFORIT_HOST="${1#*=}" 100 | shift 1 101 | ;; 102 | -p) 103 | WAITFORIT_PORT="$2" 104 | if [[ $WAITFORIT_PORT == "" ]]; then break; fi 105 | shift 2 106 | ;; 107 | --port=*) 108 | WAITFORIT_PORT="${1#*=}" 109 | shift 1 110 | ;; 111 | -t) 112 | WAITFORIT_TIMEOUT="$2" 113 | if [[ $WAITFORIT_TIMEOUT == "" ]]; then break; fi 114 | shift 2 115 | ;; 116 | --timeout=*) 117 | WAITFORIT_TIMEOUT="${1#*=}" 118 | shift 1 119 | ;; 120 | --) 121 | shift 122 | WAITFORIT_CLI=("$@") 123 | break 124 | ;; 125 | --help) 126 | usage 127 | ;; 128 | *) 129 | echoerr "Unknown argument: $1" 130 | usage 131 | ;; 132 | esac 133 | done 134 | 135 | if [[ "$WAITFORIT_HOST" == "" || "$WAITFORIT_PORT" == "" ]]; then 136 | echoerr "Error: you need to provide a host and port to test." 137 | usage 138 | fi 139 | 140 | WAITFORIT_TIMEOUT=${WAITFORIT_TIMEOUT:-15} 141 | WAITFORIT_STRICT=${WAITFORIT_STRICT:-0} 142 | WAITFORIT_CHILD=${WAITFORIT_CHILD:-0} 143 | WAITFORIT_QUIET=${WAITFORIT_QUIET:-0} 144 | 145 | # Check to see if timeout is from busybox? 146 | WAITFORIT_TIMEOUT_PATH=$(type -p timeout) 147 | WAITFORIT_TIMEOUT_PATH=$(realpath $WAITFORIT_TIMEOUT_PATH 2>/dev/null || readlink -f $WAITFORIT_TIMEOUT_PATH) 148 | 149 | WAITFORIT_BUSYTIMEFLAG="" 150 | if [[ $WAITFORIT_TIMEOUT_PATH =~ "busybox" ]]; then 151 | WAITFORIT_ISBUSY=1 152 | # Check if busybox timeout uses -t flag 153 | # (recent Alpine versions don't support -t anymore) 154 | if timeout &>/dev/stdout | grep -q -e '-t '; then 155 | WAITFORIT_BUSYTIMEFLAG="-t" 156 | fi 157 | else 158 | WAITFORIT_ISBUSY=0 159 | fi 160 | 161 | if [[ $WAITFORIT_CHILD -gt 0 ]]; then 162 | wait_for 163 | WAITFORIT_RESULT=$? 164 | exit $WAITFORIT_RESULT 165 | else 166 | if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then 167 | wait_for_wrapper 168 | WAITFORIT_RESULT=$? 169 | else 170 | wait_for 171 | WAITFORIT_RESULT=$? 172 | fi 173 | fi 174 | 175 | if [[ $WAITFORIT_CLI != "" ]]; then 176 | if [[ $WAITFORIT_RESULT -ne 0 && $WAITFORIT_STRICT -eq 1 ]]; then 177 | echoerr "$WAITFORIT_cmdname: strict mode, refusing to execute subprocess" 178 | exit $WAITFORIT_RESULT 179 | fi 180 | exec "${WAITFORIT_CLI[@]}" 181 | else 182 | exit $WAITFORIT_RESULT 183 | fi -------------------------------------------------------------------------------- /checkstyle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | -------------------------------------------------------------------------------- /ewm-main-service-spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.0.1", 3 | "info": { 4 | "description": "Documentation \"Explore With Me\" API v1.0", 5 | "title": "\"Explore With Me\" API сервер", 6 | "version": "1.0" 7 | }, 8 | "servers": [ 9 | { 10 | "description": "Generated server url", 11 | "url": "http://localhost:8080" 12 | } 13 | ], 14 | "tags": [ 15 | { 16 | "description": "Публичный API для работы с подборками событий", 17 | "name": "Public: Подборки событий" 18 | }, 19 | { 20 | "description": "API для работы с категориями", 21 | "name": "Admin: Категории" 22 | }, 23 | { 24 | "description": "Закрытый API для работы с событиями", 25 | "name": "Private: События" 26 | }, 27 | { 28 | "description": "Публичный API для работы с категориями", 29 | "name": "Public: Категории" 30 | }, 31 | { 32 | "description": "API для работы с событиями", 33 | "name": "Admin: События" 34 | }, 35 | { 36 | "description": "Публичный API для работы с событиями", 37 | "name": "Public: События" 38 | }, 39 | { 40 | "description": "Закрытый API для работы с запросами текущего пользователя на участие в событиях", 41 | "name": "Private: Запросы на участие" 42 | }, 43 | { 44 | "description": "API для работы с пользователями", 45 | "name": "Admin: Пользователи" 46 | }, 47 | { 48 | "description": "API для работы с подборками событий", 49 | "name": "Admin: Подборки событий" 50 | } 51 | ], 52 | "paths": { 53 | "/admin/categories": { 54 | "post": { 55 | "description": "Обратите внимание: имя категории должно быть уникальным", 56 | "operationId": "addCategory", 57 | "requestBody": { 58 | "content": { 59 | "application/json": { 60 | "schema": { 61 | "$ref": "#/components/schemas/NewCategoryDto" 62 | } 63 | } 64 | }, 65 | "description": "данные добавляемой категории", 66 | "required": true 67 | }, 68 | "responses": { 69 | "201": { 70 | "content": { 71 | "application/json": { 72 | "schema": { 73 | "$ref": "#/components/schemas/CategoryDto" 74 | } 75 | } 76 | }, 77 | "description": "Категория добавлена" 78 | }, 79 | "400": { 80 | "content": { 81 | "application/json": { 82 | "example": { 83 | "status": "BAD_REQUEST", 84 | "reason": "Incorrectly made request.", 85 | "message": "Field: name. Error: must not be blank. Value: null", 86 | "timestamp": "2022-09-07 09:10:50" 87 | }, 88 | "schema": { 89 | "$ref": "#/components/schemas/ApiError" 90 | } 91 | } 92 | }, 93 | "description": "Запрос составлен некорректно" 94 | }, 95 | "409": { 96 | "content": { 97 | "application/json": { 98 | "example": { 99 | "status": "CONFLICT", 100 | "reason": "Integrity constraint has been violated.", 101 | "message": "could not execute statement; SQL [n/a]; constraint [uq_category_name]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement", 102 | "timestamp": "2022-09-07 09:10:50" 103 | }, 104 | "schema": { 105 | "$ref": "#/components/schemas/ApiError" 106 | } 107 | } 108 | }, 109 | "description": "Нарушение целостности данных" 110 | } 111 | }, 112 | "summary": "Добавление новой категории", 113 | "tags": [ 114 | "Admin: Категории" 115 | ] 116 | } 117 | }, 118 | "/admin/categories/{catId}": { 119 | "delete": { 120 | "description": "Обратите внимание: с категорией не должно быть связано ни одного события.", 121 | "operationId": "deleteCategory", 122 | "parameters": [ 123 | { 124 | "description": "id категории", 125 | "in": "path", 126 | "name": "catId", 127 | "required": true, 128 | "schema": { 129 | "type": "integer", 130 | "format": "int64" 131 | } 132 | } 133 | ], 134 | "responses": { 135 | "204": { 136 | "description": "Категория удалена" 137 | }, 138 | "404": { 139 | "content": { 140 | "application/json": { 141 | "example": { 142 | "status": "NOT_FOUND", 143 | "reason": "The required object was not found.", 144 | "message": "Category with id=27 was not found", 145 | "timestamp": "2022-09-07 09:10:50" 146 | }, 147 | "schema": { 148 | "$ref": "#/components/schemas/ApiError" 149 | } 150 | } 151 | }, 152 | "description": "Категория не найдена или недоступна" 153 | }, 154 | "409": { 155 | "content": { 156 | "application/json": { 157 | "example": { 158 | "status": "CONFLICT", 159 | "reason": "For the requested operation the conditions are not met.", 160 | "message": "The category is not empty", 161 | "timestamp": "2023-01-21 16:56:19" 162 | }, 163 | "schema": { 164 | "$ref": "#/components/schemas/ApiError" 165 | } 166 | } 167 | }, 168 | "description": "Существуют события, связанные с категорией" 169 | } 170 | }, 171 | "summary": "Удаление категории", 172 | "tags": [ 173 | "Admin: Категории" 174 | ] 175 | }, 176 | "patch": { 177 | "description": "Обратите внимание: имя категории должно быть уникальным", 178 | "operationId": "updateCategory", 179 | "parameters": [ 180 | { 181 | "description": "id категории", 182 | "in": "path", 183 | "name": "catId", 184 | "required": true, 185 | "schema": { 186 | "type": "integer", 187 | "format": "int64" 188 | } 189 | } 190 | ], 191 | "requestBody": { 192 | "content": { 193 | "application/json": { 194 | "schema": { 195 | "$ref": "#/components/schemas/CategoryDto" 196 | } 197 | } 198 | }, 199 | "description": "Данные категории для изменения", 200 | "required": true 201 | }, 202 | "responses": { 203 | "200": { 204 | "content": { 205 | "application/json": { 206 | "schema": { 207 | "$ref": "#/components/schemas/CategoryDto" 208 | } 209 | } 210 | }, 211 | "description": "Данные категории изменены" 212 | }, 213 | "404": { 214 | "content": { 215 | "application/json": { 216 | "example": { 217 | "status": "NOT_FOUND", 218 | "reason": "The required object was not found.", 219 | "message": "Category with id=27 was not found", 220 | "timestamp": "2022-09-07 09:10:50" 221 | }, 222 | "schema": { 223 | "$ref": "#/components/schemas/ApiError" 224 | } 225 | } 226 | }, 227 | "description": "Категория не найдена или недоступна" 228 | }, 229 | "409": { 230 | "content": { 231 | "application/json": { 232 | "example": { 233 | "status": "CONFLICT", 234 | "reason": "Integrity constraint has been violated.", 235 | "message": "could not execute statement; SQL [n/a]; constraint [uq_category_name]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement", 236 | "timestamp": "2022-09-07 09:10:50" 237 | }, 238 | "schema": { 239 | "$ref": "#/components/schemas/ApiError" 240 | } 241 | } 242 | }, 243 | "description": "Нарушение целостности данных" 244 | } 245 | }, 246 | "summary": "Изменение категории", 247 | "tags": [ 248 | "Admin: Категории" 249 | ] 250 | } 251 | }, 252 | "/admin/compilations": { 253 | "post": { 254 | "operationId": "saveCompilation", 255 | "requestBody": { 256 | "content": { 257 | "application/json": { 258 | "schema": { 259 | "$ref": "#/components/schemas/NewCompilationDto" 260 | } 261 | } 262 | }, 263 | "description": "данные новой подборки", 264 | "required": true 265 | }, 266 | "responses": { 267 | "201": { 268 | "content": { 269 | "application/json": { 270 | "schema": { 271 | "$ref": "#/components/schemas/CompilationDto" 272 | } 273 | } 274 | }, 275 | "description": "Подборка добавлена" 276 | }, 277 | "400": { 278 | "content": { 279 | "application/json": { 280 | "example": { 281 | "status": "BAD_REQUEST", 282 | "reason": "Incorrectly made request.", 283 | "message": "Field: title. Error: must not be blank. Value: null", 284 | "timestamp": "2022-09-07 09:10:50" 285 | }, 286 | "schema": { 287 | "$ref": "#/components/schemas/ApiError" 288 | } 289 | } 290 | }, 291 | "description": "Запрос составлен некорректно" 292 | }, 293 | "409": { 294 | "content": { 295 | "application/json": { 296 | "example": { 297 | "status": "CONFLICT", 298 | "reason": "Integrity constraint has been violated.", 299 | "message": "could not execute statement; SQL [n/a]; constraint [uq_compilation_name]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement", 300 | "timestamp": "2022-09-07 09:10:50" 301 | }, 302 | "schema": { 303 | "$ref": "#/components/schemas/ApiError" 304 | } 305 | } 306 | }, 307 | "description": "Нарушение целостности данных" 308 | } 309 | }, 310 | "summary": "Добавление новой подборки (подборка может не содержать событий)", 311 | "tags": [ 312 | "Admin: Подборки событий" 313 | ] 314 | } 315 | }, 316 | "/admin/compilations/{compId}": { 317 | "delete": { 318 | "operationId": "deleteCompilation", 319 | "parameters": [ 320 | { 321 | "description": "id подборки", 322 | "in": "path", 323 | "name": "compId", 324 | "required": true, 325 | "schema": { 326 | "type": "integer", 327 | "format": "int64" 328 | } 329 | } 330 | ], 331 | "responses": { 332 | "204": { 333 | "description": "Подборка удалена" 334 | }, 335 | "404": { 336 | "content": { 337 | "application/json": { 338 | "example": { 339 | "status": "NOT_FOUND", 340 | "reason": "The required object was not found.", 341 | "message": "Compilation with id=11 was not found", 342 | "timestamp": "2022-09-07 09:10:50" 343 | }, 344 | "schema": { 345 | "$ref": "#/components/schemas/ApiError" 346 | } 347 | } 348 | }, 349 | "description": "Подборка не найдена или недоступна" 350 | } 351 | }, 352 | "summary": "Удаление подборки", 353 | "tags": [ 354 | "Admin: Подборки событий" 355 | ] 356 | }, 357 | "patch": { 358 | "operationId": "updateCompilation", 359 | "parameters": [ 360 | { 361 | "description": "id подборки", 362 | "in": "path", 363 | "name": "compId", 364 | "required": true, 365 | "schema": { 366 | "type": "integer", 367 | "format": "int64" 368 | } 369 | } 370 | ], 371 | "requestBody": { 372 | "content": { 373 | "application/json": { 374 | "schema": { 375 | "$ref": "#/components/schemas/UpdateCompilationRequest" 376 | } 377 | } 378 | }, 379 | "description": "данные для обновления подборки", 380 | "required": true 381 | }, 382 | "responses": { 383 | "200": { 384 | "content": { 385 | "application/json": { 386 | "schema": { 387 | "$ref": "#/components/schemas/CompilationDto" 388 | } 389 | } 390 | }, 391 | "description": "Подборка обновлена" 392 | }, 393 | "404": { 394 | "content": { 395 | "application/json": { 396 | "example": { 397 | "status": "NOT_FOUND", 398 | "reason": "The required object was not found.", 399 | "message": "Category with id=27 was not found", 400 | "timestamp": "2022-09-07 09:10:50" 401 | }, 402 | "schema": { 403 | "$ref": "#/components/schemas/ApiError" 404 | } 405 | } 406 | }, 407 | "description": "Подборка не найдена или недоступна" 408 | } 409 | }, 410 | "summary": "Обновить информацию о подборке", 411 | "tags": [ 412 | "Admin: Подборки событий" 413 | ] 414 | } 415 | }, 416 | "/admin/events": { 417 | "get": { 418 | "description": "Эндпоинт возвращает полную информацию обо всех событиях подходящих под переданные условия\n\nВ случае, если по заданным фильтрам не найдено ни одного события, возвращает пустой список", 419 | "operationId": "getEvents_2", 420 | "parameters": [ 421 | { 422 | "description": "список id пользователей, чьи события нужно найти", 423 | "in": "query", 424 | "name": "users", 425 | "required": false, 426 | "schema": { 427 | "type": "array", 428 | "items": { 429 | "type": "integer", 430 | "format": "int64" 431 | } 432 | } 433 | }, 434 | { 435 | "description": "список состояний в которых находятся искомые события", 436 | "in": "query", 437 | "name": "states", 438 | "required": false, 439 | "schema": { 440 | "type": "array", 441 | "items": { 442 | "type": "string" 443 | } 444 | } 445 | }, 446 | { 447 | "description": "список id категорий в которых будет вестись поиск", 448 | "in": "query", 449 | "name": "categories", 450 | "required": false, 451 | "schema": { 452 | "type": "array", 453 | "items": { 454 | "type": "integer", 455 | "format": "int64" 456 | } 457 | } 458 | }, 459 | { 460 | "description": "дата и время не раньше которых должно произойти событие", 461 | "in": "query", 462 | "name": "rangeStart", 463 | "required": false, 464 | "schema": { 465 | "type": "string" 466 | } 467 | }, 468 | { 469 | "description": "дата и время не позже которых должно произойти событие", 470 | "in": "query", 471 | "name": "rangeEnd", 472 | "required": false, 473 | "schema": { 474 | "type": "string" 475 | } 476 | }, 477 | { 478 | "description": "количество событий, которые нужно пропустить для формирования текущего набора", 479 | "in": "query", 480 | "name": "from", 481 | "required": false, 482 | "schema": { 483 | "minimum": 0, 484 | "type": "integer", 485 | "format": "int32", 486 | "default": 0 487 | } 488 | }, 489 | { 490 | "description": "количество событий в наборе", 491 | "in": "query", 492 | "name": "size", 493 | "required": false, 494 | "schema": { 495 | "type": "integer", 496 | "format": "int32", 497 | "default": 10 498 | } 499 | } 500 | ], 501 | "responses": { 502 | "200": { 503 | "content": { 504 | "application/json": { 505 | "schema": { 506 | "type": "array", 507 | "items": { 508 | "$ref": "#/components/schemas/EventFullDto" 509 | } 510 | } 511 | } 512 | }, 513 | "description": "События найдены" 514 | }, 515 | "400": { 516 | "content": { 517 | "application/json": { 518 | "example": { 519 | "status": "BAD_REQUEST", 520 | "reason": "Incorrectly made request.", 521 | "message": "Failed to convert value of type java.lang.String to required type int; nested exception is java.lang.NumberFormatException: For input string: ad", 522 | "timestamp": "2022-09-07 09:10:50" 523 | }, 524 | "schema": { 525 | "$ref": "#/components/schemas/ApiError" 526 | } 527 | } 528 | }, 529 | "description": "Запрос составлен некорректно" 530 | } 531 | }, 532 | "summary": "Поиск событий", 533 | "tags": [ 534 | "Admin: События" 535 | ] 536 | } 537 | }, 538 | "/admin/events/{eventId}": { 539 | "patch": { 540 | "description": "Редактирование данных любого события администратором. Валидация данных не требуется.\nОбратите внимание:\n - дата начала изменяемого события должна быть не ранее чем за час от даты публикации. (Ожидается код ошибки 409)\n- событие можно публиковать, только если оно в состоянии ожидания публикации (Ожидается код ошибки 409)\n- событие можно отклонить, только если оно еще не опубликовано (Ожидается код ошибки 409)", 541 | "operationId": "updateEvent_1", 542 | "parameters": [ 543 | { 544 | "description": "id события", 545 | "in": "path", 546 | "name": "eventId", 547 | "required": true, 548 | "schema": { 549 | "type": "integer", 550 | "format": "int64" 551 | } 552 | } 553 | ], 554 | "requestBody": { 555 | "content": { 556 | "application/json": { 557 | "schema": { 558 | "$ref": "#/components/schemas/UpdateEventAdminRequest" 559 | } 560 | } 561 | }, 562 | "description": "Данные для изменения информации о событии", 563 | "required": true 564 | }, 565 | "responses": { 566 | "200": { 567 | "content": { 568 | "application/json": { 569 | "schema": { 570 | "$ref": "#/components/schemas/EventFullDto" 571 | } 572 | } 573 | }, 574 | "description": "Событие отредактировано" 575 | }, 576 | "404": { 577 | "content": { 578 | "application/json": { 579 | "example": { 580 | "status": "NOT_FOUND", 581 | "reason": "The required object was not found.", 582 | "message": "Event with id=2 was not found", 583 | "timestamp": "2022-09-07 09:10:50" 584 | }, 585 | "schema": { 586 | "$ref": "#/components/schemas/ApiError" 587 | } 588 | } 589 | }, 590 | "description": "Событие не найдено или недоступно" 591 | }, 592 | "409": { 593 | "content": { 594 | "application/json": { 595 | "example": { 596 | "status": "FORBIDDEN", 597 | "reason": "For the requested operation the conditions are not met.", 598 | "message": "Cannot publish the event because it's not in the right state: PUBLISHED", 599 | "timestamp": "2022-09-07 09:10:50" 600 | }, 601 | "schema": { 602 | "$ref": "#/components/schemas/ApiError" 603 | } 604 | } 605 | }, 606 | "description": "Событие не удовлетворяет правилам редактирования" 607 | } 608 | }, 609 | "summary": "Редактирование данных события и его статуса (отклонение/публикация).", 610 | "tags": [ 611 | "Admin: События" 612 | ] 613 | } 614 | }, 615 | "/admin/users": { 616 | "get": { 617 | "description": "Возвращает информацию обо всех пользователях (учитываются параметры ограничения выборки), либо о конкретных (учитываются указанные идентификаторы)\n\nВ случае, если по заданным фильтрам не найдено ни одного пользователя, возвращает пустой список", 618 | "operationId": "getUsers", 619 | "parameters": [ 620 | { 621 | "description": "id пользователей", 622 | "in": "query", 623 | "name": "ids", 624 | "required": false, 625 | "schema": { 626 | "type": "array", 627 | "items": { 628 | "type": "integer", 629 | "format": "int64" 630 | } 631 | } 632 | }, 633 | { 634 | "description": "количество элементов, которые нужно пропустить для формирования текущего набора", 635 | "in": "query", 636 | "name": "from", 637 | "required": false, 638 | "schema": { 639 | "minimum": 0, 640 | "type": "integer", 641 | "format": "int32", 642 | "default": 0 643 | } 644 | }, 645 | { 646 | "description": "количество элементов в наборе", 647 | "in": "query", 648 | "name": "size", 649 | "required": false, 650 | "schema": { 651 | "type": "integer", 652 | "format": "int32", 653 | "default": 10 654 | } 655 | } 656 | ], 657 | "responses": { 658 | "200": { 659 | "content": { 660 | "application/json": { 661 | "schema": { 662 | "type": "array", 663 | "items": { 664 | "$ref": "#/components/schemas/UserDto" 665 | } 666 | } 667 | } 668 | }, 669 | "description": "Пользователи найдены" 670 | }, 671 | "400": { 672 | "content": { 673 | "application/json": { 674 | "example": { 675 | "status": "BAD_REQUEST", 676 | "reason": "Incorrectly made request.", 677 | "message": "Failed to convert value of type java.lang.String to required type int; nested exception is java.lang.NumberFormatException: For input string: ad", 678 | "timestamp": "2022-09-07 09:10:50" 679 | }, 680 | "schema": { 681 | "$ref": "#/components/schemas/ApiError" 682 | } 683 | } 684 | }, 685 | "description": "Запрос составлен некорректно" 686 | } 687 | }, 688 | "summary": "Получение информации о пользователях", 689 | "tags": [ 690 | "Admin: Пользователи" 691 | ] 692 | }, 693 | "post": { 694 | "operationId": "registerUser", 695 | "requestBody": { 696 | "content": { 697 | "application/json": { 698 | "schema": { 699 | "$ref": "#/components/schemas/NewUserRequest" 700 | } 701 | } 702 | }, 703 | "description": "Данные добавляемого пользователя", 704 | "required": true 705 | }, 706 | "responses": { 707 | "201": { 708 | "content": { 709 | "application/json": { 710 | "schema": { 711 | "$ref": "#/components/schemas/UserDto" 712 | } 713 | } 714 | }, 715 | "description": "Пользователь зарегистрирован" 716 | }, 717 | "400": { 718 | "content": { 719 | "application/json": { 720 | "example": { 721 | "status": "BAD_REQUEST", 722 | "reason": "Incorrectly made request.", 723 | "message": "Field: name. Error: must not be blank. Value: null", 724 | "timestamp": "2022-09-07 09:10:50" 725 | }, 726 | "schema": { 727 | "$ref": "#/components/schemas/ApiError" 728 | } 729 | } 730 | }, 731 | "description": "Запрос составлен некорректно" 732 | }, 733 | "409": { 734 | "content": { 735 | "application/json": { 736 | "example": { 737 | "status": "CONFLICT", 738 | "reason": "Integrity constraint has been violated.", 739 | "message": "could not execute statement; SQL [n/a]; constraint [uq_email]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement", 740 | "timestamp": "2022-09-07 09:10:50" 741 | }, 742 | "schema": { 743 | "$ref": "#/components/schemas/ApiError" 744 | } 745 | } 746 | }, 747 | "description": "Нарушение целостности данных" 748 | } 749 | }, 750 | "summary": "Добавление нового пользователя", 751 | "tags": [ 752 | "Admin: Пользователи" 753 | ] 754 | } 755 | }, 756 | "/admin/users/{userId}": { 757 | "delete": { 758 | "operationId": "delete", 759 | "parameters": [ 760 | { 761 | "description": "id пользователя", 762 | "in": "path", 763 | "name": "userId", 764 | "required": true, 765 | "schema": { 766 | "type": "integer", 767 | "format": "int64" 768 | } 769 | } 770 | ], 771 | "responses": { 772 | "204": { 773 | "description": "Пользователь удален" 774 | }, 775 | "404": { 776 | "content": { 777 | "application/json": { 778 | "example": { 779 | "status": "NOT_FOUND", 780 | "reason": "The required object was not found.", 781 | "message": "User with id=555 was not found", 782 | "timestamp": "2022-09-07 09:10:50" 783 | }, 784 | "schema": { 785 | "$ref": "#/components/schemas/ApiError" 786 | } 787 | } 788 | }, 789 | "description": "Пользователь не найден или недоступен" 790 | } 791 | }, 792 | "summary": "Удаление пользователя", 793 | "tags": [ 794 | "Admin: Пользователи" 795 | ] 796 | } 797 | }, 798 | "/categories": { 799 | "get": { 800 | "description": "В случае, если по заданным фильтрам не найдено ни одной категории, возвращает пустой список", 801 | "operationId": "getCategories", 802 | "parameters": [ 803 | { 804 | "description": "количество категорий, которые нужно пропустить для формирования текущего набора", 805 | "in": "query", 806 | "name": "from", 807 | "required": false, 808 | "schema": { 809 | "minimum": 0, 810 | "type": "integer", 811 | "format": "int32", 812 | "default": 0 813 | } 814 | }, 815 | { 816 | "description": "количество категорий в наборе", 817 | "in": "query", 818 | "name": "size", 819 | "required": false, 820 | "schema": { 821 | "type": "integer", 822 | "format": "int32", 823 | "default": 10 824 | } 825 | } 826 | ], 827 | "responses": { 828 | "200": { 829 | "content": { 830 | "application/json": { 831 | "schema": { 832 | "type": "array", 833 | "items": { 834 | "$ref": "#/components/schemas/CategoryDto" 835 | } 836 | } 837 | } 838 | }, 839 | "description": "Категории найдены" 840 | }, 841 | "400": { 842 | "content": { 843 | "application/json": { 844 | "example": { 845 | "status": "BAD_REQUEST", 846 | "reason": "Incorrectly made request.", 847 | "message": "Failed to convert value of type java.lang.String to required type int; nested exception is java.lang.NumberFormatException: For input string: ad", 848 | "timestamp": "2022-09-07 09:10:50" 849 | }, 850 | "schema": { 851 | "$ref": "#/components/schemas/ApiError" 852 | } 853 | } 854 | }, 855 | "description": "Запрос составлен некорректно" 856 | } 857 | }, 858 | "summary": "Получение категорий", 859 | "tags": [ 860 | "Public: Категории" 861 | ] 862 | } 863 | }, 864 | "/categories/{catId}": { 865 | "get": { 866 | "description": "В случае, если категории с заданным id не найдено, возвращает статус код 404", 867 | "operationId": "getCategory", 868 | "parameters": [ 869 | { 870 | "description": "id категории", 871 | "in": "path", 872 | "name": "catId", 873 | "required": true, 874 | "schema": { 875 | "type": "integer", 876 | "format": "int64" 877 | } 878 | } 879 | ], 880 | "responses": { 881 | "200": { 882 | "content": { 883 | "application/json": { 884 | "schema": { 885 | "$ref": "#/components/schemas/CategoryDto" 886 | } 887 | } 888 | }, 889 | "description": "Категория найдена" 890 | }, 891 | "400": { 892 | "content": { 893 | "application/json": { 894 | "example": { 895 | "status": "BAD_REQUEST", 896 | "reason": "Incorrectly made request.", 897 | "message": "Failed to convert value of type java.lang.String to required type long; nested exception is java.lang.NumberFormatException: For input string: ad", 898 | "timestamp": "2022-09-07 09:10:50" 899 | }, 900 | "schema": { 901 | "$ref": "#/components/schemas/ApiError" 902 | } 903 | } 904 | }, 905 | "description": "Запрос составлен некорректно" 906 | }, 907 | "404": { 908 | "content": { 909 | "application/json": { 910 | "example": { 911 | "status": "NOT_FOUND", 912 | "reason": "The required object was not found.", 913 | "message": "Category with id=19 was not found", 914 | "timestamp": "2022-09-07 09:10:50" 915 | }, 916 | "schema": { 917 | "$ref": "#/components/schemas/ApiError" 918 | } 919 | } 920 | }, 921 | "description": "Категория не найдена или недоступна" 922 | } 923 | }, 924 | "summary": "Получение информации о категории по её идентификатору", 925 | "tags": [ 926 | "Public: Категории" 927 | ] 928 | } 929 | }, 930 | "/compilations": { 931 | "get": { 932 | "description": "В случае, если по заданным фильтрам не найдено ни одной подборки, возвращает пустой список", 933 | "operationId": "getCompilations", 934 | "parameters": [ 935 | { 936 | "description": "искать только закрепленные/не закрепленные подборки", 937 | "in": "query", 938 | "name": "pinned", 939 | "required": false, 940 | "schema": { 941 | "type": "boolean" 942 | } 943 | }, 944 | { 945 | "description": "количество элементов, которые нужно пропустить для формирования текущего набора", 946 | "in": "query", 947 | "name": "from", 948 | "required": false, 949 | "schema": { 950 | "minimum": 0, 951 | "type": "integer", 952 | "format": "int32", 953 | "default": 0 954 | } 955 | }, 956 | { 957 | "description": "количество элементов в наборе", 958 | "in": "query", 959 | "name": "size", 960 | "required": false, 961 | "schema": { 962 | "type": "integer", 963 | "format": "int32", 964 | "default": 10 965 | } 966 | } 967 | ], 968 | "responses": { 969 | "200": { 970 | "content": { 971 | "application/json": { 972 | "schema": { 973 | "type": "array", 974 | "items": { 975 | "$ref": "#/components/schemas/CompilationDto" 976 | } 977 | } 978 | } 979 | }, 980 | "description": "Найдены подборки событий" 981 | }, 982 | "400": { 983 | "content": { 984 | "application/json": { 985 | "example": { 986 | "status": "BAD_REQUEST", 987 | "reason": "Incorrectly made request.", 988 | "message": "Failed to convert value of type java.lang.String to required type int; nested exception is java.lang.NumberFormatException: For input string: ad", 989 | "timestamp": "2022-09-07 09:10:50" 990 | }, 991 | "schema": { 992 | "$ref": "#/components/schemas/ApiError" 993 | } 994 | } 995 | }, 996 | "description": "Запрос составлен некорректно" 997 | } 998 | }, 999 | "summary": "Получение подборок событий", 1000 | "tags": [ 1001 | "Public: Подборки событий" 1002 | ] 1003 | } 1004 | }, 1005 | "/compilations/{compId}": { 1006 | "get": { 1007 | "description": "В случае, если подборки с заданным id не найдено, возвращает статус код 404", 1008 | "operationId": "getCompilation", 1009 | "parameters": [ 1010 | { 1011 | "description": "id подборки", 1012 | "in": "path", 1013 | "name": "compId", 1014 | "required": true, 1015 | "schema": { 1016 | "type": "integer", 1017 | "format": "int64" 1018 | } 1019 | } 1020 | ], 1021 | "responses": { 1022 | "200": { 1023 | "content": { 1024 | "application/json": { 1025 | "schema": { 1026 | "$ref": "#/components/schemas/CompilationDto" 1027 | } 1028 | } 1029 | }, 1030 | "description": "Подборка событий найдена" 1031 | }, 1032 | "400": { 1033 | "content": { 1034 | "application/json": { 1035 | "example": { 1036 | "status": "BAD_REQUEST", 1037 | "reason": "Incorrectly made request.", 1038 | "message": "Failed to convert value of type java.lang.String to required type long; nested exception is java.lang.NumberFormatException: For input string: ad", 1039 | "timestamp": "2022-09-07 09:10:50" 1040 | }, 1041 | "schema": { 1042 | "$ref": "#/components/schemas/ApiError" 1043 | } 1044 | } 1045 | }, 1046 | "description": "Запрос составлен некорректно" 1047 | }, 1048 | "404": { 1049 | "content": { 1050 | "application/json": { 1051 | "example": { 1052 | "status": "NOT_FOUND", 1053 | "reason": "The required object was not found.", 1054 | "message": "Compilation with id=84 was not found", 1055 | "timestamp": "2022-09-07 09:10:50" 1056 | }, 1057 | "schema": { 1058 | "$ref": "#/components/schemas/ApiError" 1059 | } 1060 | } 1061 | }, 1062 | "description": "Подборка не найдена или недоступна" 1063 | } 1064 | }, 1065 | "summary": "Получение подборки событий по его id", 1066 | "tags": [ 1067 | "Public: Подборки событий" 1068 | ] 1069 | } 1070 | }, 1071 | "/events": { 1072 | "get": { 1073 | "description": "Обратите внимание: \n- это публичный эндпоинт, соответственно в выдаче должны быть только опубликованные события\n- текстовый поиск (по аннотации и подробному описанию) должен быть без учета регистра букв\n- если в запросе не указан диапазон дат [rangeStart-rangeEnd], то нужно выгружать события, которые произойдут позже текущей даты и времени\n- информация о каждом событии должна включать в себя количество просмотров и количество уже одобренных заявок на участие\n- информацию о том, что по этому эндпоинту был осуществлен и обработан запрос, нужно сохранить в сервисе статистики\n\nВ случае, если по заданным фильтрам не найдено ни одного события, возвращает пустой список", 1074 | "operationId": "getEvents_1", 1075 | "parameters": [ 1076 | { 1077 | "description": "текст для поиска в содержимом аннотации и подробном описании события", 1078 | "in": "query", 1079 | "name": "text", 1080 | "required": false, 1081 | "schema": { 1082 | "maxLength": 7000, 1083 | "minLength": 1, 1084 | "type": "string" 1085 | } 1086 | }, 1087 | { 1088 | "description": "список идентификаторов категорий в которых будет вестись поиск", 1089 | "in": "query", 1090 | "name": "categories", 1091 | "required": false, 1092 | "schema": { 1093 | "type": "array", 1094 | "items": { 1095 | "type": "integer", 1096 | "format": "int64" 1097 | } 1098 | } 1099 | }, 1100 | { 1101 | "description": "поиск только платных/бесплатных событий", 1102 | "in": "query", 1103 | "name": "paid", 1104 | "required": false, 1105 | "schema": { 1106 | "type": "boolean" 1107 | } 1108 | }, 1109 | { 1110 | "description": "дата и время не раньше которых должно произойти событие", 1111 | "in": "query", 1112 | "name": "rangeStart", 1113 | "required": false, 1114 | "schema": { 1115 | "type": "string" 1116 | } 1117 | }, 1118 | { 1119 | "description": "дата и время не позже которых должно произойти событие", 1120 | "in": "query", 1121 | "name": "rangeEnd", 1122 | "required": false, 1123 | "schema": { 1124 | "type": "string" 1125 | } 1126 | }, 1127 | { 1128 | "description": "только события у которых не исчерпан лимит запросов на участие", 1129 | "in": "query", 1130 | "name": "onlyAvailable", 1131 | "required": false, 1132 | "schema": { 1133 | "type": "boolean", 1134 | "default": false 1135 | } 1136 | }, 1137 | { 1138 | "description": "Вариант сортировки: по дате события или по количеству просмотров", 1139 | "in": "query", 1140 | "name": "sort", 1141 | "required": false, 1142 | "schema": { 1143 | "type": "string", 1144 | "enum": [ 1145 | "EVENT_DATE", 1146 | "VIEWS" 1147 | ] 1148 | } 1149 | }, 1150 | { 1151 | "description": "количество событий, которые нужно пропустить для формирования текущего набора", 1152 | "in": "query", 1153 | "name": "from", 1154 | "required": false, 1155 | "schema": { 1156 | "minimum": 0, 1157 | "type": "integer", 1158 | "format": "int32", 1159 | "default": 0 1160 | } 1161 | }, 1162 | { 1163 | "description": "количество событий в наборе", 1164 | "in": "query", 1165 | "name": "size", 1166 | "required": false, 1167 | "schema": { 1168 | "type": "integer", 1169 | "format": "int32", 1170 | "default": 10 1171 | } 1172 | } 1173 | ], 1174 | "responses": { 1175 | "200": { 1176 | "content": { 1177 | "application/json": { 1178 | "schema": { 1179 | "type": "array", 1180 | "items": { 1181 | "$ref": "#/components/schemas/EventShortDto" 1182 | } 1183 | } 1184 | } 1185 | }, 1186 | "description": "События найдены" 1187 | }, 1188 | "400": { 1189 | "content": { 1190 | "application/json": { 1191 | "example": { 1192 | "status": "BAD_REQUEST", 1193 | "reason": "Incorrectly made request.", 1194 | "message": "Event must be published", 1195 | "timestamp": "2022-09-07 09:10:50" 1196 | }, 1197 | "schema": { 1198 | "$ref": "#/components/schemas/ApiError" 1199 | } 1200 | } 1201 | }, 1202 | "description": "Запрос составлен некорректно" 1203 | } 1204 | }, 1205 | "summary": "Получение событий с возможностью фильтрации", 1206 | "tags": [ 1207 | "Public: События" 1208 | ] 1209 | } 1210 | }, 1211 | "/events/{id}": { 1212 | "get": { 1213 | "description": "Обратите внимание:\n- событие должно быть опубликовано\n- информация о событии должна включать в себя количество просмотров и количество подтвержденных запросов\n- информацию о том, что по этому эндпоинту был осуществлен и обработан запрос, нужно сохранить в сервисе статистики\n\nВ случае, если события с заданным id не найдено, возвращает статус код 404", 1214 | "operationId": "getEvent_1", 1215 | "parameters": [ 1216 | { 1217 | "description": "id события", 1218 | "in": "path", 1219 | "name": "id", 1220 | "required": true, 1221 | "schema": { 1222 | "type": "integer", 1223 | "format": "int64" 1224 | } 1225 | } 1226 | ], 1227 | "responses": { 1228 | "200": { 1229 | "content": { 1230 | "application/json": { 1231 | "schema": { 1232 | "$ref": "#/components/schemas/EventFullDto" 1233 | } 1234 | } 1235 | }, 1236 | "description": "Событие найдено" 1237 | }, 1238 | "400": { 1239 | "content": { 1240 | "application/json": { 1241 | "example": { 1242 | "status": "BAD_REQUEST", 1243 | "reason": "Incorrectly made request.", 1244 | "message": "Failed to convert value of type java.lang.String to required type int; nested exception is java.lang.NumberFormatException: For input string: ad", 1245 | "timestamp": "2022-09-07 09:10:50" 1246 | }, 1247 | "schema": { 1248 | "$ref": "#/components/schemas/ApiError" 1249 | } 1250 | } 1251 | }, 1252 | "description": "Запрос составлен некорректно" 1253 | }, 1254 | "404": { 1255 | "content": { 1256 | "application/json": { 1257 | "example": { 1258 | "status": "NOT_FOUND", 1259 | "reason": "The required object was not found.", 1260 | "message": "Event with id=13 was not found", 1261 | "timestamp": "2022-09-07 09:10:50" 1262 | }, 1263 | "schema": { 1264 | "$ref": "#/components/schemas/ApiError" 1265 | } 1266 | } 1267 | }, 1268 | "description": "Событие не найдено или недоступно" 1269 | } 1270 | }, 1271 | "summary": "Получение подробной информации об опубликованном событии по его идентификатору", 1272 | "tags": [ 1273 | "Public: События" 1274 | ] 1275 | } 1276 | }, 1277 | "/users/{userId}/events": { 1278 | "get": { 1279 | "description": "В случае, если по заданным фильтрам не найдено ни одного события, возвращает пустой список", 1280 | "operationId": "getEvents", 1281 | "parameters": [ 1282 | { 1283 | "description": "id текущего пользователя", 1284 | "in": "path", 1285 | "name": "userId", 1286 | "required": true, 1287 | "schema": { 1288 | "type": "integer", 1289 | "format": "int64" 1290 | } 1291 | }, 1292 | { 1293 | "description": "количество элементов, которые нужно пропустить для формирования текущего набора", 1294 | "in": "query", 1295 | "name": "from", 1296 | "required": false, 1297 | "schema": { 1298 | "minimum": 0, 1299 | "type": "integer", 1300 | "format": "int32", 1301 | "default": 0 1302 | } 1303 | }, 1304 | { 1305 | "description": "количество элементов в наборе", 1306 | "in": "query", 1307 | "name": "size", 1308 | "required": false, 1309 | "schema": { 1310 | "type": "integer", 1311 | "format": "int32", 1312 | "default": 10 1313 | } 1314 | } 1315 | ], 1316 | "responses": { 1317 | "200": { 1318 | "content": { 1319 | "application/json": { 1320 | "schema": { 1321 | "type": "array", 1322 | "items": { 1323 | "$ref": "#/components/schemas/EventShortDto" 1324 | } 1325 | } 1326 | } 1327 | }, 1328 | "description": "События найдены" 1329 | }, 1330 | "400": { 1331 | "content": { 1332 | "application/json": { 1333 | "example": { 1334 | "status": "BAD_REQUEST", 1335 | "reason": "Incorrectly made request.", 1336 | "message": "Failed to convert value of type java.lang.String to required type int; nested exception is java.lang.NumberFormatException: For input string: ad", 1337 | "timestamp": "2022-09-07 09:10:50" 1338 | }, 1339 | "schema": { 1340 | "$ref": "#/components/schemas/ApiError" 1341 | } 1342 | } 1343 | }, 1344 | "description": "Запрос составлен некорректно" 1345 | } 1346 | }, 1347 | "summary": "Получение событий, добавленных текущим пользователем", 1348 | "tags": [ 1349 | "Private: События" 1350 | ] 1351 | }, 1352 | "post": { 1353 | "description": "Обратите внимание: дата и время на которые намечено событие не может быть раньше, чем через два часа от текущего момента", 1354 | "operationId": "addEvent", 1355 | "parameters": [ 1356 | { 1357 | "description": "id текущего пользователя", 1358 | "in": "path", 1359 | "name": "userId", 1360 | "required": true, 1361 | "schema": { 1362 | "type": "integer", 1363 | "format": "int64" 1364 | } 1365 | } 1366 | ], 1367 | "requestBody": { 1368 | "content": { 1369 | "application/json": { 1370 | "schema": { 1371 | "$ref": "#/components/schemas/NewEventDto" 1372 | } 1373 | } 1374 | }, 1375 | "description": "данные добавляемого события", 1376 | "required": true 1377 | }, 1378 | "responses": { 1379 | "201": { 1380 | "content": { 1381 | "application/json": { 1382 | "schema": { 1383 | "$ref": "#/components/schemas/EventFullDto" 1384 | } 1385 | } 1386 | }, 1387 | "description": "Событие добавлено" 1388 | }, 1389 | "400": { 1390 | "content": { 1391 | "application/json": { 1392 | "example": { 1393 | "status": "BAD_REQUEST", 1394 | "reason": "Incorrectly made request.", 1395 | "message": "Field: category. Error: must not be blank. Value: null", 1396 | "timestamp": "2022-09-07 09:10:50" 1397 | }, 1398 | "schema": { 1399 | "$ref": "#/components/schemas/ApiError" 1400 | } 1401 | } 1402 | }, 1403 | "description": "Запрос составлен некорректно" 1404 | }, 1405 | "409": { 1406 | "content": { 1407 | "application/json": { 1408 | "example": { 1409 | "status": "FORBIDDEN", 1410 | "reason": "For the requested operation the conditions are not met.", 1411 | "message": "Field: eventDate. Error: должно содержать дату, которая еще не наступила. Value: 2020-12-31T15:10:05", 1412 | "timestamp": "2022-09-07 09:10:50" 1413 | }, 1414 | "schema": { 1415 | "$ref": "#/components/schemas/ApiError" 1416 | } 1417 | } 1418 | }, 1419 | "description": "Событие не удовлетворяет правилам создания" 1420 | } 1421 | }, 1422 | "summary": "Добавление нового события", 1423 | "tags": [ 1424 | "Private: События" 1425 | ] 1426 | } 1427 | }, 1428 | "/users/{userId}/events/{eventId}": { 1429 | "get": { 1430 | "description": "В случае, если события с заданным id не найдено, возвращает статус код 404", 1431 | "operationId": "getEvent", 1432 | "parameters": [ 1433 | { 1434 | "description": "id текущего пользователя", 1435 | "in": "path", 1436 | "name": "userId", 1437 | "required": true, 1438 | "schema": { 1439 | "type": "integer", 1440 | "format": "int64" 1441 | } 1442 | }, 1443 | { 1444 | "description": "id события", 1445 | "in": "path", 1446 | "name": "eventId", 1447 | "required": true, 1448 | "schema": { 1449 | "type": "integer", 1450 | "format": "int64" 1451 | } 1452 | } 1453 | ], 1454 | "responses": { 1455 | "200": { 1456 | "content": { 1457 | "application/json": { 1458 | "schema": { 1459 | "$ref": "#/components/schemas/EventFullDto" 1460 | } 1461 | } 1462 | }, 1463 | "description": "Событие найдено" 1464 | }, 1465 | "400": { 1466 | "content": { 1467 | "application/json": { 1468 | "example": { 1469 | "status": "BAD_REQUEST", 1470 | "reason": "Incorrectly made request.", 1471 | "message": "Failed to convert value of type java.lang.String to required type long; nested exception is java.lang.NumberFormatException: For input string: ad", 1472 | "timestamp": "2022-09-07 09:10:50" 1473 | }, 1474 | "schema": { 1475 | "$ref": "#/components/schemas/ApiError" 1476 | } 1477 | } 1478 | }, 1479 | "description": "Запрос составлен некорректно" 1480 | }, 1481 | "404": { 1482 | "content": { 1483 | "application/json": { 1484 | "example": { 1485 | "status": "NOT_FOUND", 1486 | "reason": "The required object was not found.", 1487 | "message": "Event with id=13 was not found", 1488 | "timestamp": "2022-09-07 09:10:50" 1489 | }, 1490 | "schema": { 1491 | "$ref": "#/components/schemas/ApiError" 1492 | } 1493 | } 1494 | }, 1495 | "description": "Событие не найдено или недоступно" 1496 | } 1497 | }, 1498 | "summary": "Получение полной информации о событии добавленном текущим пользователем", 1499 | "tags": [ 1500 | "Private: События" 1501 | ] 1502 | }, 1503 | "patch": { 1504 | "description": "Обратите внимание:\n- изменить можно только отмененные события или события в состоянии ожидания модерации (Ожидается код ошибки 409)\n- дата и время на которые намечено событие не может быть раньше, чем через два часа от текущего момента (Ожидается код ошибки 409)\n", 1505 | "operationId": "updateEvent", 1506 | "parameters": [ 1507 | { 1508 | "description": "id текущего пользователя", 1509 | "in": "path", 1510 | "name": "userId", 1511 | "required": true, 1512 | "schema": { 1513 | "type": "integer", 1514 | "format": "int64" 1515 | } 1516 | }, 1517 | { 1518 | "description": "id редактируемого события", 1519 | "in": "path", 1520 | "name": "eventId", 1521 | "required": true, 1522 | "schema": { 1523 | "type": "integer", 1524 | "format": "int64" 1525 | } 1526 | } 1527 | ], 1528 | "requestBody": { 1529 | "content": { 1530 | "application/json": { 1531 | "schema": { 1532 | "$ref": "#/components/schemas/UpdateEventUserRequest" 1533 | } 1534 | } 1535 | }, 1536 | "description": "Новые данные события", 1537 | "required": true 1538 | }, 1539 | "responses": { 1540 | "200": { 1541 | "content": { 1542 | "application/json": { 1543 | "schema": { 1544 | "$ref": "#/components/schemas/EventFullDto" 1545 | } 1546 | } 1547 | }, 1548 | "description": "Событие обновлено" 1549 | }, 1550 | "400": { 1551 | "content": { 1552 | "application/json": { 1553 | "example": { 1554 | "status": "BAD_REQUEST", 1555 | "reason": "Incorrectly made request.", 1556 | "message": "Event must not be published", 1557 | "timestamp": "2022-09-07 09:10:50" 1558 | }, 1559 | "schema": { 1560 | "$ref": "#/components/schemas/ApiError" 1561 | } 1562 | } 1563 | }, 1564 | "description": "Запрос составлен некорректно" 1565 | }, 1566 | "404": { 1567 | "content": { 1568 | "application/json": { 1569 | "example": { 1570 | "status": "NOT_FOUND", 1571 | "reason": "The required object was not found.", 1572 | "message": "Event with id=283 was not found", 1573 | "timestamp": "2022-09-07 09:10:50" 1574 | }, 1575 | "schema": { 1576 | "$ref": "#/components/schemas/ApiError" 1577 | } 1578 | } 1579 | }, 1580 | "description": "Событие не найдено или недоступно" 1581 | }, 1582 | "409": { 1583 | "content": { 1584 | "application/json": { 1585 | "example": { 1586 | "status": "FORBIDDEN", 1587 | "reason": "For the requested operation the conditions are not met.", 1588 | "message": "Only pending or canceled events can be changed", 1589 | "timestamp": "2022-09-07 09:10:50" 1590 | }, 1591 | "schema": { 1592 | "$ref": "#/components/schemas/ApiError" 1593 | } 1594 | } 1595 | }, 1596 | "description": "Событие не удовлетворяет правилам редактирования" 1597 | } 1598 | }, 1599 | "summary": "Изменение события добавленного текущим пользователем", 1600 | "tags": [ 1601 | "Private: События" 1602 | ] 1603 | } 1604 | }, 1605 | "/users/{userId}/events/{eventId}/requests": { 1606 | "get": { 1607 | "description": "В случае, если по заданным фильтрам не найдено ни одной заявки, возвращает пустой список", 1608 | "operationId": "getEventParticipants", 1609 | "parameters": [ 1610 | { 1611 | "description": "id текущего пользователя", 1612 | "in": "path", 1613 | "name": "userId", 1614 | "required": true, 1615 | "schema": { 1616 | "type": "integer", 1617 | "format": "int64" 1618 | } 1619 | }, 1620 | { 1621 | "description": "id события", 1622 | "in": "path", 1623 | "name": "eventId", 1624 | "required": true, 1625 | "schema": { 1626 | "type": "integer", 1627 | "format": "int64" 1628 | } 1629 | } 1630 | ], 1631 | "responses": { 1632 | "200": { 1633 | "content": { 1634 | "application/json": { 1635 | "schema": { 1636 | "type": "array", 1637 | "items": { 1638 | "$ref": "#/components/schemas/ParticipationRequestDto" 1639 | } 1640 | } 1641 | } 1642 | }, 1643 | "description": "Найдены запросы на участие" 1644 | }, 1645 | "400": { 1646 | "content": { 1647 | "application/json": { 1648 | "example": { 1649 | "status": "BAD_REQUEST", 1650 | "reason": "Incorrectly made request.", 1651 | "message": "Failed to convert value of type java.lang.String to required type int; nested exception is java.lang.NumberFormatException: For input string: ad", 1652 | "timestamp": "2022-09-07 09:10:50" 1653 | }, 1654 | "schema": { 1655 | "$ref": "#/components/schemas/ApiError" 1656 | } 1657 | } 1658 | }, 1659 | "description": "Запрос составлен некорректно" 1660 | } 1661 | }, 1662 | "summary": "Получение информации о запросах на участие в событии текущего пользователя", 1663 | "tags": [ 1664 | "Private: События" 1665 | ] 1666 | }, 1667 | "patch": { 1668 | "description": "Обратите внимание:\n- если для события лимит заявок равен 0 или отключена пре-модерация заявок, то подтверждение заявок не требуется\n- нельзя подтвердить заявку, если уже достигнут лимит по заявкам на данное событие (Ожидается код ошибки 409)\n- статус можно изменить только у заявок, находящихся в состоянии ожидания (Ожидается код ошибки 409)\n- если при подтверждении данной заявки, лимит заявок для события исчерпан, то все неподтверждённые заявки необходимо отклонить", 1669 | "operationId": "changeRequestStatus", 1670 | "parameters": [ 1671 | { 1672 | "description": "id текущего пользователя", 1673 | "in": "path", 1674 | "name": "userId", 1675 | "required": true, 1676 | "schema": { 1677 | "type": "integer", 1678 | "format": "int64" 1679 | } 1680 | }, 1681 | { 1682 | "description": "id события текущего пользователя", 1683 | "in": "path", 1684 | "name": "eventId", 1685 | "required": true, 1686 | "schema": { 1687 | "type": "integer", 1688 | "format": "int64" 1689 | } 1690 | } 1691 | ], 1692 | "requestBody": { 1693 | "content": { 1694 | "application/json": { 1695 | "schema": { 1696 | "$ref": "#/components/schemas/EventRequestStatusUpdateRequest" 1697 | } 1698 | } 1699 | }, 1700 | "description": "Новый статус для заявок на участие в событии текущего пользователя", 1701 | "required": true 1702 | }, 1703 | "responses": { 1704 | "200": { 1705 | "content": { 1706 | "application/json": { 1707 | "schema": { 1708 | "$ref": "#/components/schemas/EventRequestStatusUpdateResult" 1709 | } 1710 | } 1711 | }, 1712 | "description": "Статус заявок изменён" 1713 | }, 1714 | "400": { 1715 | "content": { 1716 | "application/json": { 1717 | "example": { 1718 | "status": "BAD_REQUEST", 1719 | "reason": "Incorrectly made request.", 1720 | "message": "Request must have status PENDING", 1721 | "timestamp": "2022-09-07 09:10:50" 1722 | }, 1723 | "schema": { 1724 | "$ref": "#/components/schemas/ApiError" 1725 | } 1726 | } 1727 | }, 1728 | "description": "Запрос составлен некорректно" 1729 | }, 1730 | "404": { 1731 | "content": { 1732 | "application/json": { 1733 | "example": { 1734 | "status": "NOT_FOUND", 1735 | "reason": "The required object was not found.", 1736 | "message": "Event with id=321 was not found", 1737 | "timestamp": "2022-09-07 09:10:50" 1738 | }, 1739 | "schema": { 1740 | "$ref": "#/components/schemas/ApiError" 1741 | } 1742 | } 1743 | }, 1744 | "description": "Событие не найдено или недоступно" 1745 | }, 1746 | "409": { 1747 | "content": { 1748 | "application/json": { 1749 | "example": { 1750 | "status": "CONFLICT", 1751 | "reason": "For the requested operation the conditions are not met.", 1752 | "message": "The participant limit has been reached", 1753 | "timestamp": "2022-09-07 09:10:50" 1754 | }, 1755 | "schema": { 1756 | "$ref": "#/components/schemas/ApiError" 1757 | } 1758 | } 1759 | }, 1760 | "description": "Достигнут лимит одобренных заявок" 1761 | } 1762 | }, 1763 | "summary": "Изменение статуса (подтверждена, отменена) заявок на участие в событии текущего пользователя", 1764 | "tags": [ 1765 | "Private: События" 1766 | ] 1767 | } 1768 | }, 1769 | "/users/{userId}/requests": { 1770 | "get": { 1771 | "description": "В случае, если по заданным фильтрам не найдено ни одной заявки, возвращает пустой список", 1772 | "operationId": "getUserRequests", 1773 | "parameters": [ 1774 | { 1775 | "description": "id текущего пользователя", 1776 | "in": "path", 1777 | "name": "userId", 1778 | "required": true, 1779 | "schema": { 1780 | "type": "integer", 1781 | "format": "int64" 1782 | } 1783 | } 1784 | ], 1785 | "responses": { 1786 | "200": { 1787 | "content": { 1788 | "application/json": { 1789 | "schema": { 1790 | "type": "array", 1791 | "items": { 1792 | "$ref": "#/components/schemas/ParticipationRequestDto" 1793 | } 1794 | } 1795 | } 1796 | }, 1797 | "description": "Найдены запросы на участие" 1798 | }, 1799 | "400": { 1800 | "content": { 1801 | "application/json": { 1802 | "example": { 1803 | "status": "BAD_REQUEST", 1804 | "reason": "Incorrectly made request.", 1805 | "message": "Failed to convert value of type java.lang.String to required type long; nested exception is java.lang.NumberFormatException: For input string: ad", 1806 | "timestamp": "2022-09-07 09:10:50" 1807 | }, 1808 | "schema": { 1809 | "$ref": "#/components/schemas/ApiError" 1810 | } 1811 | } 1812 | }, 1813 | "description": "Запрос составлен некорректно" 1814 | }, 1815 | "404": { 1816 | "content": { 1817 | "application/json": { 1818 | "example": { 1819 | "status": "NOT_FOUND", 1820 | "reason": "The required object was not found.", 1821 | "message": "User with id=11 was not found", 1822 | "timestamp": "2022-09-07 09:10:50" 1823 | }, 1824 | "schema": { 1825 | "$ref": "#/components/schemas/ApiError" 1826 | } 1827 | } 1828 | }, 1829 | "description": "Пользователь не найден" 1830 | } 1831 | }, 1832 | "summary": "Получение информации о заявках текущего пользователя на участие в чужих событиях", 1833 | "tags": [ 1834 | "Private: Запросы на участие" 1835 | ] 1836 | }, 1837 | "post": { 1838 | "description": "Обратите внимание:\n- нельзя добавить повторный запрос (Ожидается код ошибки 409)\n- инициатор события не может добавить запрос на участие в своём событии (Ожидается код ошибки 409)\n- нельзя участвовать в неопубликованном событии (Ожидается код ошибки 409)\n- если у события достигнут лимит запросов на участие - необходимо вернуть ошибку (Ожидается код ошибки 409)\n- если для события отключена пре-модерация запросов на участие, то запрос должен автоматически перейти в состояние подтвержденного", 1839 | "operationId": "addParticipationRequest", 1840 | "parameters": [ 1841 | { 1842 | "description": "id текущего пользователя", 1843 | "in": "path", 1844 | "name": "userId", 1845 | "required": true, 1846 | "schema": { 1847 | "type": "integer", 1848 | "format": "int64" 1849 | } 1850 | }, 1851 | { 1852 | "description": "id события", 1853 | "in": "query", 1854 | "name": "eventId", 1855 | "required": true, 1856 | "schema": { 1857 | "type": "integer", 1858 | "format": "int64" 1859 | } 1860 | } 1861 | ], 1862 | "responses": { 1863 | "201": { 1864 | "content": { 1865 | "application/json": { 1866 | "schema": { 1867 | "$ref": "#/components/schemas/ParticipationRequestDto" 1868 | } 1869 | } 1870 | }, 1871 | "description": "Заявка создана" 1872 | }, 1873 | "400": { 1874 | "content": { 1875 | "application/json": { 1876 | "example": { 1877 | "status": "BAD_REQUEST", 1878 | "reason": "Incorrectly made request.", 1879 | "message": "Failed to convert value of type java.lang.String to required type long; nested exception is java.lang.NumberFormatException: For input string: ad", 1880 | "timestamp": "2022-09-07 09:10:50" 1881 | }, 1882 | "schema": { 1883 | "$ref": "#/components/schemas/ApiError" 1884 | } 1885 | } 1886 | }, 1887 | "description": "Запрос составлен некорректно" 1888 | }, 1889 | "404": { 1890 | "content": { 1891 | "application/json": { 1892 | "example": { 1893 | "status": "NOT_FOUND", 1894 | "reason": "The required object was not found.", 1895 | "message": "Event with id=13 was not found", 1896 | "timestamp": "2022-09-07 09:10:50" 1897 | }, 1898 | "schema": { 1899 | "$ref": "#/components/schemas/ApiError" 1900 | } 1901 | } 1902 | }, 1903 | "description": "Событие не найдено или недоступно" 1904 | }, 1905 | "409": { 1906 | "content": { 1907 | "application/json": { 1908 | "example": { 1909 | "status": "CONFLICT", 1910 | "reason": "Integrity constraint has been violated.", 1911 | "message": "could not execute statement; SQL [n/a]; constraint [uq_request]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement", 1912 | "timestamp": "2022-09-07 09:10:50" 1913 | }, 1914 | "schema": { 1915 | "$ref": "#/components/schemas/ApiError" 1916 | } 1917 | } 1918 | }, 1919 | "description": "Нарушение целостности данных" 1920 | } 1921 | }, 1922 | "summary": "Добавление запроса от текущего пользователя на участие в событии", 1923 | "tags": [ 1924 | "Private: Запросы на участие" 1925 | ] 1926 | } 1927 | }, 1928 | "/users/{userId}/requests/{requestId}/cancel": { 1929 | "patch": { 1930 | "operationId": "cancelRequest", 1931 | "parameters": [ 1932 | { 1933 | "description": "id текущего пользователя", 1934 | "in": "path", 1935 | "name": "userId", 1936 | "required": true, 1937 | "schema": { 1938 | "type": "integer", 1939 | "format": "int64" 1940 | } 1941 | }, 1942 | { 1943 | "description": "id запроса на участие", 1944 | "in": "path", 1945 | "name": "requestId", 1946 | "required": true, 1947 | "schema": { 1948 | "type": "integer", 1949 | "format": "int64" 1950 | } 1951 | } 1952 | ], 1953 | "responses": { 1954 | "200": { 1955 | "content": { 1956 | "application/json": { 1957 | "schema": { 1958 | "$ref": "#/components/schemas/ParticipationRequestDto" 1959 | } 1960 | } 1961 | }, 1962 | "description": "Заявка отменена" 1963 | }, 1964 | "404": { 1965 | "content": { 1966 | "application/json": { 1967 | "example": { 1968 | "status": "NOT_FOUND", 1969 | "reason": "The required object was not found.", 1970 | "message": "Request with id=2727 was not found", 1971 | "timestamp": "2022-09-07 09:10:50" 1972 | }, 1973 | "schema": { 1974 | "$ref": "#/components/schemas/ApiError" 1975 | } 1976 | } 1977 | }, 1978 | "description": "Запрос не найден или недоступен" 1979 | } 1980 | }, 1981 | "summary": "Отмена своего запроса на участие в событии", 1982 | "tags": [ 1983 | "Private: Запросы на участие" 1984 | ] 1985 | } 1986 | } 1987 | }, 1988 | "components": { 1989 | "schemas": { 1990 | "ApiError": { 1991 | "type": "object", 1992 | "properties": { 1993 | "errors": { 1994 | "type": "array", 1995 | "description": "Список стектрейсов или описания ошибок", 1996 | "example": [], 1997 | "items": { 1998 | "type": "string", 1999 | "description": "Список стектрейсов или описания ошибок", 2000 | "example": "[]" 2001 | } 2002 | }, 2003 | "message": { 2004 | "type": "string", 2005 | "description": "Сообщение об ошибке", 2006 | "example": "Only pending or canceled events can be changed" 2007 | }, 2008 | "reason": { 2009 | "type": "string", 2010 | "description": "Общее описание причины ошибки", 2011 | "example": "For the requested operation the conditions are not met." 2012 | }, 2013 | "status": { 2014 | "type": "string", 2015 | "description": "Код статуса HTTP-ответа", 2016 | "example": "FORBIDDEN", 2017 | "enum": [ 2018 | "100 CONTINUE", 2019 | "101 SWITCHING_PROTOCOLS", 2020 | "102 PROCESSING", 2021 | "103 CHECKPOINT", 2022 | "200 OK", 2023 | "201 CREATED", 2024 | "202 ACCEPTED", 2025 | "203 NON_AUTHORITATIVE_INFORMATION", 2026 | "204 NO_CONTENT", 2027 | "205 RESET_CONTENT", 2028 | "206 PARTIAL_CONTENT", 2029 | "207 MULTI_STATUS", 2030 | "208 ALREADY_REPORTED", 2031 | "226 IM_USED", 2032 | "300 MULTIPLE_CHOICES", 2033 | "301 MOVED_PERMANENTLY", 2034 | "302 FOUND", 2035 | "302 MOVED_TEMPORARILY", 2036 | "303 SEE_OTHER", 2037 | "304 NOT_MODIFIED", 2038 | "305 USE_PROXY", 2039 | "307 TEMPORARY_REDIRECT", 2040 | "308 PERMANENT_REDIRECT", 2041 | "400 BAD_REQUEST", 2042 | "401 UNAUTHORIZED", 2043 | "402 PAYMENT_REQUIRED", 2044 | "403 FORBIDDEN", 2045 | "404 NOT_FOUND", 2046 | "405 METHOD_NOT_ALLOWED", 2047 | "406 NOT_ACCEPTABLE", 2048 | "407 PROXY_AUTHENTICATION_REQUIRED", 2049 | "408 REQUEST_TIMEOUT", 2050 | "409 CONFLICT", 2051 | "410 GONE", 2052 | "411 LENGTH_REQUIRED", 2053 | "412 PRECONDITION_FAILED", 2054 | "413 PAYLOAD_TOO_LARGE", 2055 | "413 REQUEST_ENTITY_TOO_LARGE", 2056 | "414 URI_TOO_LONG", 2057 | "414 REQUEST_URI_TOO_LONG", 2058 | "415 UNSUPPORTED_MEDIA_TYPE", 2059 | "416 REQUESTED_RANGE_NOT_SATISFIABLE", 2060 | "417 EXPECTATION_FAILED", 2061 | "418 I_AM_A_TEAPOT", 2062 | "419 INSUFFICIENT_SPACE_ON_RESOURCE", 2063 | "420 METHOD_FAILURE", 2064 | "421 DESTINATION_LOCKED", 2065 | "422 UNPROCESSABLE_ENTITY", 2066 | "423 LOCKED", 2067 | "424 FAILED_DEPENDENCY", 2068 | "425 TOO_EARLY", 2069 | "426 UPGRADE_REQUIRED", 2070 | "428 PRECONDITION_REQUIRED", 2071 | "429 TOO_MANY_REQUESTS", 2072 | "431 REQUEST_HEADER_FIELDS_TOO_LARGE", 2073 | "451 UNAVAILABLE_FOR_LEGAL_REASONS", 2074 | "500 INTERNAL_SERVER_ERROR", 2075 | "501 NOT_IMPLEMENTED", 2076 | "502 BAD_GATEWAY", 2077 | "503 SERVICE_UNAVAILABLE", 2078 | "504 GATEWAY_TIMEOUT", 2079 | "505 HTTP_VERSION_NOT_SUPPORTED", 2080 | "506 VARIANT_ALSO_NEGOTIATES", 2081 | "507 INSUFFICIENT_STORAGE", 2082 | "508 LOOP_DETECTED", 2083 | "509 BANDWIDTH_LIMIT_EXCEEDED", 2084 | "510 NOT_EXTENDED", 2085 | "511 NETWORK_AUTHENTICATION_REQUIRED" 2086 | ] 2087 | }, 2088 | "timestamp": { 2089 | "type": "string", 2090 | "description": "Дата и время когда произошла ошибка (в формате \"yyyy-MM-dd HH:mm:ss\")", 2091 | "example": "2022-06-09 06:27:23" 2092 | } 2093 | }, 2094 | "description": "Сведения об ошибке" 2095 | }, 2096 | "CategoryDto": { 2097 | "required": [ 2098 | "name" 2099 | ], 2100 | "type": "object", 2101 | "properties": { 2102 | "id": { 2103 | "type": "integer", 2104 | "description": "Идентификатор категории", 2105 | "format": "int64", 2106 | "readOnly": true, 2107 | "example": 1 2108 | }, 2109 | "name": { 2110 | "maxLength": 50, 2111 | "minLength": 1, 2112 | "type": "string", 2113 | "description": "Название категории", 2114 | "example": "Концерты" 2115 | } 2116 | }, 2117 | "description": "Категория" 2118 | }, 2119 | "CompilationDto": { 2120 | "required": [ 2121 | "id", 2122 | "pinned", 2123 | "title" 2124 | ], 2125 | "type": "object", 2126 | "properties": { 2127 | "events": { 2128 | "uniqueItems": true, 2129 | "type": "array", 2130 | "description": "Список событий входящих в подборку", 2131 | "example": [ 2132 | { 2133 | "annotation": "Эксклюзивность нашего шоу гарантирует привлечение максимальной зрительской аудитории", 2134 | "category": { 2135 | "id": 1, 2136 | "name": "Концерты" 2137 | }, 2138 | "confirmedRequests": 5, 2139 | "eventDate": "2024-03-10 14:30:00", 2140 | "id": 1, 2141 | "initiator": { 2142 | "id": 3, 2143 | "name": "Фёдоров Матвей" 2144 | }, 2145 | "paid": true, 2146 | "title": "Знаменитое шоу 'Летающая кукуруза'", 2147 | "views": 999 2148 | }, 2149 | { 2150 | "annotation": "За почти три десятилетия группа 'Java Core' закрепились на сцене как группа, объединяющая поколения.", 2151 | "category": { 2152 | "id": 1, 2153 | "name": "Концерты" 2154 | }, 2155 | "confirmedRequests": 555, 2156 | "eventDate": "2025-09-13 21:00:00", 2157 | "id": 1, 2158 | "initiator": { 2159 | "id": 3, 2160 | "name": "Паша Петров" 2161 | }, 2162 | "paid": true, 2163 | "title": "Концерт рок-группы 'Java Core'", 2164 | "views": 991 2165 | } 2166 | ], 2167 | "items": { 2168 | "$ref": "#/components/schemas/EventShortDto" 2169 | } 2170 | }, 2171 | "id": { 2172 | "type": "integer", 2173 | "description": "Идентификатор", 2174 | "format": "int64", 2175 | "example": 1 2176 | }, 2177 | "pinned": { 2178 | "type": "boolean", 2179 | "description": "Закреплена ли подборка на главной странице сайта", 2180 | "example": true 2181 | }, 2182 | "title": { 2183 | "type": "string", 2184 | "description": "Заголовок подборки", 2185 | "example": "Летние концерты" 2186 | } 2187 | }, 2188 | "description": "Подборка событий" 2189 | }, 2190 | "EventFullDto": { 2191 | "required": [ 2192 | "annotation", 2193 | "category", 2194 | "eventDate", 2195 | "initiator", 2196 | "location", 2197 | "paid", 2198 | "title" 2199 | ], 2200 | "type": "object", 2201 | "properties": { 2202 | "annotation": { 2203 | "type": "string", 2204 | "description": "Краткое описание", 2205 | "example": "Эксклюзивность нашего шоу гарантирует привлечение максимальной зрительской аудитории" 2206 | }, 2207 | "category": { 2208 | "$ref": "#/components/schemas/CategoryDto" 2209 | }, 2210 | "confirmedRequests": { 2211 | "type": "integer", 2212 | "description": "Количество одобренных заявок на участие в данном событии", 2213 | "format": "int64", 2214 | "example": 5 2215 | }, 2216 | "createdOn": { 2217 | "type": "string", 2218 | "description": "Дата и время создания события (в формате \"yyyy-MM-dd HH:mm:ss\")", 2219 | "example": "2022-09-06 11:00:23" 2220 | }, 2221 | "description": { 2222 | "type": "string", 2223 | "description": "Полное описание события", 2224 | "example": "Что получится, если соединить кукурузу и полёт? Создатели \"Шоу летающей кукурузы\" испытали эту идею на практике и воплотили в жизнь инновационный проект, предлагающий свежий взгляд на развлечения..." 2225 | }, 2226 | "eventDate": { 2227 | "type": "string", 2228 | "description": "Дата и время на которые намечено событие (в формате \"yyyy-MM-dd HH:mm:ss\")", 2229 | "example": "2024-12-31 15:10:05" 2230 | }, 2231 | "id": { 2232 | "type": "integer", 2233 | "description": "Идентификатор", 2234 | "format": "int64", 2235 | "example": 1 2236 | }, 2237 | "initiator": { 2238 | "$ref": "#/components/schemas/UserShortDto" 2239 | }, 2240 | "location": { 2241 | "$ref": "#/components/schemas/Location" 2242 | }, 2243 | "paid": { 2244 | "type": "boolean", 2245 | "description": "Нужно ли оплачивать участие", 2246 | "example": true 2247 | }, 2248 | "participantLimit": { 2249 | "type": "integer", 2250 | "description": "Ограничение на количество участников. Значение 0 - означает отсутствие ограничения", 2251 | "format": "int32", 2252 | "example": 10, 2253 | "default": 0 2254 | }, 2255 | "publishedOn": { 2256 | "type": "string", 2257 | "description": "Дата и время публикации события (в формате \"yyyy-MM-dd HH:mm:ss\")", 2258 | "example": "2022-09-06 15:10:05" 2259 | }, 2260 | "requestModeration": { 2261 | "type": "boolean", 2262 | "description": "Нужна ли пре-модерация заявок на участие", 2263 | "example": true, 2264 | "default": true 2265 | }, 2266 | "state": { 2267 | "type": "string", 2268 | "description": "Список состояний жизненного цикла события", 2269 | "example": "PUBLISHED", 2270 | "enum": [ 2271 | "PENDING", 2272 | "PUBLISHED", 2273 | "CANCELED" 2274 | ] 2275 | }, 2276 | "title": { 2277 | "type": "string", 2278 | "description": "Заголовок", 2279 | "example": "Знаменитое шоу 'Летающая кукуруза'" 2280 | }, 2281 | "views": { 2282 | "type": "integer", 2283 | "description": "Количество просмотрев события", 2284 | "format": "int64", 2285 | "example": 999 2286 | } 2287 | } 2288 | }, 2289 | "EventRequestStatusUpdateRequest": { 2290 | "type": "object", 2291 | "properties": { 2292 | "requestIds": { 2293 | "type": "array", 2294 | "description": "Идентификаторы запросов на участие в событии текущего пользователя", 2295 | "example": [ 2296 | 1, 2297 | 2, 2298 | 3 2299 | ], 2300 | "items": { 2301 | "type": "integer", 2302 | "description": "Идентификаторы запросов на участие в событии текущего пользователя", 2303 | "format": "int64" 2304 | } 2305 | }, 2306 | "status": { 2307 | "type": "string", 2308 | "description": "Новый статус запроса на участие в событии текущего пользователя", 2309 | "example": "CONFIRMED", 2310 | "enum": [ 2311 | "CONFIRMED", 2312 | "REJECTED" 2313 | ] 2314 | } 2315 | }, 2316 | "description": "Изменение статуса запроса на участие в событии текущего пользователя" 2317 | }, 2318 | "EventRequestStatusUpdateResult": { 2319 | "type": "object", 2320 | "properties": { 2321 | "confirmedRequests": { 2322 | "type": "array", 2323 | "items": { 2324 | "$ref": "#/components/schemas/ParticipationRequestDto" 2325 | } 2326 | }, 2327 | "rejectedRequests": { 2328 | "type": "array", 2329 | "items": { 2330 | "$ref": "#/components/schemas/ParticipationRequestDto" 2331 | } 2332 | } 2333 | }, 2334 | "description": "Результат подтверждения/отклонения заявок на участие в событии" 2335 | }, 2336 | "EventShortDto": { 2337 | "required": [ 2338 | "annotation", 2339 | "category", 2340 | "eventDate", 2341 | "initiator", 2342 | "paid", 2343 | "title" 2344 | ], 2345 | "type": "object", 2346 | "properties": { 2347 | "annotation": { 2348 | "type": "string", 2349 | "description": "Краткое описание", 2350 | "example": "Эксклюзивность нашего шоу гарантирует привлечение максимальной зрительской аудитории" 2351 | }, 2352 | "category": { 2353 | "$ref": "#/components/schemas/CategoryDto" 2354 | }, 2355 | "confirmedRequests": { 2356 | "type": "integer", 2357 | "description": "Количество одобренных заявок на участие в данном событии", 2358 | "format": "int64", 2359 | "example": 5 2360 | }, 2361 | "eventDate": { 2362 | "type": "string", 2363 | "description": "Дата и время на которые намечено событие (в формате \"yyyy-MM-dd HH:mm:ss\")", 2364 | "example": "2024-12-31 15:10:05" 2365 | }, 2366 | "id": { 2367 | "type": "integer", 2368 | "description": "Идентификатор", 2369 | "format": "int64", 2370 | "example": 1 2371 | }, 2372 | "initiator": { 2373 | "$ref": "#/components/schemas/UserShortDto" 2374 | }, 2375 | "paid": { 2376 | "type": "boolean", 2377 | "description": "Нужно ли оплачивать участие", 2378 | "example": true 2379 | }, 2380 | "title": { 2381 | "type": "string", 2382 | "description": "Заголовок", 2383 | "example": "Знаменитое шоу 'Летающая кукуруза'" 2384 | }, 2385 | "views": { 2386 | "type": "integer", 2387 | "description": "Количество просмотрев события", 2388 | "format": "int64", 2389 | "example": 999 2390 | } 2391 | }, 2392 | "description": "Краткая информация о событии", 2393 | "example": [ 2394 | { 2395 | "annotation": "Эксклюзивность нашего шоу гарантирует привлечение максимальной зрительской аудитории", 2396 | "category": { 2397 | "id": 1, 2398 | "name": "Концерты" 2399 | }, 2400 | "confirmedRequests": 5, 2401 | "eventDate": "2024-03-10 14:30:00", 2402 | "id": 1, 2403 | "initiator": { 2404 | "id": 3, 2405 | "name": "Фёдоров Матвей" 2406 | }, 2407 | "paid": true, 2408 | "title": "Знаменитое шоу 'Летающая кукуруза'", 2409 | "views": 999 2410 | }, 2411 | { 2412 | "annotation": "За почти три десятилетия группа 'Java Core' закрепились на сцене как группа, объединяющая поколения.", 2413 | "category": { 2414 | "id": 1, 2415 | "name": "Концерты" 2416 | }, 2417 | "confirmedRequests": 555, 2418 | "eventDate": "2025-09-13 21:00:00", 2419 | "id": 1, 2420 | "initiator": { 2421 | "id": 3, 2422 | "name": "Паша Петров" 2423 | }, 2424 | "paid": true, 2425 | "title": "Концерт рок-группы 'Java Core'", 2426 | "views": 991 2427 | } 2428 | ] 2429 | }, 2430 | "Location": { 2431 | "type": "object", 2432 | "properties": { 2433 | "lat": { 2434 | "type": "number", 2435 | "description": "Широта", 2436 | "format": "float", 2437 | "example": 55.754167 2438 | }, 2439 | "lon": { 2440 | "type": "number", 2441 | "description": "Долгота", 2442 | "format": "float", 2443 | "example": 37.62 2444 | } 2445 | }, 2446 | "description": "Широта и долгота места проведения события" 2447 | }, 2448 | "NewCategoryDto": { 2449 | "required": [ 2450 | "name" 2451 | ], 2452 | "type": "object", 2453 | "properties": { 2454 | "name": { 2455 | "maxLength": 50, 2456 | "minLength": 1, 2457 | "type": "string", 2458 | "description": "Название категории", 2459 | "example": "Концерты" 2460 | } 2461 | }, 2462 | "description": "Данные для добавления новой категории" 2463 | }, 2464 | "NewCompilationDto": { 2465 | "required": [ 2466 | "title" 2467 | ], 2468 | "type": "object", 2469 | "properties": { 2470 | "events": { 2471 | "uniqueItems": true, 2472 | "type": "array", 2473 | "description": "Список идентификаторов событий входящих в подборку", 2474 | "example": [ 2475 | 1, 2476 | 2, 2477 | 3 2478 | ], 2479 | "items": { 2480 | "type": "integer", 2481 | "description": "Список идентификаторов событий входящих в подборку", 2482 | "format": "int64" 2483 | } 2484 | }, 2485 | "pinned": { 2486 | "type": "boolean", 2487 | "description": "Закреплена ли подборка на главной странице сайта", 2488 | "example": false, 2489 | "default": false 2490 | }, 2491 | "title": { 2492 | "maxLength": 50, 2493 | "minLength": 1, 2494 | "type": "string", 2495 | "description": "Заголовок подборки", 2496 | "example": "Летние концерты" 2497 | } 2498 | }, 2499 | "description": "Подборка событий" 2500 | }, 2501 | "NewEventDto": { 2502 | "required": [ 2503 | "annotation", 2504 | "category", 2505 | "description", 2506 | "eventDate", 2507 | "location", 2508 | "title" 2509 | ], 2510 | "type": "object", 2511 | "properties": { 2512 | "annotation": { 2513 | "maxLength": 2000, 2514 | "minLength": 20, 2515 | "type": "string", 2516 | "description": "Краткое описание события", 2517 | "example": "Сплав на байдарках похож на полет." 2518 | }, 2519 | "category": { 2520 | "type": "integer", 2521 | "description": "id категории к которой относится событие", 2522 | "format": "int64", 2523 | "example": 2 2524 | }, 2525 | "description": { 2526 | "maxLength": 7000, 2527 | "minLength": 20, 2528 | "type": "string", 2529 | "description": "Полное описание события", 2530 | "example": "Сплав на байдарках похож на полет. На спокойной воде — это парение. На бурной, порожистой — выполнение фигур высшего пилотажа. И то, и другое дарят чувство обновления, феерические эмоции, яркие впечатления." 2531 | }, 2532 | "eventDate": { 2533 | "type": "string", 2534 | "description": "Дата и время на которые намечено событие. Дата и время указываются в формате \"yyyy-MM-dd HH:mm:ss\"", 2535 | "example": "2024-12-31 15:10:05" 2536 | }, 2537 | "location": { 2538 | "$ref": "#/components/schemas/Location" 2539 | }, 2540 | "paid": { 2541 | "type": "boolean", 2542 | "description": "Нужно ли оплачивать участие в событии", 2543 | "example": true, 2544 | "default": false 2545 | }, 2546 | "participantLimit": { 2547 | "type": "integer", 2548 | "description": "Ограничение на количество участников. Значение 0 - означает отсутствие ограничения", 2549 | "format": "int32", 2550 | "example": 10, 2551 | "default": 0 2552 | }, 2553 | "requestModeration": { 2554 | "type": "boolean", 2555 | "description": "Нужна ли пре-модерация заявок на участие. Если true, то все заявки будут ожидать подтверждения инициатором события. Если false - то будут подтверждаться автоматически.", 2556 | "example": false, 2557 | "default": true 2558 | }, 2559 | "title": { 2560 | "maxLength": 120, 2561 | "minLength": 3, 2562 | "type": "string", 2563 | "description": "Заголовок события", 2564 | "example": "Сплав на байдарках" 2565 | } 2566 | }, 2567 | "description": "Новое событие" 2568 | }, 2569 | "NewUserRequest": { 2570 | "required": [ 2571 | "email", 2572 | "name" 2573 | ], 2574 | "type": "object", 2575 | "properties": { 2576 | "email": { 2577 | "maxLength": 254, 2578 | "minLength": 6, 2579 | "type": "string", 2580 | "description": "Почтовый адрес", 2581 | "example": "ivan.petrov@practicummail.ru" 2582 | }, 2583 | "name": { 2584 | "maxLength": 250, 2585 | "minLength": 2, 2586 | "type": "string", 2587 | "description": "Имя", 2588 | "example": "Иван Петров" 2589 | } 2590 | }, 2591 | "description": "Данные нового пользователя" 2592 | }, 2593 | "ParticipationRequestDto": { 2594 | "type": "object", 2595 | "properties": { 2596 | "created": { 2597 | "type": "string", 2598 | "description": "Дата и время создания заявки", 2599 | "example": "2022-09-06T21:10:05.432" 2600 | }, 2601 | "event": { 2602 | "type": "integer", 2603 | "description": "Идентификатор события", 2604 | "format": "int64", 2605 | "example": 1 2606 | }, 2607 | "id": { 2608 | "type": "integer", 2609 | "description": "Идентификатор заявки", 2610 | "format": "int64", 2611 | "example": 3 2612 | }, 2613 | "requester": { 2614 | "type": "integer", 2615 | "description": "Идентификатор пользователя, отправившего заявку", 2616 | "format": "int64", 2617 | "example": 2 2618 | }, 2619 | "status": { 2620 | "type": "string", 2621 | "description": "Статус заявки", 2622 | "example": "PENDING" 2623 | } 2624 | }, 2625 | "description": "Заявка на участие в событии" 2626 | }, 2627 | "UpdateCompilationRequest": { 2628 | "type": "object", 2629 | "properties": { 2630 | "events": { 2631 | "uniqueItems": true, 2632 | "type": "array", 2633 | "description": "Список id событий подборки для полной замены текущего списка", 2634 | "items": { 2635 | "type": "integer", 2636 | "description": "Список id событий подборки для полной замены текущего списка", 2637 | "format": "int64" 2638 | } 2639 | }, 2640 | "pinned": { 2641 | "type": "boolean", 2642 | "description": "Закреплена ли подборка на главной странице сайта", 2643 | "example": true 2644 | }, 2645 | "title": { 2646 | "maxLength": 50, 2647 | "minLength": 1, 2648 | "type": "string", 2649 | "description": "Заголовок подборки", 2650 | "example": "Необычные фотозоны" 2651 | } 2652 | }, 2653 | "description": "Изменение информации о подборке событий. Если поле в запросе не указано (равно null) - значит изменение этих данных не треубется." 2654 | }, 2655 | "UpdateEventAdminRequest": { 2656 | "type": "object", 2657 | "properties": { 2658 | "annotation": { 2659 | "maxLength": 2000, 2660 | "minLength": 20, 2661 | "type": "string", 2662 | "description": "Новая аннотация", 2663 | "example": "Сап прогулки по рекам и каналам – это возможность увидеть Практикбург с другого ракурса" 2664 | }, 2665 | "category": { 2666 | "type": "integer", 2667 | "description": "Новая категория", 2668 | "format": "int64", 2669 | "example": 3 2670 | }, 2671 | "description": { 2672 | "maxLength": 7000, 2673 | "minLength": 20, 2674 | "type": "string", 2675 | "description": "Новое описание", 2676 | "example": "От английского SUP - Stand Up Paddle — \"стоя на доске с веслом\", гавайская разновидность сёрфинга, в котором серфер, стоя на доске, катается на волнах и при этом гребет веслом, а не руками, как в классическом серфинге." 2677 | }, 2678 | "eventDate": { 2679 | "type": "string", 2680 | "description": "Новые дата и время на которые намечено событие. Дата и время указываются в формате \"yyyy-MM-dd HH:mm:ss\"", 2681 | "example": "2023-10-11 23:10:05" 2682 | }, 2683 | "location": { 2684 | "$ref": "#/components/schemas/Location" 2685 | }, 2686 | "paid": { 2687 | "type": "boolean", 2688 | "description": "Новое значение флага о платности мероприятия", 2689 | "example": true 2690 | }, 2691 | "participantLimit": { 2692 | "type": "integer", 2693 | "description": "Новый лимит пользователей", 2694 | "format": "int32", 2695 | "example": 7 2696 | }, 2697 | "requestModeration": { 2698 | "type": "boolean", 2699 | "description": "Нужна ли пре-модерация заявок на участие", 2700 | "example": false 2701 | }, 2702 | "stateAction": { 2703 | "type": "string", 2704 | "description": "Новое состояние события", 2705 | "enum": [ 2706 | "PUBLISH_EVENT", 2707 | "REJECT_EVENT" 2708 | ] 2709 | }, 2710 | "title": { 2711 | "maxLength": 120, 2712 | "minLength": 3, 2713 | "type": "string", 2714 | "description": "Новый заголовок", 2715 | "example": "Сап прогулки по рекам и каналам" 2716 | } 2717 | }, 2718 | "description": "Данные для изменения информации о событии. Если поле в запросе не указано (равно null) - значит изменение этих данных не треубется." 2719 | }, 2720 | "UpdateEventUserRequest": { 2721 | "type": "object", 2722 | "properties": { 2723 | "annotation": { 2724 | "maxLength": 2000, 2725 | "minLength": 20, 2726 | "type": "string", 2727 | "description": "Новая аннотация", 2728 | "example": "Сап прогулки по рекам и каналам – это возможность увидеть Практикбург с другого ракурса" 2729 | }, 2730 | "category": { 2731 | "type": "integer", 2732 | "description": "Новая категория", 2733 | "format": "int64", 2734 | "example": 3 2735 | }, 2736 | "description": { 2737 | "maxLength": 7000, 2738 | "minLength": 20, 2739 | "type": "string", 2740 | "description": "Новое описание", 2741 | "example": "От английского SUP - Stand Up Paddle — \"стоя на доске с веслом\", гавайская разновидность сёрфинга, в котором серфер, стоя на доске, катается на волнах и при этом гребет веслом, а не руками, как в классическом серфинге." 2742 | }, 2743 | "eventDate": { 2744 | "type": "string", 2745 | "description": "Новые дата и время на которые намечено событие. Дата и время указываются в формате \"yyyy-MM-dd HH:mm:ss\"", 2746 | "example": "2023-10-11 23:10:05" 2747 | }, 2748 | "location": { 2749 | "$ref": "#/components/schemas/Location" 2750 | }, 2751 | "paid": { 2752 | "type": "boolean", 2753 | "description": "Новое значение флага о платности мероприятия", 2754 | "example": true 2755 | }, 2756 | "participantLimit": { 2757 | "type": "integer", 2758 | "description": "Новый лимит пользователей", 2759 | "format": "int32", 2760 | "example": 7 2761 | }, 2762 | "requestModeration": { 2763 | "type": "boolean", 2764 | "description": "Нужна ли пре-модерация заявок на участие", 2765 | "example": false 2766 | }, 2767 | "stateAction": { 2768 | "type": "string", 2769 | "description": "Изменение сотояния события", 2770 | "example": "CANCEL_REVIEW", 2771 | "enum": [ 2772 | "SEND_TO_REVIEW", 2773 | "CANCEL_REVIEW" 2774 | ] 2775 | }, 2776 | "title": { 2777 | "maxLength": 120, 2778 | "minLength": 3, 2779 | "type": "string", 2780 | "description": "Новый заголовок", 2781 | "example": "Сап прогулки по рекам и каналам" 2782 | } 2783 | }, 2784 | "description": "Данные для изменения информации о событии. Если поле в запросе не указано (равно null) - значит изменение этих данных не треубется." 2785 | }, 2786 | "UserDto": { 2787 | "required": [ 2788 | "email", 2789 | "name" 2790 | ], 2791 | "type": "object", 2792 | "properties": { 2793 | "email": { 2794 | "type": "string", 2795 | "description": "Почтовый адрес", 2796 | "example": "petrov.i@practicummail.ru" 2797 | }, 2798 | "id": { 2799 | "type": "integer", 2800 | "description": "Идентификатор", 2801 | "format": "int64", 2802 | "readOnly": true, 2803 | "example": 1 2804 | }, 2805 | "name": { 2806 | "type": "string", 2807 | "description": "Имя", 2808 | "example": "Петров Иван" 2809 | } 2810 | }, 2811 | "description": "Пользователь" 2812 | }, 2813 | "UserShortDto": { 2814 | "required": [ 2815 | "id", 2816 | "name" 2817 | ], 2818 | "type": "object", 2819 | "properties": { 2820 | "id": { 2821 | "type": "integer", 2822 | "description": "Идентификатор", 2823 | "format": "int64", 2824 | "example": 3 2825 | }, 2826 | "name": { 2827 | "type": "string", 2828 | "description": "Имя", 2829 | "example": "Фёдоров Матвей" 2830 | } 2831 | }, 2832 | "description": "Пользователь (краткая информация)" 2833 | } 2834 | } 2835 | } 2836 | } 2837 | --------------------------------------------------------------------------------