diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000000000000000000000000000000000000..8ae4d470d17eb9b5cdb095896b4a17eea7e9f581
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,7 @@
+.idea
+*.iml
+.git/
+.gradle
+gradle
+out/
+Dockerfile
\ No newline at end of file
diff --git a/.env b/.env
new file mode 100644
index 0000000000000000000000000000000000000000..d9afc9929fb00baeae0d224af2bea6d1326586c8
--- /dev/null
+++ b/.env
@@ -0,0 +1,8 @@
+SERVER_ADDRESS="localhost:8080"
+POSTGRES_CONN="postgres://postgres:postgres@172.18.1.2:5432/avito?sslmode=disable"
+POSTGRES_JDBC_URL="jdbc:postgresql://your_host:your_port/your_db"
+POSTGRES_USERNAME="postgres"
+POSTGRES_PASSWORD="postgres"
+POSTGRES_HOST="172.18.1.2"
+POSTGRES_PORT="5432"
+POSTGRES_DATABASE="avito"
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..63177e3dfcbc9db2a754b7936ac2b395a3186e4b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,30 @@
+HELP.md
+.gradle
+/build/
+!gradle/wrapper/gradle-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+/out/
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+
+### VS Code ###
+.vscode/
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed563e8f35f13197e3262fe2e79de79a3575b210
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,153 @@
+variables:
+  CALLBACK_URL: "https://codenrock.com/api/gitlab/check"
+  CONTEXT: config.yaml
+  DOMAIN: avito2024.codenrock.com
+
+stages:
+  - build
+  - deploy
+
+build:
+  stage: build
+  image: docker:27.0.3-dind
+  services:
+    - docker:27.0.3-dind
+  before_script:
+    - mkdir -pv ${HOME}/.docker
+    - cp -vf  $YCR_DOCKER_CONFIG_JSON ${HOME}/.docker/config.json
+    - chmod 0600 ${HOME}/.docker/config.json
+    - sleep 20
+    - docker info
+  variables:
+     DOCKER_HOST: tcp://docker:2375
+     DOCKER_TLS_CERTDIR: ""
+  only:
+    - main
+    - master
+  script:
+    - docker build . -f ./Dockerfile -t ${CI_REGISTRY_IMAGE}:$CI_COMMIT_SHA
+    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
+    - docker push ${CI_REGISTRY_IMAGE}:$CI_COMMIT_SHA
+  tags:
+    - runner
+    - build
+    - k8s
+
+deploy:
+  environment:
+    name: production
+    url: https://$KUBE_NAMESPACE-$CI_PROJECT_NAMESPACE_ID.$DOMAIN
+  image:
+    name: bitnami/kubectl:latest
+    entrypoint: ['']
+  stage: deploy
+  only:
+    - main
+    - master
+  script:
+    - export KUBE_NAMESPACE=$(echo $CI_PROJECT_DIR|sed 's/.*\/\(.*\)\/.*/\1/')
+    - export HOST_NAME=$KUBE_NAMESPACE-$CI_PROJECT_NAMESPACE_ID.$DOMAIN
+    - if [ "$KUBE_NAMESPACE" == "" ]; then echo "Namespace is not configured"; exit 1; fi
+    - echo "URL https://$HOST_NAME"
+    - kubectl config get-contexts
+    - kubectl config use-context $CONTEXT
+    - kubectl create ns $KUBE_NAMESPACE || true
+    - kubectl -n default get secret avito2024-tls -o yaml|sed 's/  namespace:.*//g'|sed 's/  uid:.*//g'|sed 's/  resourceVersion:.*//g'|sed 's/  creationTimestamp:.*//g' | kubectl apply --namespace $KUBE_NAMESPACE -f -
+    - kubectl -n default get secret regcred -o yaml|sed 's/  namespace:.*//g'|sed 's/  uid:.*//g'|sed 's/  resourceVersion:.*//g'|sed 's/  creationTimestamp:.*//g' | kubectl apply --namespace $KUBE_NAMESPACE -f -
+    - |
+      cat <<EOF | kubectl -n $KUBE_NAMESPACE apply -f -
+      ---
+      apiVersion: apps/v1
+      kind: Deployment
+      metadata:
+        name: $KUBE_NAMESPACE-backend
+        annotations:
+          app.gitlab.com/app: $CI_PROJECT_PATH_SLUG
+          app.gitlab.com/env: $CI_ENVIRONMENT_SLUG
+      spec:
+        replicas: 1
+        selector:
+          matchLabels:
+            app: $KUBE_NAMESPACE-backend
+        template:
+          metadata:
+            labels:
+              app: $KUBE_NAMESPACE-backend
+            annotations:
+              app.gitlab.com/app: $CI_PROJECT_PATH_SLUG
+              app.gitlab.com/env: $CI_ENVIRONMENT_SLUG
+          spec:
+            imagePullSecrets:
+              - name: regcred
+            containers:
+              - name: $KUBE_NAMESPACE
+                image: ${CI_REGISTRY_IMAGE}:$CI_COMMIT_SHA
+                imagePullPolicy: Always
+                resources:
+                  requests:
+                    cpu: "100m"
+                    memory: "256M"
+                env:
+                - name: POSTGRES_CONN
+                  value: "postgres://$KUBE_NAMESPACE:$KUBE_NAMESPACE@rc1b-5xmqy6bq501kls4m.mdb.yandexcloud.net:6432/$KUBE_NAMESPACE"
+                - name: POSTGRES_JDBC_URL
+                  value: "jdbc:postgresql://rc1b-5xmqy6bq501kls4m.mdb.yandexcloud.net:6432/$KUBE_NAMESPACE"
+                - name: POSTGRES_USERNAME
+                  value: "$KUBE_NAMESPACE"
+                - name: POSTGRES_PASSWORD
+                  value: "$KUBE_NAMESPACE"
+                - name: POSTGRES_HOST
+                  value: "rc1b-5xmqy6bq501kls4m.mdb.yandexcloud.net"
+                - name: POSTGRES_PORT
+                  value: "6432"
+                - name: POSTGRES_DATABASE
+                  value: "$KUBE_NAMESPACE"
+                - name: SERVER_ADDRESS
+                  value: "0.0.0.0:8080"
+                ports:
+                  - containerPort: 8080
+                    protocol: TCP
+      ---
+      apiVersion: v1
+      kind: Service
+      metadata:
+        name: ${KUBE_NAMESPACE}-backend
+      spec:
+        selector:
+          app: ${KUBE_NAMESPACE}-backend
+        ports:
+          - protocol: TCP
+            port: 8080
+            targetPort: 8080
+      ---
+      apiVersion: networking.k8s.io/v1
+      kind: Ingress
+      metadata:
+        name: $KUBE_NAMESPACE-backend
+        annotations:
+          kubernetes.io/ingress.class: nginx
+          #cert-manager.io/cluster-issuer: "letsencrypt"
+          nginx.ingress.kubernetes.io/ssl-redirect: "false"
+          nginx.ingress.kubernetes.io/force-ssl-redirect: "false"
+      spec:
+        tls:
+        - hosts:
+          - $HOST_NAME
+          secretName: avito2024-tls
+        rules:
+        - host: $HOST_NAME
+          http:
+            paths:
+            - path: /
+              pathType: ImplementationSpecific
+              backend:
+                service:
+                  name: $KUBE_NAMESPACE-backend
+                  port:
+                    number: 8080
+      ---
+      EOF
+  tags:
+    - runner
+    - build
+    - k8s
diff --git a/.gitlab/agents/yc/config.yaml b/.gitlab/agents/yc/config.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..7499bcafdf084e0fdb580a381f2cc500a6c8b4be
--- /dev/null
+++ b/.gitlab/agents/yc/config.yaml
@@ -0,0 +1,3 @@
+ci_access:
+  groups:
+    - id: avito-testirovanie-na-backend-1270
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..39b92eeb459ae5b9ab8694ac36e1e5a67b563898
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,15 @@
+FROM gradle:4.7.0-jdk8-alpine AS build
+COPY --chown=gradle:gradle . /home/gradle/src
+WORKDIR /home/gradle/src
+RUN gradle build --no-daemon 
+
+FROM openjdk:8-jre-slim
+
+EXPOSE 8080
+
+RUN mkdir /app
+
+COPY --from=build /home/gradle/src/build/libs/*.jar /app/spring-boot-application.jar
+
+ENTRYPOINT ["java", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseCGroupMemoryLimitForHeap", "-Djava.security.egd=file:/dev/./urandom","-jar","/app/spring-boot-application.jar"]
+
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..4bc5c53f8eb2bf4fa1af31aa72ebd8680f8b4a44
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,8 @@
+run:
+	go run ./cmd/app/main.go -l
+
+migrateup:
+	migrate -path ./migrations -database postgres://postgres:postgres@172.18.1.2:5432/avito?sslmode=disable -verbose up
+
+migratedown:
+	migrate -path ./migrations -database postgres://postgres:postgres@172.18.1.2:5432/avito?sslmode=disable -verbose down
diff --git a/README.md b/README.md
index 4f67d158636bf267600a7580459c831d5f83e23e..94884e06f4ffd4b4d8183ba2bb14791fefa7f327 100644
--- a/README.md
+++ b/README.md
@@ -1,93 +1,31 @@
-# Zadanie 6105
+## Структура проекта
+В данном проекте находится типовой пример для сборки приложения в докере из находящящегося в проекте Dockerfile. Пример на Gradle используется исключительно в качестве шаблона, вы можете переписать проект как вам хочется - главное, что бы Dockerfile находился в корне проекта и приложение отвечало по порту 8080. Других требований нет.
 
+## Задание
+В папке "задание" размещена задача.
 
+## Сбор и развертывание приложения
+Приложение должно отвечать по порту `8080` (жестко задано в настройках деплоя). После деплоя оно будет доступно по адресу: `https://<имя_проекта>-<уникальный_идентификатор_группы_группы>.avito2024.codenrock.com`
 
-## Getting started
-
-To make it easy for you to get started with GitLab, here's a list of recommended next steps.
-
-Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
-
-## Add your files
-
-- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
-- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
+Пример: Для кода из репозитория `/avito2024/cnrprod-team-27437/task1` сформируется домен
 
 ```
-cd existing_repo
-git remote add origin https://git.codenrock.com/cnrprod1713782508-user-78446/zadanie-6105.git
-git branch -M main
-git push -uf origin main
+task1-5447.avito2024.codenrock.com
 ```
 
-## Integrate with your tools
-
-- [ ] [Set up project integrations](https://git.codenrock.com/cnrprod1713782508-user-78446/zadanie-6105/-/settings/integrations)
-
-## Collaborate with your team
-
-- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
-- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
-- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
-- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
-- [ ] [Set auto-merge](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
-
-## Test and Deploy
-
-Use the built-in continuous integration in GitLab.
-
-- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
-- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
-- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
-- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
-- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
-
-***
-
-# Editing this README
-
-When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template.
-
-## Suggestions for a good README
-
-Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
-
-## Name
-Choose a self-explaining name for your project.
-
-## Description
-Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
-
-## Badges
-On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
-
-## Visuals
-Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
-
-## Installation
-Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
 
-## Usage
-Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
+**Для удобства домен указывается в логе сборки**
 
-## Support
-Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
+Логи сборки проекта находятся на вкладке **CI/CD** -> **Jobs**.
 
-## Roadmap
-If you have ideas for releases in the future, it is a good idea to list them in the README.
+Ссылка на собранный проект находится на вкладке **Deployments** -> **Environment**. Вы можете сразу открыть URL по кнопке "Open".
 
-## Contributing
-State if you are open to contributions and what your requirements are for accepting them.
+## Доступ к сервисам
 
-For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
+### Kubernetes
+На вашу команду выделен kubernetes namespace. Для подключения к нему используйте утилиту `kubectl` и `*.kube.config` файл, который вам выдадут организаторы.
 
-You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
+Состояние namespace, работающие pods и логи приложений можно посмотреть по адресу [https://dashboard.avito2024.codenrock.com/](https://dashboard.avito2024.codenrock.com/). Для открытия дашборда необходимо выбрать авторизацию через Kubeconfig и указать путь до выданного вам `*.kube.config` файла
 
-## Authors and acknowledgment
-Show your appreciation to those who have contributed to the project.
 
-## License
-For open source projects, say how it is licensed.
 
-## Project status
-If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
diff --git a/SOMESTRUCT.md b/SOMESTRUCT.md
new file mode 100644
index 0000000000000000000000000000000000000000..2c47f4611c2e4070401597acb8d62ad0c6208585
--- /dev/null
+++ b/SOMESTRUCT.md
@@ -0,0 +1,98 @@
+<pre><code>
+package main
+
+import (
+"database/sql"
+"fmt"
+"os"
+
+	"github.com/gin-gonic/gin"
+	_ "github.com/lib/pq"
+)
+
+func main() {
+// Чтение переменных окружения
+serverAddress := os.Getenv("SERVER_ADDRESS")
+postgresConnURL := os.Getenv("POSTGRES_CONN")
+
+	// Подключение к базе данных PostgreSQL
+	db, err := sql.Open("postgres", postgresConnURL)
+	if err != nil {
+		panic(err)
+	}
+	defer db.Close()
+
+	// Создание экземпляра Gin
+	r := gin.Default()
+
+	// Маршруты API
+	r.GET("/api/ping", func(c *gin.Context) {
+		c.JSON(200, gin.H{
+			"message": "ok",
+		})
+	})
+
+	tenders := r.Group("/api/tenders")
+	{
+		tenders.GET("", listTenders)
+		tenders.POST("/new", createTender)
+		tenders.GET("/my", getTendersByUser)
+		tenders.PATCH("/:id/edit", editTender)
+		tenders.PUT("/:id/rollback/:version", rollbackTender)
+	}
+
+	bids := r.Group("/api/bids")
+	{
+		bids.POST("/new", createBid)
+		bids.GET("/my", getBidsByUser)
+		bids.GET("/:tenderId/list", getBidsForTender)
+		bids.PATCH("/:id/edit", editBid)
+		bids.PUT("/:id/rollback/:version", rollbackBid)
+	}
+
+	// Запуск сервера
+	r.Run(serverAddress)
+}
+
+// Обработчики маршрутов
+func listTenders(c *gin.Context) {
+// Логика получения списка тендеров
+}
+
+func createTender(c *gin.Context) {
+// Логика создания нового тендера
+}
+
+func getTendersByUser(c *gin.Context) {
+// Логика получения тендеров пользователя
+}
+
+func editTender(c *gin.Context) {
+// Логика редактирования тендера
+}
+
+func rollbackTender(c *gin.Context) {
+// Логика отката версии тендера
+}
+
+func createBid(c *gin.Context) {
+// Логика создания нового предложения
+}
+
+func getBidsByUser(c *gin.Context) {
+// Логика получения предложений пользователя
+}
+
+func getBidsForTender(c *gin.Context) {
+// Логика получения предложений для тендера
+}
+
+func editBid(c *gin.Context) {
+// Логика редактирования предложения
+}
+
+func rollbackBid(c *gin.Context) {
+// Логика отката версии предложения
+}
+
+</code></pre>
\ No newline at end of file
diff --git a/backend/README.md b/backend/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..e47823eeed09876f4d3850f90e1c7a81bdaede78
--- /dev/null
+++ b/backend/README.md
@@ -0,0 +1,38 @@
+# Gradle Docker Codefresh example
+
+This is an example Java application that uses Spring Boot 2, Gradle and Docker
+It is compiled using Codefresh.
+
+If you are looking for Maven, then see this [example](https://github.com/codefresh-contrib/spring-boot-2-sample-app)
+
+## Create a multi-stage docker image
+
+To compile and package using Docker multi-stage builds
+
+```bash
+docker build . -t my-app
+```
+
+## Create a Docker image packaging an existing jar
+
+```bash
+./gradlew build
+docker build . -t my-app -f Dockerfile.only-package
+```
+
+## To run the docker image
+
+```bash
+docker run -p 8080:8080 my-app
+```
+
+And then visit http://localhost:8080 in your browser.
+
+## To use this project in Codefresh
+
+There is also a [codefresh.yml](codefresh.yml) for easy usage with the [Codefresh](codefresh.io) CI/CD platform.
+
+For the simple packaging pipeline see [codefresh-package-only.yml](codefresh-package-only.yml)
+
+More details can be found in [Codefresh documentation](https://codefresh.io/docs/docs/learn-by-example/java/gradle/)
+
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..3f91239dabe9f72de0925d3404fa027cb8139de8
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,26 @@
+plugins {
+	id 'org.springframework.boot' version '2.1.4.RELEASE'
+	id 'java'
+}
+
+apply plugin: 'io.spring.dependency-management'
+
+group = 'io.codefresh'
+version = '0.0.1-SNAPSHOT'
+sourceCompatibility = '1.8'
+
+repositories {
+	mavenCentral()
+}
+
+dependencies {
+	implementation 'org.springframework.boot:spring-boot-starter-actuator'
+	implementation 'org.springframework.boot:spring-boot-starter-web'
+	testImplementation 'org.springframework.boot:spring-boot-starter-test'
+}
+
+test {
+    useJUnit()
+
+    maxHeapSize = '1G'
+}
\ No newline at end of file
diff --git a/cmd/app/main.go b/cmd/app/main.go
new file mode 100644
index 0000000000000000000000000000000000000000..4cda59a11a909fc44539a1b968ca4920e364a0db
--- /dev/null
+++ b/cmd/app/main.go
@@ -0,0 +1,24 @@
+package main
+
+import (
+	"flag"
+	"log"
+	"os"
+
+	"github.com/DarRo9/Tenders/internal/app"
+	"github.com/DarRo9/Tenders/internal/config"
+)
+
+func main() {
+	fl := flag.Bool("l", false, "Show logs")
+	flag.Parse()
+
+	cfg := config.TakeConfig(*fl)
+	err := config.ConfirmConfig(cfg)
+	if err != nil {
+		log.Fatal(err)
+		os.Exit(1)
+	}
+
+	app.Start(cfg)
+}
diff --git a/codefresh-package-only.yml b/codefresh-package-only.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ecd6076e2d92d421d1848d3ccf739d6c5211f1de
--- /dev/null
+++ b/codefresh-package-only.yml
@@ -0,0 +1,34 @@
+version: '1.0'
+stages:
+  - prepare
+  - test
+  - package
+  - build
+steps:
+  main_clone:
+    title: Cloning main repository...
+    stage: prepare
+    type: git-clone
+    repo: 'codefresh-contrib/gradle-sample-app'
+    revision: master
+    git: github
+  MyUnitTests:
+    title: Compile/Unit test
+    stage: test
+    image: gradle:4.7.0-jdk8-alpine
+    commands:
+      - gradle test --no-daemon --build-cache --gradle-user-home=/codefresh/volume/.gradle -Dmaven.repo.local=/codefresh/volume/m2
+  BuildMyJar:
+    title: Packaging Jar file
+    stage: package
+    image: gradle:4.7.0-jdk8-alpine
+    commands:
+     - gradle build --no-daemon --build-cache --gradle-user-home=/codefresh/volume/.gradle -Dmaven.repo.local=/codefresh/volume/m2
+  MyAppDockerImage:
+    title: Building Docker Image
+    type: build
+    stage: build
+    image_name: gradle-sample-app
+    working_directory: ./
+    tag: 'non-multi-stage'
+    dockerfile: Dockerfile.only-package
diff --git a/codefresh.yml b/codefresh.yml
new file mode 100644
index 0000000000000000000000000000000000000000..118117352cacaab57aca08a0e702fd8904fc8afd
--- /dev/null
+++ b/codefresh.yml
@@ -0,0 +1,20 @@
+version: '1.0'
+stages:
+  - prepare
+  - build
+steps:
+  main_clone:
+    title: Cloning main repository...
+    stage: prepare
+    type: git-clone
+    repo: 'codefresh-contrib/gradle-sample-app'
+    revision: master
+    git: github
+  BuildingDockerImage:
+    title: Building Docker Image
+    stage: build
+    type: build
+    image_name: gradle-sample-app
+    working_directory: ./
+    tag: 'multi-stage'
+    dockerfile: Dockerfile
\ No newline at end of file
diff --git a/config.yaml b/config.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..7499bcafdf084e0fdb580a381f2cc500a6c8b4be
--- /dev/null
+++ b/config.yaml
@@ -0,0 +1,3 @@
+ci_access:
+  groups:
+    - id: avito-testirovanie-na-backend-1270
diff --git a/docker-compose.yaml b/docker-compose.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..3dd1f630bb3fcfd1688f8278584fe7bff5ade64a
--- /dev/null
+++ b/docker-compose.yaml
@@ -0,0 +1,26 @@
+version: '3.7'
+
+services:
+  postgres:
+    image: postgres:latest
+    container_name: postgres
+    restart: always
+    volumes:
+      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
+    environment:
+      - POSTGRES_USER=postgres
+      - POSTGRES_PASSWORD=postgres
+      - POSTGRES_DATABASE=avito
+      - POSTGRES_SSL_MODE=disable
+    networks:
+      my_net:
+        ipv4_address: 172.18.1.2
+volumes:
+  post_avito_data:
+
+networks:
+  my_net:
+    driver: bridge
+    ipam:
+      config:
+        - subnet: 172.18.1.0/24
\ No newline at end of file
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000000000000000000000000000000000000..6bce5514e00074db40fbf71b84356ab82466e1da
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,44 @@
+module github.com/DarRo9/Tenders/test_avito
+
+go 1.22.5
+
+require (
+	github.com/DarRo9/Tenders v0.0.0-20240913084324-41d3c82db720
+	github.com/gin-gonic/gin v1.10.0
+	github.com/golang-migrate/migrate/v4 v4.17.1
+	github.com/joho/godotenv v1.5.1
+	github.com/lib/pq v1.10.9
+	github.com/sirupsen/logrus v1.9.2
+)
+
+require (
+	github.com/bytedance/sonic v1.11.6 // indirect
+	github.com/bytedance/sonic/loader v0.1.1 // indirect
+	github.com/cloudwego/base64x v0.1.4 // indirect
+	github.com/cloudwego/iasm v0.2.0 // indirect
+	github.com/gabriel-vasile/mimetype v1.4.3 // indirect
+	github.com/gin-contrib/sse v0.1.0 // indirect
+	github.com/go-playground/locales v0.14.1 // indirect
+	github.com/go-playground/universal-translator v0.18.1 // indirect
+	github.com/go-playground/validator/v10 v10.20.0 // indirect
+	github.com/goccy/go-json v0.10.2 // indirect
+	github.com/hashicorp/errwrap v1.1.0 // indirect
+	github.com/hashicorp/go-multierror v1.1.1 // indirect
+	github.com/json-iterator/go v1.1.12 // indirect
+	github.com/klauspost/cpuid/v2 v2.2.7 // indirect
+	github.com/leodido/go-urn v1.4.0 // indirect
+	github.com/mattn/go-isatty v0.0.20 // indirect
+	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
+	github.com/modern-go/reflect2 v1.0.2 // indirect
+	github.com/pelletier/go-toml/v2 v2.2.2 // indirect
+	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
+	github.com/ugorji/go/codec v1.2.12 // indirect
+	go.uber.org/atomic v1.7.0 // indirect
+	golang.org/x/arch v0.8.0 // indirect
+	golang.org/x/crypto v0.23.0 // indirect
+	golang.org/x/net v0.25.0 // indirect
+	golang.org/x/sys v0.20.0 // indirect
+	golang.org/x/text v0.15.0 // indirect
+	google.golang.org/protobuf v1.34.1 // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
+)
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000000000000000000000000000000000000..1ce2e552e88ca2d61551377f7a52d0467574691b
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,137 @@
+github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
+github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
+github.com/DarRo9/Tenders v0.0.0-20240913084324-41d3c82db720 h1:1diOHc5Hu7zYEC8itbWMeM6tY/ec/+8P55KGIGdwH64=
+github.com/DarRo9/Tenders v0.0.0-20240913084324-41d3c82db720/go.mod h1:h9GY5WyXvI8v6hrvt9Piv7te13CNedBr1WyVmq/LTTM=
+github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
+github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
+github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
+github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
+github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
+github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
+github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
+github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
+github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
+github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dhui/dktest v0.4.1 h1:/w+IWuDXVymg3IrRJCHHOkMK10m9aNVMOyD0X12YVTg=
+github.com/dhui/dktest v0.4.1/go.mod h1:DdOqcUpL7vgyP4GlF3X3w7HbSlz8cEQzwewPveYEQbA=
+github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
+github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
+github.com/docker/docker v24.0.9+incompatible h1:HPGzNmwfLZWdxHqK9/II92pyi1EpYKsAqcl4G0Of9v0=
+github.com/docker/docker v24.0.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
+github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
+github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
+github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
+github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
+github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
+github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
+github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
+github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
+github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
+github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
+github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
+github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
+github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
+github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
+github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
+github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
+github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
+github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
+github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang-migrate/migrate/v4 v4.17.1 h1:4zQ6iqL6t6AiItphxJctQb3cFqWiSpMnX7wLTPnnYO4=
+github.com/golang-migrate/migrate/v4 v4.17.1/go.mod h1:m8hinFyWBn0SA4QKHuKh175Pm9wjmxj3S2Mia7dbXzM=
+github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
+github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
+github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
+github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
+github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
+github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
+github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
+github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
+github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
+github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
+github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
+github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
+github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
+github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
+github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
+github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
+github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
+github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
+github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
+github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
+github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/sirupsen/logrus v1.9.2 h1:oxx1eChJGI6Uks2ZC4W1zpLlVgqB8ner4EuQwV4Ik1Y=
+github.com/sirupsen/logrus v1.9.2/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
+github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
+github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
+github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
+github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
+go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
+go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
+golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
+golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
+golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
+golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
+golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
+golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
+golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
+golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
+golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
+golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg=
+golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM=
+golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
+golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
+google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
+google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
+rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000000000000000000000000000000000000..87b738cbd051603d91cc39de6cb000dd98fe6b02
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000000000000000000000000000000000000..f4d7b2bf616f7674854ff527df47b371b72472da
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
new file mode 100644
index 0000000000000000000000000000000000000000..af6708ff229fda75da4f7cc4da4747217bac4d53
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+    echo "$*"
+}
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Escape application args
+save () {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+  cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000000000000000000000000000000000000..6d57edc706c93465988754383a2d7ff353d4e79f
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/init.sql b/init.sql
new file mode 100644
index 0000000000000000000000000000000000000000..31440f7702e634fa900b83d7e39af86dd5423da6
--- /dev/null
+++ b/init.sql
@@ -0,0 +1,73 @@
+CREATE DATABASE avito;
+\c avito;
+CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
+
+CREATE TABLE employee (
+    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
+    username VARCHAR(50) UNIQUE NOT NULL,
+    first_name VARCHAR(50),
+    last_name VARCHAR(50),
+    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+);
+
+CREATE TYPE organization_type AS ENUM (
+    'IE',
+    'LLC',
+    'JSC'
+);
+
+CREATE TABLE organization (
+    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
+    name VARCHAR(100) NOT NULL,
+    description TEXT,
+    type organization_type,
+    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+);
+
+CREATE TABLE organization_responsible (
+    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
+    organization_id UUID REFERENCES organization(id) ON DELETE CASCADE,
+    user_id UUID REFERENCES employee(id) ON DELETE CASCADE
+);
+
+-- Вставка данных в таблицу employee
+INSERT INTO employee (username, first_name, last_name)
+VALUES
+    ('john_doe', 'John', 'Doe'),
+    ('jane_smith', 'Jane', 'Smith'),
+    ('alex_brown', 'Alex', 'Brown'),
+    ('emily_jones', 'Emily', 'Jones'),
+    ('michael_white', 'Michael', 'White'),
+    ('jdoe', 'John', 'Doe'),
+    ('asmith', 'Alice', 'Smith'),
+    ('bjackson', 'Bob', 'Jackson'),
+    ('cjohnson', 'Charlie', 'Johnson'),
+    ('dlee', 'Diana', 'Lee');
+
+-- Вставка данных в таблицу organization
+INSERT INTO organization (name, description, type)
+VALUES
+    ('Tech Innovations', 'A company focused on technological advancements.', 'LLC'),
+    ('Green Solutions', 'An organization dedicated to environmental sustainability.', 'JSC'),
+    ('Fast Delivery Services', 'Logistics and delivery company.', 'IE'),
+    ('Creative Designs', 'A design agency specializing in branding.', 'LLC'),
+    ('Health First', 'A health and wellness organization.', 'JSC'),
+    ('Tech Innovations LLC', 'A company focused on technological advancements.', 'LLC'),
+    ('Green Energy JSC', 'A joint stock company specializing in renewable energy.', 'JSC'),
+    ('Health Solutions IE', 'An individual enterprise providing health services.', 'IE'),
+    ('Global Logistics LLC', 'Logistics and supply chain management services.', 'LLC'),
+    ('Creative Media JSC', 'A joint stock company in the media and entertainment industry.', 'JSC');;
+
+INSERT INTO organization_responsible (organization_id, user_id) VALUES
+((SELECT id FROM organization WHERE name = 'Tech Innovations LLC'), (SELECT id FROM employee WHERE username = 'jdoe')),
+((SELECT id FROM organization WHERE name = 'Green Energy JSC'), (SELECT id FROM employee WHERE username = 'asmith')),
+((SELECT id FROM organization WHERE name = 'Health Solutions IE'), (SELECT id FROM employee WHERE username = 'bjackson')),
+((SELECT id FROM organization WHERE name = 'Global Logistics LLC'), (SELECT id FROM employee WHERE username = 'cjohnson')),
+((SELECT id FROM organization WHERE name = 'Creative Media JSC'), (SELECT id FROM employee WHERE username = 'dlee')),
+((SELECT id FROM organization WHERE name = 'Tech Innovations'), (SELECT id FROM employee WHERE username = 'john_doe')),
+((SELECT id FROM organization WHERE name = 'Green Solutions'), (SELECT id FROM employee WHERE username = 'jane_smith')),
+((SELECT id FROM organization WHERE name = 'Fast Delivery Services'), (SELECT id FROM employee WHERE username = 'alex_brown')),
+((SELECT id FROM organization WHERE name = 'Creative Designs'), (SELECT id FROM employee WHERE username = 'emily_jones')),
+((SELECT id FROM organization WHERE name = 'Health First'), (SELECT id FROM employee WHERE username = 'michael_white'));
\ No newline at end of file
diff --git a/internal/app/app.go b/internal/app/app.go
new file mode 100644
index 0000000000000000000000000000000000000000..c80b91c031adc62994ac527f3b3dd315429d2cea
--- /dev/null
+++ b/internal/app/app.go
@@ -0,0 +1,52 @@
+package app
+
+import (
+	"os"
+	"os/signal"
+	"syscall"
+
+	"github.com/DarRo9/Tenders/internal/config"
+	"github.com/DarRo9/Tenders/internal/handler"
+	"github.com/DarRo9/Tenders/internal/repo"
+	"github.com/DarRo9/Tenders/internal/service"
+	"github.com/DarRo9/Tenders/pkg/server"
+	log "github.com/sirupsen/logrus"
+)
+
+var (
+	migrationsFile = "file://migrations"
+)
+
+func Start(cfg *config.Config) {
+	MakeLogs("Start")
+	mgr := MakeMigration(migrationsFile, cfg.Postgres.ConnString)
+	err := mgr.Use()
+	if err != nil {
+		log.Printf("%v\n", err)
+	}
+	pdb, err := repo.MakeDB(cfg.Postgres)
+	if err != nil {
+		log.Printf("%v\n", err)
+		return
+	}
+	repo := repo.MakeRepo(pdb)
+	serv := service.MakeService(repo)
+	handler := handler.MakeHandler(serv)
+	route := handler.MakeRoutes()
+	server := server.Server{}
+
+	go func() {
+		if err = server.Start(cfg.HttpServer, route); err != nil {
+			log.Printf("Error: can't start server: %v", err)
+			return
+		}
+	}()
+
+	defer server.Shutdown(nil)
+	log.Printf("Server successfully started on %s\n", "http://"+cfg.Address)
+	quit := make(chan os.Signal, 1)
+	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
+	<-quit
+	log.Println("End of servers work")
+
+}
diff --git a/internal/app/logger.go b/internal/app/logger.go
new file mode 100644
index 0000000000000000000000000000000000000000..59ec833ab555044c44b6d8d830c4726d3ba762af
--- /dev/null
+++ b/internal/app/logger.go
@@ -0,0 +1,19 @@
+package app
+
+import (
+	"os"
+	"time"
+
+	log "github.com/sirupsen/logrus"
+)
+
+func MakeLogs(level string) {
+	logrusLevel, err := log.ParseLevel(level)
+	if err != nil {
+		log.SetLevel(log.DebugLevel)
+	} else {
+		log.SetLevel(logrusLevel)
+	}
+	log.SetFormatter(&log.TextFormatter{TimestampFormat: time.RFC3339})
+	log.SetOutput(os.Stdout)
+}
diff --git a/internal/app/migration.go b/internal/app/migration.go
new file mode 100644
index 0000000000000000000000000000000000000000..428eaa0d57a8fe816e07d4f3f2d05c84f0f3c7b8
--- /dev/null
+++ b/internal/app/migration.go
@@ -0,0 +1,52 @@
+package app
+
+import (
+	"errors"
+	"fmt"
+	"time"
+
+	"github.com/golang-migrate/migrate/v4"
+	_ "github.com/golang-migrate/migrate/v4/database/postgres"
+	_ "github.com/golang-migrate/migrate/v4/source/file"
+)
+
+var (
+	defaultAttempts = 10
+	defaultTimeout  = time.Second
+)
+
+type Migrator struct {
+	migrationsFile  string
+	pdbectionString string
+}
+
+func MakeMigration(migrationFile, pdb string) *Migrator {
+	return &Migrator{
+		migrationsFile:  migrationFile,
+		pdbectionString: pdb,
+	}
+}
+
+func (m *Migrator) Use() error {
+	var mgr *migrate.Migrate
+	var err error
+
+	for attempt := 0; attempt < defaultAttempts; attempt++ {
+		mgr, err = migrate.New(m.migrationsFile, m.pdbectionString)
+		if err == nil {
+			break
+		}
+
+		time.Sleep(defaultTimeout)
+	}
+
+	if err != nil {
+		return fmt.Errorf("Can't create migration: %v", err)
+	}
+
+	defer mgr.Close()
+	if err = mgr.Up(); err != nil && !errors.Is(err, migrate.ErrNoChange) {
+		return fmt.Errorf("Can't to apply migrations: %v", err)
+	}
+	return nil
+}
diff --git a/internal/config/config.go b/internal/config/config.go
new file mode 100644
index 0000000000000000000000000000000000000000..259c462a18321edb89882578af030d7ece1cce68
--- /dev/null
+++ b/internal/config/config.go
@@ -0,0 +1,73 @@
+package config
+
+import (
+	"errors"
+	"fmt"
+	"log"
+	"os"
+	"reflect"
+
+	"github.com/joho/godotenv"
+)
+
+type Postgres struct {
+	ConnString string `env:"POSTGRES_CONN"`
+	JDBCUrl    string `env:"POSTGRES_JDBC_URL"`
+	Username   string `env:"POSTGRES_USERNAME"`
+	Password   string `env:"POSTGRES_PASSWORD"`
+	Host       string `env:"POSTGRES_HOST" env-default:"localhost"`
+	Port       string `env:"POSTGRES_PORT" env-default:"5432"`
+	Database   string `env:"POSTGRES_DATABASE" env-default:"postgres"`
+}
+
+type HttpServer struct {
+	Address string `env:"SERVER_ADDRESS" env-default:"0.0.0.0:8080"`
+}
+
+type Config struct {
+	HttpServer `yaml:"http_server"`
+	Postgres   `yaml:"postgres"`
+}
+
+func TakeConfig(loader bool) *Config {
+	var conf Config
+	if loader {
+		err := godotenv.Load()
+		if err != nil {
+			log.Fatalf("error loading env variables: %s", err)
+		}
+	}
+
+	conf.HttpServer.Address = os.Getenv("SERVER_ADDRESS")
+	conf.Postgres.ConnString = os.Getenv("POSTGRES_CONN")
+	conf.Postgres.JDBCUrl = os.Getenv("POSTGRES_JDBC_URL")
+	conf.Postgres.Username = os.Getenv("POSTGRES_USERNAME")
+	conf.Postgres.Password = os.Getenv("POSTGRES_PASSWORD")
+	conf.Postgres.Host = os.Getenv("POSTGRES_HOST")
+	conf.Postgres.Port = os.Getenv("POSTGRES_PORT")
+	conf.Postgres.Database = os.Getenv("POSTGRES_DATABASE")
+
+	return &conf
+}
+
+func ConfirmConfig(cfg *Config) error {
+	return confirmConfig(reflect.ValueOf(*cfg))
+}
+
+func confirmConfig(v reflect.Value) error {
+	for i := 0; i < v.NumField(); i++ {
+		field := v.Field(i)
+		if field.Kind() == reflect.String {
+			if field.String() == "" {
+				return errors.New(fmt.Sprintf("The %s field must not be empty", v.Type().Field(i).Name))
+			}
+		}
+
+		if field.Kind() == reflect.Struct {
+			if err := confirmConfig(field); err != nil {
+				return err
+			}
+		}
+	}
+	return nil
+}
diff --git a/internal/domain/bid.go b/internal/domain/bid.go
new file mode 100644
index 0000000000000000000000000000000000000000..e270606366b21757ee6cafa70d290f40ae32eb9a
--- /dev/null
+++ b/internal/domain/bid.go
@@ -0,0 +1,15 @@
+package domain
+
+import "time"
+
+type Bid struct {
+	ID          string    `json:"id"`
+	Name        string    `json:"name"`
+	Description string    `json:"description"`
+	Status      string    `json:"status"`
+	TenderID    string    `json:"tender_id"`
+	AuthorType  string    `json:"author_type"`
+	AuthorID    string    `json:"author_id"`
+	Version     int       `json:"version"`
+	CreatedAt   time.Time `json:"created_at"`
+}
diff --git a/internal/domain/tender.go b/internal/domain/tender.go
new file mode 100644
index 0000000000000000000000000000000000000000..8170501ec0252338b9bba3a9c2930c3ebf570db5
--- /dev/null
+++ b/internal/domain/tender.go
@@ -0,0 +1,28 @@
+package domain
+
+import "time"
+
+type Tender struct {
+	ID          string    `json:"id"`
+	Name        string    `json:"name"`
+	Description string    `json:"description"`
+	Status      string    `json:"status"`
+	ServiceType string    `json:"service_type"`
+	Version     int       `json:"version"`
+	CreatedAt   time.Time `json:"created_at"`
+}
+
+type TenderCreator struct {
+	Name            string `json:"name"`
+	Description     string `json:"description"`
+	Status          string `json:"status"`
+	ServiceType     string `json:"serviceType"`
+	OrganizationID  string `json:"organizationId"`
+	CreatorUsername string `json:"creatorUsername"`
+}
+
+type TenderEditor struct {
+	Name        string `json:"name"`
+	Description string `json:"description"`
+	ServiceType string `json:"serviceType"`
+}
diff --git a/internal/handler/err.go b/internal/handler/err.go
new file mode 100644
index 0000000000000000000000000000000000000000..d94eb6d9aaa0816b99e125ea334ab198052d457a
--- /dev/null
+++ b/internal/handler/err.go
@@ -0,0 +1,8 @@
+package handler
+
+import "errors"
+
+var (
+	ErrUserIdType      = errors.New("invalid type of user id")
+	ErrUnnknownRequest = errors.New("unknown request")
+)
diff --git a/internal/handler/handler.go b/internal/handler/handler.go
new file mode 100644
index 0000000000000000000000000000000000000000..28ab8dc482fbbfbc07d0b863eebe848643c5dfcf
--- /dev/null
+++ b/internal/handler/handler.go
@@ -0,0 +1,47 @@
+package handler
+
+import (
+	"net/http"
+
+	"github.com/DarRo9/Tenders/internal/service"
+	"github.com/gin-gonic/gin"
+)
+
+const (
+	userIDCtx = "userid"
+)
+
+type Handler struct {
+	service *service.Service
+}
+
+func ping(c *gin.Context) {
+	c.String(http.StatusOK, "ok")
+}
+
+func (h *Handler) MakeRoutes() *gin.Engine {
+	router := gin.New()
+	api := router.Group("/api")
+	{
+		api.GET("/ping", ping)
+
+		tenders := api.Group("/tenders")
+		{
+			tenders.GET("/", h.getTenders)
+			tenders.POST("/new", h.makeTender)
+		}
+
+		tendersWithAuth := api.Group("/tenders", h.userAuth)
+		{
+			tendersWithAuth.GET("/my", h.getUserTenders)
+			tendersWithAuth.GET("/:tenderid/status", h.getStatusTender)
+			tendersWithAuth.PUT("/:tenderid/status", h.setStatusTender)
+		}
+	}
+
+	return router
+}
+
+func MakeHandler(service *service.Service) *Handler {
+	return &Handler{service: service}
+}
diff --git a/internal/handler/middleware.go b/internal/handler/middleware.go
new file mode 100644
index 0000000000000000000000000000000000000000..97dea719095c363b1b2a28b407d0268f40da734b
--- /dev/null
+++ b/internal/handler/middleware.go
@@ -0,0 +1,56 @@
+package handler
+
+import (
+	"net/http"
+
+	"github.com/DarRo9/Tenders/internal/service"
+	"github.com/gin-gonic/gin"
+)
+
+func (h *Handler) userAuth(c *gin.Context) {
+	username := c.DefaultQuery("username", "")
+	if username == "" {
+		c.JSON(http.StatusUnauthorized, gin.H{"cause": service.ErrUnauthorizedError.Error()})
+		return
+	}
+	userUUID, err := h.service.Auth.GetUserId(username)
+	if err != nil {
+		c.JSON(http.StatusUnauthorized, gin.H{"cause": err.Error()})
+		return
+	}
+
+	_, err = h.service.Auth.GetUserChargeId(userUUID)
+	if err != nil {
+		c.JSON(http.StatusForbidden, gin.H{"cause": err.Error()})
+		return
+	}
+
+	c.Set(userIDCtx, userUUID)
+}
+
+func getUserId(c *gin.Context) (string, error) {
+	id, ok := c.Get(userIDCtx)
+	if !ok {
+		return "", service.ErrUserNotFound
+	}
+	idS, ok := id.(string)
+	if !ok {
+		return "", ErrUserIdType
+	}
+	return idS, nil
+}
+
+func (h *Handler) createdUserIdentity(c *gin.Context) {
+	username := c.DefaultQuery("name", "")
+	if username == "" {
+		c.JSON(http.StatusUnauthorized, gin.H{"cause": service.ErrUnauthorizedError.Error()})
+		return
+	}
+	userUUID, err := h.service.Auth.GetUserId(username)
+	if err != nil {
+		c.JSON(http.StatusUnauthorized, gin.H{"cause": err.Error()})
+		return
+	}
+
+	c.Set(userIDCtx, userUUID)
+}
diff --git a/internal/handler/tenders.go b/internal/handler/tenders.go
new file mode 100644
index 0000000000000000000000000000000000000000..21ddc0214b4c1e85a5ccfa080c96cbe3b7991660
--- /dev/null
+++ b/internal/handler/tenders.go
@@ -0,0 +1,162 @@
+package handler
+
+import (
+	"net/http"
+	"strconv"
+
+	"github.com/DarRo9/Tenders/internal/domain"
+	"github.com/gin-gonic/gin"
+)
+
+func (h *Handler) setStatusTender(c *gin.Context) {
+	userUUID, err := getUserId(c)
+	if err != nil {
+		return
+	}
+	tenderid := c.Param("tenderid")
+	if tenderid == "" {
+		c.JSON(http.StatusBadRequest, gin.H{"cause": ErrUnnknownRequest.Error()})
+		return
+	}
+	status, isExist := c.GetQuery("status")
+	if !isExist {
+		c.JSON(http.StatusBadRequest, gin.H{"cause": ErrUnnknownRequest.Error()})
+		return
+	}
+	tender, err := h.service.Tender.UpdateStatusTender(tenderid, status, userUUID)
+	if err != nil {
+		c.JSON(http.StatusNotFound, gin.H{"cause": err.Error()})
+		return
+	}
+
+	c.JSON(http.StatusOK, tender)
+}
+
+func (h *Handler) getStatusTender(c *gin.Context) {
+	userUUID, err := getUserId(c)
+	if err != nil {
+		return
+	}
+
+	tenderid := c.Param("tenderid")
+	if tenderid == "" {
+		c.JSON(http.StatusBadRequest, gin.H{"cause": ErrUnnknownRequest.Error()})
+		return
+	}
+
+	status, err := h.service.Tender.GetStatusTenderByTenderID(tenderid, userUUID)
+	if err != nil {
+		c.JSON(http.StatusNotFound, gin.H{"cause": err.Error()})
+		return
+	}
+	c.String(http.StatusOK, status)
+}
+
+func (h *Handler) editTender(c *gin.Context) {
+	var tenderEditor domain.TenderEditor
+	userUUID, err := getUserId(c)
+	if err != nil {
+		return
+	}
+	tenderid := c.Param("tenderid")
+	if tenderid == "" {
+		c.JSON(http.StatusBadRequest, gin.H{"cause": ErrUnnknownRequest.Error()})
+		return
+	}
+
+	if err := c.BindJSON(&tenderEditor); err != nil {
+		c.JSON(http.StatusBadRequest, gin.H{"cause": err.Error()})
+		return
+	}
+
+	tender, err := h.service.Tender.EditTender(tenderid, userUUID, &tenderEditor)
+	if err != nil {
+		c.JSON(http.StatusNotFound, gin.H{"cause": err.Error()})
+		return
+	}
+	c.JSON(http.StatusOK, tender)
+}
+
+func (h *Handler) getTenders(c *gin.Context) {
+	serviceTypes := c.DefaultQuery("service_type", "")
+	offset, err := strconv.Atoi(c.DefaultQuery("offset", "0"))
+	if err != nil {
+		c.JSON(http.StatusBadRequest, gin.H{"cause": err.Error()})
+		return
+	}
+	limit, err := strconv.Atoi(c.DefaultQuery("limit", "5"))
+	if err != nil {
+		c.JSON(http.StatusBadRequest, gin.H{"cause": err.Error()})
+		return
+	}
+
+	tenders, err := h.service.Tender.GetTenders(limit, offset, serviceTypes)
+	if err != nil {
+		c.JSON(http.StatusBadRequest, gin.H{"cause": err.Error()})
+		return
+	}
+
+	c.JSON(http.StatusOK, tenders)
+}
+
+func (h *Handler) getUserTenders(c *gin.Context) {
+	var tenders []domain.Tender
+
+	userUUID, err := getUserId(c)
+	if err != nil {
+		c.JSON(http.StatusBadRequest, gin.H{"cause": err.Error()})
+		return
+	}
+
+	offset, err := strconv.Atoi(c.DefaultQuery("offset", "0"))
+	if err != nil {
+		c.JSON(http.StatusBadRequest, gin.H{"cause": err.Error()})
+		return
+	}
+	limit, err := strconv.Atoi(c.DefaultQuery("limit", "5"))
+	if err != nil {
+		c.JSON(http.StatusBadRequest, gin.H{"cause": err.Error()})
+		return
+	}
+
+	tenders, err = h.service.Tender.GetTendersByUserUUID(limit, offset, userUUID)
+	if err != nil {
+		c.JSON(http.StatusInternalServerError, gin.H{"cause": err.Error()})
+		return
+	}
+	c.JSON(http.StatusOK, tenders)
+}
+
+func (h *Handler) makeTender(c *gin.Context) {
+	var tenderCreator domain.TenderCreator
+	if err := c.BindJSON(&tenderCreator); err != nil {
+		c.JSON(http.StatusBadRequest, gin.H{"cause": err.Error()})
+		return
+	}
+	userUUID, err := h.service.Auth.GetUserId(tenderCreator.CreatorUsername)
+	if err != nil {
+		c.JSON(http.StatusUnauthorized, gin.H{"cause": err.Error()})
+		return
+	}
+	_, err = h.service.Auth.CheckUserCharge(userUUID, tenderCreator.OrganizationID)
+	if err != nil {
+		c.JSON(http.StatusForbidden, gin.H{"cause": err.Error()})
+		return
+	}
+	var userChargeId string
+
+	if !h.service.Auth.IsUserChargeExist(tenderCreator.CreatorUsername) {
+		userChargeId, err = h.service.Auth.CreateUserCharge(userUUID, tenderCreator.CreatorUsername)
+	} else {
+		userChargeId, err = h.service.Auth.GetUserChargeId(tenderCreator.CreatorUsername)
+	}
+
+	if err != nil {
+		c.JSON(http.StatusBadRequest, gin.H{"cause": err.Error()})
+		return
+	}
+
+	tender, err := h.service.CreateTender(tenderCreator, userChargeId)
+
+	c.JSON(http.StatusOK, tender)
+}
diff --git a/internal/repo/auth.go b/internal/repo/auth.go
new file mode 100644
index 0000000000000000000000000000000000000000..0f671c3019c5789c225240454f71aeaa6811d8fd
--- /dev/null
+++ b/internal/repo/auth.go
@@ -0,0 +1,71 @@
+package repo
+
+import (
+	"context"
+	"database/sql"
+
+	log "github.com/sirupsen/logrus"
+)
+
+type AuthRepo struct {
+	db *sql.DB
+}
+
+func NewAuthRepo(db *sql.DB) *AuthRepo {
+	return &AuthRepo{db: db}
+}
+
+func (a *AuthRepo) GetUserChargeUUID(username string) (string, error) {
+	var uuid string
+	ctx, cancelFn := context.WithTimeout(context.Background(), timeoutCtx)
+	defer cancelFn()
+	query := `SELECT id FROM user_charges WHERE username = $1;`
+	err := a.db.QueryRowContext(ctx, query, username).Scan(&uuid)
+	if err != nil {
+		log.Debugf("%s: %v", ErrUserNotFound, err)
+		return "", ErrUserNotFound
+	}
+
+	return uuid, nil
+}
+
+func (a *AuthRepo) CheckUserCharge(userid, organisationid string) (string, error) {
+	query := `SELECT user_id FROM organization_responsible WHERE user_id = $1 AND organization_id = $2;`
+
+	var uuid string
+	ctx, cancelFn := context.WithTimeout(context.Background(), timeoutCtx)
+	defer cancelFn()
+	err := a.db.QueryRowContext(ctx, query, userid, organisationid).Scan(&uuid)
+	if err != nil {
+		log.Debugf("%s: %v", ErrUserChargeNotFound, err)
+		return "", ErrUserChargeNotFound
+	}
+
+	return uuid, nil
+}
+
+func (a *AuthRepo) GetUserUUID(username string) (string, error) {
+	var uuid string
+	ctx, cancelFn := context.WithTimeout(context.Background(), timeoutCtx)
+	defer cancelFn()
+	query := `SELECT id FROM employee WHERE username = $1;`
+	err := a.db.QueryRowContext(ctx, query, username).Scan(&uuid)
+	if err != nil {
+		log.Debugf("%s: %v", ErrUserNotFound, err)
+		return "", ErrUserNotFound
+	}
+	return uuid, nil
+}
+
+func (a *AuthRepo) CreateUserCharge(userid, username string) (string, error) {
+	var createdUserId string
+	query := `INSERT INTO user_charges(user_id, username) VALUES ($1, $2) RETURNING id;`
+	ctx, cancelFn := context.WithTimeout(context.Background(), timeoutCtx)
+	defer cancelFn()
+	err := a.db.QueryRowContext(ctx, query, userid, username).Scan(&createdUserId)
+	if err != nil {
+		return "", err
+	}
+
+	return createdUserId, nil
+}
diff --git a/internal/repo/err.go b/internal/repo/err.go
new file mode 100644
index 0000000000000000000000000000000000000000..101d0a7fbaefbad68b4c09019977f3c999d08721
--- /dev/null
+++ b/internal/repo/err.go
@@ -0,0 +1,17 @@
+package repo
+
+import "errors"
+
+var (
+	ErrDatabaseConnectionFailed = errors.New("db pdbection failed")
+	ErrUserChargeNotFound       = errors.New("user charge not found")
+	ErrUserNotFound             = errors.New("user not found")
+	ErrCreationTender           = errors.New("can't create tender")
+	ErrScanDataTender           = errors.New("can't scan data tender")
+	ErrTenderNotFound           = errors.New("tender not found")
+	ErrTenderStatusNotFound     = errors.New("tenders status not found")
+	ErrInFailedTransaction      = errors.New("transaction failed")
+	ErrUpdatedTender            = errors.New("updating tender failed")
+	ErrFetchingTender           = errors.New("fetching tender faled")
+	ErrCommittingTransaction    = errors.New("committing tender failed")
+)
diff --git a/internal/repo/postgres.go b/internal/repo/postgres.go
new file mode 100644
index 0000000000000000000000000000000000000000..5793130cebf91e1805b0e1088e48178e4cdb072b
--- /dev/null
+++ b/internal/repo/postgres.go
@@ -0,0 +1,25 @@
+package repo
+
+import (
+	"database/sql"
+
+	"github.com/DarRo9/Tenders/internal/config"
+	_ "github.com/lib/pq"
+	log "github.com/sirupsen/logrus"
+)
+
+func MakeDB(cfg config.Postgres) (*sql.DB, error) {
+	db, err := sql.Open("postgres", cfg.ConnString)
+	if err != nil {
+		log.Fatalf("%s: %v", ErrDatabaseConnectionFailed, err)
+		return nil, ErrDatabaseConnectionFailed
+	}
+
+	err = db.Ping()
+	if err != nil {
+		log.Fatalf("%s: %v", ErrDatabaseConnectionFailed, err)
+		return nil, ErrDatabaseConnectionFailed
+	}
+
+	return db, nil
+}
diff --git a/internal/repo/repo.go b/internal/repo/repo.go
new file mode 100644
index 0000000000000000000000000000000000000000..3527928de75c9a80c59f7d5b1721f56505f1bc25
--- /dev/null
+++ b/internal/repo/repo.go
@@ -0,0 +1,37 @@
+package repo
+
+import (
+	"database/sql"
+
+	"github.com/DarRo9/Tenders/internal/domain"
+)
+
+type Tender interface {
+	CreateTender(tender domain.Tender, orgID, creatorID string) (domain.Tender, error)
+	GetTenders(limit, offset int, serviceType string) ([]domain.Tender, error)
+	GetTendersByUserID(limit, offset int, uuid string) ([]domain.Tender, error)
+	GetStatusTenderById(tenderUUID, userUUID string) (string, error)
+	UpdateStatusTenderById(tenderUUID, status, userUUID string) (domain.Tender, error)
+	UpdateTender(tenderUUID, userUUID string, tenderEditor *domain.TenderEditor) (domain.Tender, error)
+	GetTenderById(tenderUUID string) (domain.Tender, error)
+	//RollbackTender(tenderUUID, userUUID string, version int) (domain.Tender, error)
+}
+
+type Auth interface {
+	CheckUserCharge(userid, organisationid string) (string, error)
+	CreateUserCharge(userid, username string) (string, error)
+	GetUserUUID(username string) (string, error)
+	GetUserChargeUUID(username string) (string, error)
+}
+
+type Repository struct {
+	Auth
+	Tender
+}
+
+func MakeRepo(db *sql.DB) *Repository {
+	return &Repository{
+		Tender: NewTenderRepo(db),
+		Auth:   NewAuthRepo(db),
+	}
+}
diff --git a/internal/repo/tender.go b/internal/repo/tender.go
new file mode 100644
index 0000000000000000000000000000000000000000..d80515e5d184df916e63a3c549c26ec0f34ebfc6
--- /dev/null
+++ b/internal/repo/tender.go
@@ -0,0 +1,334 @@
+package repo
+
+import (
+	"context"
+	"database/sql"
+	"strconv"
+	"time"
+
+	"github.com/DarRo9/Tenders/internal/domain"
+	log "github.com/sirupsen/logrus"
+)
+
+const timeoutCtx = 5 * time.Second
+
+type TenderRepo struct {
+	db *sql.DB
+}
+
+func NewTenderRepo(db *sql.DB) *TenderRepo {
+	return &TenderRepo{db: db}
+}
+
+func (t *TenderRepo) CreateTender(tender domain.Tender, orgID, userUUID string) (domain.Tender, error) {
+	query := `INSERT INTO tenders (name, description, service_type, status, organization_id, creator_id, version) 
+              VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING id`
+	ctx, cancelFn := context.WithTimeout(context.Background(), timeoutCtx)
+	defer cancelFn()
+	var uuid string
+	err := t.db.QueryRowContext(ctx, query,
+		tender.Name,
+		tender.Description,
+		tender.ServiceType,
+		tender.Status,
+		orgID,
+		userUUID,
+		tender.Version).Scan(&uuid)
+
+	if err != nil {
+		log.Debugf("%s: %v", ErrCreationTender, err)
+		return domain.Tender{}, ErrCreationTender
+	}
+	tender.ID = uuid
+	return tender, nil
+}
+
+func (t *TenderRepo) GetStatusTenderById(tenderUUID, userUUID string) (string, error) {
+	var status string
+
+	query := `SELECT status 
+				FROM tenders WHERE creator_id = $1 AND id = $2;`
+
+	ctx, cancelFn := context.WithTimeout(context.Background(), timeoutCtx)
+	defer cancelFn()
+
+	err := t.db.QueryRowContext(ctx, query, userUUID, tenderUUID).Scan(&status)
+	if err != nil {
+		log.Printf("%s: %v", ErrTenderStatusNotFound, err)
+		return "", ErrTenderStatusNotFound
+	}
+
+	return status, nil
+}
+
+func (t *TenderRepo) UpdateStatusTenderById(tenderUUID, status, userUUID string) (domain.Tender, error) {
+	var tender domain.Tender
+	tx, err := t.db.Begin()
+	if err != nil {
+		log.Debugf("%s: %v", ErrInFailedTransaction, err)
+		return domain.Tender{}, ErrInFailedTransaction
+	}
+	ctx, cancelFn := context.WithTimeout(context.Background(), timeoutCtx)
+	defer cancelFn()
+
+	updateStatusQuery := `UPDATE tenders SET status = $1, 
+                   version = COALESCE((SELECT MAX(version) FROM tenders_history WHERE tender_id = $3), 0) + 1 
+               WHERE creator_id = $2 AND id = $3;`
+
+	_, err = tx.ExecContext(ctx, updateStatusQuery, status, userUUID, tenderUUID)
+	if err != nil {
+		tx.Rollback()
+		log.Debugf("%s: %v", ErrUpdatedTender, err)
+		return domain.Tender{}, ErrUpdatedTender
+	}
+
+	getTenderByIdQuery := `SELECT id, name, description, 
+        service_type, status,  
+        version, created_at 
+        FROM tenders WHERE id = $1;`
+
+	err = tx.QueryRowContext(ctx, getTenderByIdQuery, tenderUUID).Scan(
+		&tender.ID,
+		&tender.Name,
+		&tender.Description,
+		&tender.ServiceType,
+		&tender.Status,
+		&tender.Version,
+		&tender.CreatedAt,
+	)
+	if err != nil {
+		tx.Rollback()
+		if err == sql.ErrNoRows {
+			log.Debugf("%s: %v", ErrTenderNotFound, err)
+			return domain.Tender{}, ErrTenderNotFound
+		}
+		log.Debugf("%s: %v", ErrFetchingTender, err)
+		return domain.Tender{}, ErrFetchingTender
+	}
+
+	if err := tx.Commit(); err != nil {
+		log.Debugf("%s: %v", ErrCommittingTransaction, err)
+		return domain.Tender{}, ErrCommittingTransaction
+	}
+
+	return tender, nil
+}
+
+func (t *TenderRepo) GetTenderById(tenderUUID string) (domain.Tender, error) {
+	var tender domain.Tender
+	query := `SELECT id, name, description, 
+       				service_type, status,  
+       				version, created_at 
+			  FROM tenders WHERE id = $1;`
+
+	ctx, cancelFn := context.WithTimeout(context.Background(), timeoutCtx)
+	defer cancelFn()
+	err := t.db.QueryRowContext(ctx, query, tenderUUID).Scan(&tender.ID,
+		&tender.Name,
+		&tender.Description,
+		&tender.ServiceType,
+		&tender.Status,
+		&tender.Version,
+		&tender.CreatedAt)
+	if err != nil {
+		return domain.Tender{}, ErrTenderNotFound
+	}
+
+	return tender, nil
+}
+
+func (t *TenderRepo) GetTenders(limit, offset int, serviceType string) ([]domain.Tender, error) {
+	var tenders []domain.Tender
+
+	query := `SELECT id, name, description, 
+       				service_type, status, 
+       				version, created_at 
+			  FROM tenders`
+
+	params := []interface{}{}
+	paramsIndex := 1
+	if serviceType != "" {
+		query += " WHERE service_type = $" + strconv.Itoa(paramsIndex)
+		params = append(params, serviceType)
+		paramsIndex++
+	}
+	query += " ORDER BY name DESC"
+	query += " LIMIT $" + strconv.Itoa(paramsIndex) + " OFFSET $" + strconv.Itoa(paramsIndex+1)
+	params = append(params, limit, offset)
+
+	ctx, cancelFn := context.WithTimeout(context.Background(), timeoutCtx)
+	defer cancelFn()
+	rows, err := t.db.QueryContext(ctx, query, params...)
+	if err != nil {
+		log.Debugf("%s: %v", ErrTenderNotFound, err)
+		return []domain.Tender{}, ErrTenderNotFound
+	}
+
+	defer rows.Close()
+	for rows.Next() {
+		var tender domain.Tender
+		err = rows.Scan(&tender.ID,
+			&tender.Name,
+			&tender.Description,
+			&tender.ServiceType,
+			&tender.Status,
+			&tender.Version,
+			&tender.CreatedAt)
+
+		if err != nil {
+			log.Debugf("%s: %v", ErrScanDataTender, err)
+			return []domain.Tender{}, ErrScanDataTender
+		}
+		tenders = append(tenders, tender)
+	}
+	return tenders, nil
+}
+
+func (t *TenderRepo) GetTendersByUserID(limit, offset int, uuid string) ([]domain.Tender, error) {
+	var tenders []domain.Tender
+	query := `SELECT id, name, description, 
+       				service_type, status, 
+       				version, created_at 
+				FROM tenders WHERE creator_id = $1 ORDER BY name DESC LIMIT $2 OFFSET $3;`
+
+	ctx, cancelFn := context.WithTimeout(context.Background(), timeoutCtx)
+	defer cancelFn()
+	rows, err := t.db.QueryContext(ctx, query, uuid, limit, offset)
+	if err != nil {
+		log.Debugf("%s: %v", ErrTenderNotFound, err)
+		return []domain.Tender{}, ErrTenderNotFound
+	}
+	defer rows.Close()
+
+	for rows.Next() {
+		var tender domain.Tender
+		err = rows.Scan(&tender.ID,
+			&tender.Name,
+			&tender.Description,
+			&tender.ServiceType,
+			&tender.Status,
+			&tender.Version,
+			&tender.CreatedAt)
+
+		if err != nil {
+			log.Debugf("%s: %v", ErrScanDataTender, err)
+			return []domain.Tender{}, ErrScanDataTender
+		}
+		tenders = append(tenders, tender)
+	}
+
+	return tenders, nil
+}
+
+func (r *TenderRepo) RollbackTender(tenderUUID, userUUID string, version int) (domain.Tender, error) {
+	var tender domain.Tender
+	tx, err := r.db.Begin()
+	if err != nil {
+		log.Debugf("%s: %v", ErrInFailedTransaction, err)
+		return domain.Tender{}, ErrInFailedTransaction
+	}
+	ctx, cancelFn := context.WithTimeout(context.Background(), timeoutCtx)
+	defer cancelFn()
+	query := `UPDATE tenders t SET name = th.name,
+					description = th.description,
+					status = th.status,
+					service_type = th.service_type
+			  FROM (SELECT tender_id, name, description, status, service_type
+				    FROM tenders_history
+				    WHERE tender_id = $1 AND version = $2) th
+			  WHERE t.id = th.tender_id;`
+
+	_, err = tx.ExecContext(ctx, query, tenderUUID, version)
+	if err != nil {
+		tx.Rollback()
+		log.Debugf("%s: %v", ErrTenderNotFound, err)
+		return domain.Tender{}, ErrTenderNotFound
+	}
+	getTenderByIdQuery := `SELECT id, name, description, 
+								service_type, status, 
+						        version, created_at, updated_at 
+						   FROM tenders WHERE id = $1;`
+
+	err = tx.QueryRowContext(ctx, getTenderByIdQuery, tenderUUID).Scan(
+		&tender.ID,
+		&tender.Name,
+		&tender.Description,
+		&tender.ServiceType,
+		&tender.Status,
+		&tender.Version,
+		&tender.CreatedAt,
+	)
+	if err != nil {
+		tx.Rollback()
+		if err == sql.ErrNoRows {
+			log.Debugf("%s: %v", ErrTenderNotFound, err)
+			return domain.Tender{}, ErrTenderNotFound
+		}
+		log.Debugf("%s: %v", ErrFetchingTender, err)
+		return domain.Tender{}, ErrFetchingTender
+	}
+
+	if err = tx.Commit(); err != nil {
+		log.Debugf("%s: %v", ErrCommittingTransaction, err)
+		return domain.Tender{}, ErrCommittingTransaction
+	}
+
+	return tender, nil
+}
+
+func (t *TenderRepo) UpdateTender(tenderUUID, userUUID string, tenderEditor *domain.TenderEditor) (domain.Tender, error) {
+	var tender domain.Tender
+	tx, err := t.db.Begin()
+	if err != nil {
+		log.Debugf("%s: %v", ErrInFailedTransaction, err)
+		return domain.Tender{}, ErrInFailedTransaction
+	}
+	ctx, cancelFn := context.WithTimeout(context.Background(), timeoutCtx)
+	defer cancelFn()
+
+	updateStatusQuery := `UPDATE tenders SET name = $1, description = $2, service_type = $3, version = COALESCE((SELECT MAX(version) FROM tenders_history WHERE tender_id = $4), 0) + 1 
+               WHERE creator_id = $5 AND id = $6;`
+	_, err = tx.ExecContext(ctx,
+		updateStatusQuery, tenderEditor.Name,
+		tenderEditor.Description,
+		tenderEditor.ServiceType,
+		tenderUUID,
+		userUUID, tenderUUID)
+
+	if err != nil {
+		tx.Rollback()
+		log.Debugf("%s: %v", ErrTenderNotFound, err)
+		return domain.Tender{}, ErrTenderNotFound
+	}
+
+	getTenderByIdQuery := `SELECT id, name, description, 
+        service_type, status, 
+        version, created_at, updated_at 
+        FROM tenders WHERE id = $1;`
+
+	err = tx.QueryRowContext(ctx, getTenderByIdQuery, tenderUUID).Scan(
+		&tender.ID,
+		&tender.Name,
+		&tender.Description,
+		&tender.ServiceType,
+		&tender.Status,
+		&tender.Version,
+		&tender.CreatedAt,
+	)
+	if err != nil {
+		tx.Rollback()
+		if err == sql.ErrNoRows {
+			log.Debugf("%s: %v", ErrTenderNotFound, err)
+			return domain.Tender{}, ErrTenderNotFound
+		}
+		log.Debugf("%s: %v", ErrFetchingTender, err)
+		return domain.Tender{}, ErrFetchingTender
+	}
+
+	if err := tx.Commit(); err != nil {
+		log.Debugf("%s: %v", ErrCommittingTransaction, err)
+		return domain.Tender{}, ErrCommittingTransaction
+	}
+
+	return tender, nil
+}
diff --git a/internal/service/auth.go b/internal/service/auth.go
new file mode 100644
index 0000000000000000000000000000000000000000..2a31204e83c549f41f13047514ecf03a0fe71a66
--- /dev/null
+++ b/internal/service/auth.go
@@ -0,0 +1,35 @@
+package service
+
+import "github.com/DarRo9/Tenders/internal/repo"
+
+type AuthService struct {
+	repo *repo.Repository
+}
+
+func (a *AuthService) GetUserChargeId(username string) (string, error) {
+	return a.repo.Auth.GetUserChargeUUID(username)
+}
+
+func (a *AuthService) CheckUserCharge(userUUID, organisationid string) (string, error) {
+	return a.repo.Auth.CheckUserCharge(userUUID, organisationid)
+}
+
+func NewAuthService(repo *repo.Repository) *AuthService {
+	return &AuthService{repo: repo}
+}
+
+func (a *AuthService) GetUserId(username string) (string, error) {
+	return a.repo.Auth.GetUserUUID(username)
+}
+
+func (a *AuthService) IsUserChargeExist(username string) bool {
+	_, err := a.repo.Auth.GetUserChargeUUID(username)
+	if err != nil {
+		return false
+	}
+	return true
+}
+
+func (a *AuthService) CreateUserCharge(userUUID, username string) (string, error) {
+	return a.repo.Auth.CreateUserCharge(userUUID, username)
+}
diff --git a/internal/service/err.go b/internal/service/err.go
new file mode 100644
index 0000000000000000000000000000000000000000..b1645d15828d0148c2f5c3c9d423aeec69abcafb
--- /dev/null
+++ b/internal/service/err.go
@@ -0,0 +1,13 @@
+package service
+
+import (
+	"errors"
+)
+
+var (
+	ErrUserNotFound      = errors.New("user not found")
+	ErrTenderNotFound    = errors.New("tender not found")
+	ErrServiceTypeError  = errors.New("service type error")
+	ErrStatusError       = errors.New("status error")
+	ErrUnauthorizedError = errors.New("unauthorized error")
+)
diff --git a/internal/service/service.go b/internal/service/service.go
new file mode 100644
index 0000000000000000000000000000000000000000..9e39b03cfa26871cad6bf9fe3ec456000a3f8fd2
--- /dev/null
+++ b/internal/service/service.go
@@ -0,0 +1,35 @@
+package service
+
+import (
+	"github.com/DarRo9/Tenders/internal/domain"
+	"github.com/DarRo9/Tenders/internal/repo"
+)
+
+type Tender interface {
+	CreateTender(tenderCreator domain.TenderCreator, userUUID string) (domain.Tender, error)
+	GetTenders(limit, offset int, serviceType string) ([]domain.Tender, error)
+	GetTendersByUserUUID(limit, offset int, userUUID string) ([]domain.Tender, error)
+	GetStatusTenderByTenderID(tenderID, userUUID string) (string, error)
+	UpdateStatusTender(tenderUUID, status, userUUID string) (domain.Tender, error)
+	EditTender(tenderUUID, userUUID string, tenderEditor *domain.TenderEditor) (domain.Tender, error)
+}
+
+type Auth interface {
+	GetUserId(username string) (string, error)
+	GetUserChargeId(username string) (string, error)
+	CheckUserCharge(userUUID, organisationid string) (string, error)
+	CreateUserCharge(userUUID, username string) (string, error)
+	IsUserChargeExist(username string) bool
+}
+
+type Service struct {
+	Auth
+	Tender
+}
+
+func MakeService(repo *repo.Repository) *Service {
+	return &Service{
+		NewAuthService(repo),
+		NewTenderService(repo),
+	}
+}
diff --git a/internal/service/tender.go b/internal/service/tender.go
new file mode 100644
index 0000000000000000000000000000000000000000..ac456d93106ef3bdedcd4cd535ba1ec57a43dbd1
--- /dev/null
+++ b/internal/service/tender.go
@@ -0,0 +1,72 @@
+package service
+
+import (
+	"errors"
+	"time"
+
+	"github.com/DarRo9/Tenders/internal/domain"
+	"github.com/DarRo9/Tenders/internal/repo"
+	log "github.com/sirupsen/logrus"
+)
+
+type TenderService struct {
+	repo *repo.Repository
+}
+
+func NewTenderService(repo *repo.Repository) *TenderService {
+	return &TenderService{repo: repo}
+}
+
+func (t *TenderService) GetTenders(limit, offset int, serviceType string) ([]domain.Tender, error) {
+	return t.repo.Tender.GetTenders(limit, offset, serviceType)
+}
+
+func (t *TenderService) CreateTender(tenderCreator domain.TenderCreator, userUUID string) (domain.Tender, error) {
+	tenderCreator.Status = "Created"
+	if !checkServiceType(tenderCreator.ServiceType) {
+		log.Debugf("%s: %v", ErrStatusError, errors.New("service type not found"))
+		return domain.Tender{}, ErrServiceTypeError
+	}
+
+	var tender domain.Tender
+	tender = t.initTender(tenderCreator)
+	return t.repo.CreateTender(tender, tenderCreator.OrganizationID, userUUID)
+}
+
+func (t *TenderService) initTender(creator domain.TenderCreator) domain.Tender {
+	return domain.Tender{
+		Name:        creator.Name,
+		Description: creator.Description,
+		ServiceType: creator.ServiceType,
+		Status:      creator.Status,
+		Version:     1,
+		CreatedAt:   time.Now(),
+	}
+}
+
+func (t *TenderService) GetTendersByUserUUID(limit, offset int, uuid string) ([]domain.Tender, error) {
+	return t.repo.GetTendersByUserID(limit, offset, uuid)
+}
+
+func (t *TenderService) EditTender(tenderUUID, userUUID string, tenderEditor *domain.TenderEditor) (domain.Tender, error) {
+	if tenderEditor == nil {
+		return t.repo.GetTenderById(tenderUUID)
+	}
+	if !checkServiceType(tenderEditor.ServiceType) {
+		return domain.Tender{}, ErrServiceTypeError
+	}
+
+	return t.repo.UpdateTender(tenderUUID, userUUID, tenderEditor)
+}
+
+func (t *TenderService) GetStatusTenderByTenderID(tenderID, userUUID string) (string, error) {
+	status, err := t.repo.Tender.GetStatusTenderById(tenderID, userUUID)
+	if err != nil {
+		return "", ErrTenderNotFound
+	}
+	return status, nil
+}
+
+func (t *TenderService) UpdateStatusTender(tenderUUID, status, userUUID string) (domain.Tender, error) {
+	return t.repo.UpdateStatusTenderById(tenderUUID, status, userUUID)
+}
diff --git a/internal/service/validation.go b/internal/service/validation.go
new file mode 100644
index 0000000000000000000000000000000000000000..49e49ee82904f48b5a5acf4eb9272ff8512c4e63
--- /dev/null
+++ b/internal/service/validation.go
@@ -0,0 +1,22 @@
+package service
+
+func checkServiceType(serviceType string) bool {
+	serviceTypes := []string{"Construction", "Delivery", "Manufacture"}
+	for _, sT := range serviceTypes {
+		if sT == serviceType {
+			return true
+		}
+	}
+
+	return false
+}
+
+func checkStatus(status string) bool {
+	allStatuses := []string{"Created", "Published", "Closed"}
+	for _, s := range allStatuses {
+		if status == s {
+			return true
+		}
+	}
+	return false
+}
diff --git a/migrations/20240908102818_init.down.sql b/migrations/20240908102818_init.down.sql
new file mode 100644
index 0000000000000000000000000000000000000000..6decd4fd69db99878e620a15d781f129cb23d92d
--- /dev/null
+++ b/migrations/20240908102818_init.down.sql
@@ -0,0 +1,2 @@
+DROP TABLE IF EXISTS bids;
+DROP TABLE IF EXISTS tenders;
diff --git a/migrations/20240908102818_init.up.sql b/migrations/20240908102818_init.up.sql
new file mode 100644
index 0000000000000000000000000000000000000000..4e69c08056cf4a0d800f89a2d36a103030542336
--- /dev/null
+++ b/migrations/20240908102818_init.up.sql
@@ -0,0 +1,70 @@
+CREATE TABLE user_charges (
+                              id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+                              username VARCHAR(50) UNIQUE NOT NULL,
+                              user_id UUID NOT NULL
+);
+
+CREATE TABLE tenders (
+    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+    name VARCHAR(100) NOT NULL,
+    description VARCHAR(500),
+    service_type VARCHAR(50) CHECK (service_type IN ('Construction', 'Delivery', 'Manufacture')),
+    status VARCHAR(20) CHECK (status IN ('Created', 'Published', 'Closed')),
+    organization_id UUID NOT NULL,
+    creator_id UUID NOT NULL REFERENCES user_charges(id) ON DELETE CASCADE,
+    version INT DEFAULT 1 CHECK (version >= 1),
+    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+);
+
+
+
+CREATE TABLE bids (
+    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+    name VARCHAR(100) NOT NULL,
+    description VARCHAR(500),
+    status VARCHAR(20) CHECK (status IN ('Created', 'Published', 'Canceled', 'Approved', 'Rejected')),
+    tender_id UUID REFERENCES tenders(id) ON DELETE CASCADE,
+    author_type VARCHAR(50),
+    author_id UUID,
+    version INT DEFAULT 1 CHECK (version >= 1),
+    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+);
+
+
+
+CREATE TABLE tenders_history (
+    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+    tender_id UUID NOT NULL,
+    name VARCHAR(100) NOT NULL,
+    description VARCHAR(500),
+    service_type VARCHAR(50) CHECK (service_type IN ('Construction', 'Delivery', 'Manufacture')),
+    status VARCHAR(20) CHECK (status IN ('Created', 'Published', 'Closed')),
+    organization_id UUID NOT NULL,
+    creator_id UUID NOT NULL,
+    version INT DEFAULT 1 CHECK (version >= 1),
+    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+);
+
+CREATE OR REPLACE FUNCTION tender_versions()
+RETURNS TRIGGER AS $$
+BEGIN
+    IF (TG_OP = 'INSERT') THEN
+       INSERT INTO tenders_history (tender_id, name, description, service_type, status, organization_id, creator_id)
+       VALUES (NEW.id, NEW.name, NEW.description, NEW.service_type, NEW.status, NEW.organization_id, NEW.creator_id);
+    RETURN NEW;
+    ELSIF (TG_OP = 'UPDATE') THEN
+        INSERT INTO tenders_history (tender_id, name, description, service_type, status, organization_id, creator_id, version, created_at)
+        VALUES (NEW.id, NEW.name, NEW.description, NEW.service_type, NEW.status, NEW.organization_id, NEW.creator_id, NEW.version, NEW.created_at);
+    RETURN NEW;
+END IF;
+END;
+$$
+LANGUAGE plpgsql;
+
+
+CREATE TRIGGER tender_versions_trigger
+    AFTER INSERT OR UPDATE ON tenders
+    FOR EACH ROW
+    EXECUTE PROCEDURE tender_versions();
\ No newline at end of file
diff --git a/pkg/server/server.go b/pkg/server/server.go
new file mode 100644
index 0000000000000000000000000000000000000000..4ea082739c9db6cad7681f09edd2851471def86a
--- /dev/null
+++ b/pkg/server/server.go
@@ -0,0 +1,29 @@
+package server
+
+import (
+	"context"
+	"net/http"
+	"time"
+
+	"github.com/DarRo9/Tenders/internal/config"
+)
+
+type Server struct {
+	httpServer *http.Server
+}
+
+func (s *Server) Start(cfg config.HttpServer, httpHandler http.Handler) error {
+	s.httpServer = &http.Server{
+		Addr:           cfg.Address,
+		Handler:        httpHandler,
+		MaxHeaderBytes: 1 << 20,
+		ReadTimeout:    5 * time.Second,
+		WriteTimeout:   5 * time.Second,
+		IdleTimeout:    10 * time.Second,
+	}
+	return s.httpServer.ListenAndServe()
+}
+
+func (s *Server) Shutdown(ctx context.Context) error {
+	return s.httpServer.Shutdown(ctx)
+}
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..864bc1ce858cd0bbe9c639fa777b535b78bf419b
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,6 @@
+pluginManagement {
+	repositories {
+		gradlePluginPortal()
+	}
+}
+rootProject.name = 'gradle-example'
diff --git a/src/main/java/io/codefresh/gradleexample/GradleExampleApplication.java b/src/main/java/io/codefresh/gradleexample/GradleExampleApplication.java
new file mode 100644
index 0000000000000000000000000000000000000000..e41614137ae15478bc2c81fcc7fc8c93ccc0e9e5
--- /dev/null
+++ b/src/main/java/io/codefresh/gradleexample/GradleExampleApplication.java
@@ -0,0 +1,13 @@
+package io.codefresh.gradleexample;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class GradleExampleApplication {
+
+	public static void main(String[] args) {
+		SpringApplication.run(GradleExampleApplication.class, args);
+	}
+
+}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
new file mode 100644
index 0000000000000000000000000000000000000000..b5d2a9e434a6c67b8b1daf5550ee4ea0dab31f83
--- /dev/null
+++ b/src/main/resources/application.properties
@@ -0,0 +1 @@
+server.servlet.context-path=/
diff --git a/src/main/resources/static/index.html b/src/main/resources/static/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..57b69df28429111acc46e6304efcd0e1cd61161e
--- /dev/null
+++ b/src/main/resources/static/index.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <title>Gradle Docker example</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+</head>
+<body>
+    <p>Hello. I am a Java project, compiled by Gradle running inside Docker</a></p>
+
+    <p>See a quick <a href="actuator/health">status report</a></p>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/test/java/io/codefresh/gradleexample/GradleExampleApplicationTest.java b/src/test/java/io/codefresh/gradleexample/GradleExampleApplicationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..5a881f99bd047e57db4f1fb6f07f14a82d81b4a7
--- /dev/null
+++ b/src/test/java/io/codefresh/gradleexample/GradleExampleApplicationTest.java
@@ -0,0 +1,19 @@
+package io.codefresh.gradleexample;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class GradleExampleApplicationTest {
+
+	@Test
+	public void contextLoads() {
+		assertEquals("Expected correct message","Hello World","Hello "+"World");
+	}
+
+}
diff --git a/test_docker.sh b/test_docker.sh
new file mode 100644
index 0000000000000000000000000000000000000000..4f7f8d3adc707a8bb5de13d5ad68789cf97afae4
--- /dev/null
+++ b/test_docker.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+SERVER_ADDRESS="0.0.0.0:8080"
+POSTGRES_CONN="host=your_host user=your_user password=your_password dbname=your_db sslmode=disable"
+POSTGRES_JDBC_URL="jdbc:postgresql://your_host:your_port/your_db"
+POSTGRES_USERNAME="your_user"
+POSTGRES_PASSWORD="your_password"
+POSTGRES_HOST=""
+POSTGRES_PORT="5432"
+POSTGRES_DATABASE=""
+
+docker run \
+  -e SERVER_ADDRESS="$SERVER_ADDRESS" \
+  -e POSTGRES_CONN="$POSTGRES_CONN" \
+  -e POSTGRES_JDBC_URL="$POSTGRES_JDBC_URL" \
+  -e POSTGRES_USERNAME="$POSTGRES_USERNAME" \
+  -e POSTGRES_PASSWORD="$POSTGRES_PASSWORD" \
+  -e POSTGRES_HOST="$POSTGRES_HOST" \
+  -e POSTGRES_PORT="$POSTGRES_PORT" \
+  -e POSTGRES_DATABASE="$POSTGRES_DATABASE" \
+  avito
\ No newline at end of file
diff --git "a/\320\267\320\260\320\264\320\260\320\275\320\270\320\265/README.md" "b/\320\267\320\260\320\264\320\260\320\275\320\270\320\265/README.md"
new file mode 100644
index 0000000000000000000000000000000000000000..231f71076f0cc1e893349e0920d76a6bdece9c9e
--- /dev/null
+++ "b/\320\267\320\260\320\264\320\260\320\275\320\270\320\265/README.md"
@@ -0,0 +1,473 @@
+# Сервис проведения тендеров
+## Проблема:
+
+Авито — большая компания, в рамках которой пользователи не только продают/покупают товары и услуги, но и предоставляют помощь крупному бизнесу и предприятиям.
+
+Поэтому ребята из Авито решили сделать сервис, который позволит бизнесу создать тендер на оказание каких-либо услуг. А пользователи/другие бизнесы будут предлагать свои выгодные условия для получения данного тендера.
+
+Помогите ребятам из Авито реализовать новое HTTP API!
+
+## Про приложение
+
+### Стек
+- Любой язык программирования
+- Любые библиотеки
+- Postgres
+
+### Настройка приложения производится через переменные окружения
+
+- `SERVER_ADDRESS` — адрес и порт, который будет слушать HTTP сервер при запуске. Пример: 0.0.0.0:8080.
+- `POSTGRES_CONN` — URL-строка для подключения к PostgreSQL в формате postgres://{username}:{password}@{host}:{5432}/{dbname}.
+- `POSTGRES_JDBC_URL` — JDBC-строка для подключения к PostgreSQL в формате jdbc:postgresql://{host}:{port}/{dbname}.
+- `POSTGRES_USERNAME` — имя пользователя для подключения к PostgreSQL.
+- `POSTGRES_PASSWORD` — пароль для подключения к PostgreSQL.
+- `POSTGRES_HOST` — хост для подключения к PostgreSQL (например, localhost).
+- `POSTGRES_PORT` — порт для подключения к PostgreSQL (например, 5432).
+- `POSTGRES_DATABASE` — имя базы данных PostgreSQL, которую будет использовать приложение.
+
+## Основные требования
+### Сущности
+#### Пользователь и организация
+
+Сущности пользователя и организации уже созданы и представлены в базе данных следующим образом:
+
+Пользователь (User):
+
+```sql
+CREATE TABLE employee (
+    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
+    username VARCHAR(50) UNIQUE NOT NULL,
+    first_name VARCHAR(50),
+    last_name VARCHAR(50),
+    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+);
+```
+
+Организация (Organization):
+```sql
+CREATE TYPE organization_type AS ENUM (
+    'IE',
+    'LLC',
+    'JSC'
+);
+
+CREATE TABLE organization (
+    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
+    name VARCHAR(100) NOT NULL,
+    description TEXT,
+    type organization_type,
+    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+);
+
+CREATE TABLE organization_responsible (
+    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
+    organization_id UUID REFERENCES organization(id) ON DELETE CASCADE,
+    user_id UUID REFERENCES employee(id) ON DELETE CASCADE
+);
+```
+
+### API
+Все эндпоинты начинаются с префикса /api.
+
+Обратите внимание, что успешное выполнение запроса GET /api/ping обязательно для начала тестирования приложения.
+
+Все запросы и ответы должны соответствовать структуре и требованиям спецификации Open API, включая статус-коды, ограничения по длине и допустимые символы в строках.
+
+Если запрос не соответствует требованиям, возвращайте статус-код 400. Если же имеется более специфичный код ответа, используйте его.
+
+Если в запросе есть хотя бы один некорректный параметр, весь запрос должен быть отклонён.
+
+### Бизнес-логика
+#### Тендер
+
+Тендеры могут создавать только пользователи от имени своей организации.
+
+Доступные действия с тендером:
+
+- **Создание**:
+
+  - Тендер будет создан.
+
+  - Доступен только ответственным за организацию.
+
+  - Статус: `CREATED`.
+
+- **Публикация**:
+
+  - Тендер становится доступен всем пользователям.
+
+  - Статус: `PUBLISHED`.
+
+- **Закрытие**:
+
+  - Тендер больше не доступен пользователям, кроме ответственных за организацию.
+
+  - Статус: `CLOSED`.
+
+- **Редактирование**:
+
+  - Изменяются характеристики тендера.
+
+  - Увеличивается версия.
+
+#### Предложение
+
+Предложения могут создавать пользователи от имени своей организации.
+
+Предложение связано только с одним тендером. Один пользователь может быть ответственным в одной организации.
+
+Доступные действия с предложениями:
+
+- **Создание**:
+
+  - Предложение будет создано.
+
+  - Доступно только автору и ответственным за организацию.
+
+  - Статус: `CREATED`.
+
+- **Публикация**:
+
+  - Предложение становится доступно ответственным за организацию и автору.
+
+  - Статус: `PUBLISHED`.
+
+- **Отмена**:
+
+  - Виден только автору и ответственным за организацию.
+
+  - Статус: `CANCELED`.
+
+- **Редактирование**:
+
+  - Изменяются характеристики предложения.
+
+  - Увеличивается версия.
+
+- **Согласование/отклонение**:
+
+  - Доступно только ответственным за организацию, связанной с тендером.
+
+  - Решение может быть принято любым ответственным.
+
+  - При согласовании одного предложения, тендер автоматически закрывается.
+
+## Дополнительные требования
+
+1. Расширенный процесс согласования:
+
+   - Если есть хотя бы одно решение reject, предложение отклоняется.
+   
+   - Для согласования предложения нужно получить решения больше или равно кворуму.
+   
+   - Кворум = min(3, количество ответственных за организацию).
+
+3. Просмотр отзывов на прошлые предложения:
+
+   - Ответственный за организацию может просмотреть отзывы на предложения автора, который создал предложение для его тендера.
+
+5. Оставление отзывов на предложение:
+
+   - Ответственный за организацию может оставить отзыв на предложение.
+
+7. Добавить возможность отката по версии (Тендер и Предложение):
+
+   - После отката, считается новой правкой с увеличением версии.
+
+9. Описание конфигурации линтера.
+
+## Тестирование
+
+### 1. Проверка доступности сервера
+- **Эндпоинт:** GET /ping
+- **Цель:** Убедиться, что сервер готов обрабатывать запросы.
+- **Ожидаемый результат:** Статус код 200 и текст "ok".
+
+```yaml
+GET /api/ping
+
+Response:
+
+  200 OK
+
+  Body: ok
+```
+
+### 2. Тестирование функциональности тендеров
+#### Получение списка тендеров
+- **Эндпоинт:** GET /tenders
+- **Описание:** Возвращает список тендеров с возможностью фильтрации по типу услуг.
+- **Ожидаемый результат:** Статус код 200 и корректный список тендеров.
+
+```yaml
+GET /api/tenders
+
+Response:
+
+  200 OK
+
+  Body: [ {...}, {...}, ... ]
+```
+
+#### Создание нового тендера
+- **Эндпоинт:** POST /tenders/new
+- **Описание:** Создает новый тендер с заданными параметрами.
+- **Ожидаемый результат:** Статус код 200 и данные созданного тендера.
+
+```yaml
+POST /api/tenders/new
+
+Request Body:
+
+  {
+
+    "name": "Тендер 1",
+
+    "description": "Описание тендера",
+
+    "serviceType": "Construction",
+
+    "status": "Open",
+
+    "organizationId": 1,
+
+    "creatorUsername": "user1"
+
+  }
+
+Response:
+
+  200 OK
+
+  Body: 
+  
+  { 
+    "id": 1, 
+    "name": "Тендер 1", 
+    "description": "Описание тендера",
+    ...
+  }
+```
+
+#### Получение тендеров пользователя
+- **Эндпоинт:** GET /tenders/my
+- **Описание:** Возвращает список тендеров текущего пользователя.
+- **Ожидаемый результат:** Статус код 200 и список тендеров пользователя.
+
+```yaml
+GET /api/tenders/my?username=user1
+
+Response:
+
+  200 OK
+
+  Body: [ {...}, {...}, ... ]  
+```
+
+#### Редактирование тендера
+- **Эндпоинт:** PATCH /tenders/{tenderId}/edit
+- **Описание:** Изменение параметров существующего тендера.
+- **Ожидаемый результат:** Статус код 200 и обновленные данные тендера.
+
+```yaml
+PATCH /api/tenders/1/edit
+
+Request Body:
+
+  {
+
+    "name": "Обновленный Тендер 1",
+
+    "description": "Обновленное описание"
+
+  }
+
+Response:
+
+  200 OK
+
+  Body: 
+  { 
+    "id": 1, 
+    "name": "Обновленный Тендер 1", 
+    "description": "Обновленное описание",
+    ...
+  }  
+```
+
+#### Откат версии тендера
+- **Эндпоинт:** PUT /tenders/{tenderId}/rollback/{version}
+- **Описание:** Откатить параметры тендера к указанной версии.
+- **Ожидаемый результат:** Статус код 200 и данные тендера на указанной версии.
+
+```yaml
+PUT /api/tenders/1/rollback/2
+
+Response:
+
+  200 OK
+
+  Body: 
+  { 
+    "id": 1, 
+    "name": "Тендер 1 версия 2", 
+    ... 
+  }
+```
+
+### 3. Тестирование функциональности предложений
+#### Создание нового предложения
+- **Эндпоинт:** POST /bids/new
+- **Описание:** Создает новое предложение для существующего тендера.
+- **Ожидаемый результат:** Статус код 200 и данные созданного предложения.
+
+```yaml
+POST /api/bids/new
+
+Request Body:
+
+  {
+
+    "name": "Предложение 1",
+
+    "description": "Описание предложения",
+
+    "status": "Submitted",
+
+    "tenderId": 1,
+
+    "organizationId": 1,
+
+    "creatorUsername": "user1"
+
+  }
+
+Response:
+
+  200 OK
+
+  Body: 
+  { 
+    "id": 1, 
+    "name": "Предложение 1", 
+    "description": "Описание предложения",
+    ...
+  }
+```
+
+#### Получение списка предложений пользователя
+- **Эндпоинт:** GET /bids/my
+- **Описание:** Возвращает список предложений текущего пользователя.
+- **Ожидаемый результат:** Статус код 200 и список предложений пользователя.
+
+```yaml
+GET /api/bids/my?username=user1
+
+Response:
+
+  200 OK
+
+  Body: [ {...}, {...}, ... ]
+  ```
+  
+#### Получение списка предложений для тендера
+- **Эндпоинт:** GET /bids/{tenderId}/list
+- **Описание:** Возвращает предложения, связанные с указанным тендером.
+- **Ожидаемый результат:** Статус код 200 и список предложений для тендера.
+
+```yaml
+GET /api/bids/1/list
+
+Response:
+
+  200 OK
+
+  Body: [ {...}, {...}, ... ]
+  ```
+  
+#### Редактирование предложения
+- **Эндпоинт:** PATCH /bids/{bidId}/edit
+- **Описание:** Редактирование существующего предложения.
+- **Ожидаемый результат:** Статус код 200 и обновленные данные предложения.
+
+```yaml
+PATCH /api/bids/1/edit
+
+Request Body:
+
+  {
+
+    "name": "Обновленное Предложение 1",
+
+    "description": "Обновленное описание"
+
+  }
+
+Response:
+
+  200 OK
+
+  Body: 
+  { 
+    "id": 1, 
+    "name": "Обновленное Предложение 1", 
+    "description": "Обновленное описание",
+    ...,
+  }
+```
+
+#### Откат версии предложения
+- **Эндпоинт:** PUT /bids/{bidId}/rollback/{version}
+- **Описание:** Откатить параметры предложения к указанной версии.
+- **Ожидаемый результат:** Статус код 200 и данные предложения на указанной версии.
+
+```yaml
+PUT /api/bids/1/rollback/2
+
+Response:
+
+  200 OK
+
+  Body: 
+  { 
+    "id": 1, 
+    "name": "Предложение 1 версия 2", 
+    ...
+  }
+```
+
+### 4. Тестирование функциональности отзывов
+#### Просмотр отзывов на прошлые предложения
+- **Эндпоинт:** GET /bids/{tenderId}/reviews
+- **Описание:** Ответственный за организацию может посмотреть прошлые отзывы на предложения автора, который создал предложение для его тендера.
+- **Ожидаемый результат:** Статус код 200 и список отзывов на предложения указанного автора.
+
+```yaml
+GET /api/bids/1/reviews?authorUsername=user2&organizationId=1
+
+Response:
+
+  200 OK
+
+  Body: [ {...}, {...}, ... ]
+```
+
+### Оценивание
+
+
+| Название группы    | Ручки                                  | Баллы | От каких групп зависит |
+| ------------------ | -------------------------------------- | ----- | ---------------------- |
+| 01/ping            | - /ping                                | 1     |                        |
+| 02/tenders/new     | - /tenders/new                         | 2     |                        |
+| 03/tenders/list    | - /tenders<br>- /tenders/my            | 5     | - 02/tenders/new       |
+| 04/tenders/status  | - /tenders/status                      | 3     | - 02/tenders/new       |
+| 05/tenders/version | - /tenders/edit<br>- /tenders/rollback | 6     | - 02/tenders/new       |
+| 06/bids/new        | - /bids/new                            | 2     |                        |
+| 07/bids/decision   | - /bids/submit_decision                | 3/6   | - 06/bids/new          |
+| 08/bids/list       | - /bids/list<br>- /bids/my             | 5     | - 06/bids/new          |
+| 09/bids/status     | - /bids/status                         | 3     | - 06/bids/new          |
+| 10/bids/version    | - /bids/edit<br>- /bids/rollback       | 6     | - 06/bids/new          |
+| 11/bids/feedback   | - /bids/reviews<br>- /bids/feedback    | 7     | - 06/bids/new          |
+
diff --git "a/\320\267\320\260\320\264\320\260\320\275\320\270\320\265/openapi.yml" "b/\320\267\320\260\320\264\320\260\320\275\320\270\320\265/openapi.yml"
new file mode 100644
index 0000000000000000000000000000000000000000..b8e901980f6a627fc5bd7c25b1e1de713e8c099c
--- /dev/null
+++ "b/\320\267\320\260\320\264\320\260\320\275\320\270\320\265/openapi.yml"
@@ -0,0 +1,1132 @@
+openapi: "3.0.1"
+info:
+  title: Tender Management API
+  version: "1.0"
+  description: |
+    API для управления тендерами и предложениями. 
+
+    Основные функции API включают управление тендерами (создание, изменение, получение списка) и управление предложениями (создание, изменение, получение списка).
+servers:
+  - url: http://localhost:8080/api
+    description: Локальный сервер API
+
+paths:
+  /ping:
+    get:
+      summary: Проверка доступности сервера
+      description: |
+        Этот эндпоинт используется для проверки готовности сервера обрабатывать запросы. 
+
+        Чекер программа будет ждать первый успешный ответ и затем начнет выполнение тестовых сценариев.
+      operationId: checkServer
+      responses:
+        "200":
+          description: |
+            Сервер готов обрабатывать запросы, если отвечает "200 OK".
+            Тело ответа не важно, достаточно вернуть "ok".
+          content:
+            text/plain:
+              schema:
+                type: string
+                example: ok
+        "500":
+          description: Сервер не готов обрабатывать запросы, если ответ статусом 500 или любой другой, кроме 200.
+
+  /tenders:
+    get:
+      summary: Получение списка тендеров
+      description: |
+        Список тендеров с возможностью фильтрации по типу услуг.
+
+        Если фильтры не заданы, возвращаются все тендеры.
+      operationId: getTenders
+      parameters:
+        - $ref: "#/components/parameters/paginationLimit"
+        - $ref: "#/components/parameters/paginationOffset"
+        - name: service_type
+          description: |
+            Возвращенные тендеры должны соответствовать указанным видам услуг.
+
+            Если список пустой, фильтры не применяются.
+          in: query
+          schema:
+            type: array
+            items:
+              $ref: "#/components/schemas/tenderServiceType"
+            example:
+              - Construction
+              - Delivery
+      responses:
+        "200":
+          description: Список тендеров, отсортированных по алфавиту по названию.
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  $ref: "#/components/schemas/tender"
+        "400":
+          description: Неверный формат запроса или его параметры.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+
+  /tenders/new:
+    post:
+      summary: Создание нового тендера
+      description: Создание нового тендера с заданными параметрами.
+      operationId: createTender
+      requestBody:
+        description: Данные нового тендера.
+        required: true
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                name:
+                  $ref: "#/components/schemas/tenderName"
+                description:
+                  $ref: "#/components/schemas/tenderDescription"
+                serviceType:
+                  $ref: "#/components/schemas/tenderServiceType"
+                organizationId:
+                  $ref: "#/components/schemas/organizationId"
+                creatorUsername:
+                  $ref: "#/components/schemas/username"
+              required:
+                - name
+                - description
+                - serviceType
+                - organizationId
+                - creatorUsername
+      responses:
+        "200":
+          description: Тендер успешно создан. Сервер присваивает уникальный идентификатор и время создания.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/tender"
+        "401":
+          description: Пользователь не существует или некорректен.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "403":
+          description: Недостаточно прав для выполнения действия.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+
+  /tenders/my:
+    get:
+      summary: Получить тендеры пользователя
+      description: |
+        Получение списка тендеров текущего пользователя.
+
+        Для удобства использования включена поддержка пагинации.
+      operationId: getUserTenders
+      parameters:
+        - $ref: "#/components/parameters/paginationLimit"
+        - $ref: "#/components/parameters/paginationOffset"
+        - name: username
+          in: query
+          schema:
+            $ref: "#/components/schemas/username"
+      responses:
+        "200":
+          description: Список тендеров пользователя, отсортированный по алфавиту.
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  $ref: "#/components/schemas/tender"
+        "401":
+          description: Пользователь не существует или некорректен.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+
+  /tenders/{tenderId}/status:
+    get:
+      summary: Получение текущего статуса тендера
+      description: Получить статус тендера по его уникальному идентификатору.
+      operationId: getTenderStatus
+      parameters:
+        - name: tenderId
+          in: path
+          required: true
+          schema:
+            $ref: "#/components/schemas/tenderId"
+        - name: username
+          in: query
+          schema:
+            $ref: "#/components/schemas/username"
+      responses:
+        "200":
+          description: Текущий статус тендера.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/tenderStatus"
+        "401":
+          description: Пользователь не существует или некорректен.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "403":
+          description: Недостаточно прав для выполнения действия.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "404":
+          description: Тендер не найден.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+    put:
+      summary: Изменение статуса тендера
+      description: Изменить статус тендера по его идентификатору.
+      operationId: updateTenderStatus
+      parameters:
+        - name: tenderId
+          in: path
+          required: true
+          schema:
+            $ref: "#/components/schemas/tenderId"
+        - name: status
+          in: query
+          required: true
+          schema:
+            $ref: "#/components/schemas/tenderStatus"
+        - name: username
+          in: query
+          required: true
+          schema:
+            $ref: "#/components/schemas/username"
+      responses:
+        "200":
+          description: Статус тендера успешно изменен.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/tender"
+        "400":
+          description: Неверный формат запроса или его параметры.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "401":
+          description: Пользователь не существует или некорректен.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "403":
+          description: Недостаточно прав для выполнения действия.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "404":
+          description: Тендер не найден.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+
+  /tenders/{tenderId}/edit:
+    patch:
+      summary: Редактирование тендера
+      description: Изменение параметров существующего тендера.
+      operationId: editTender
+      parameters:
+        - name: tenderId
+          in: path
+          required: true
+          schema:
+            $ref: "#/components/schemas/tenderId"
+        - name: username
+          in: query
+          required: true
+          schema:
+            $ref: "#/components/schemas/username"
+      requestBody:
+        description: |
+          Перечисление параметров и их новых значений для обновления тендера.
+
+          Если значение не передано, оно останется без изменений.
+        required: true
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                name:
+                  $ref: "#/components/schemas/tenderName"
+                description:
+                  $ref: "#/components/schemas/tenderDescription"
+                serviceType:
+                  $ref: "#/components/schemas/tenderServiceType"
+      responses:
+        "200":
+          description: Тендер успешно изменен и возвращает обновленную информацию.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/tender"
+        "400":
+          description: Данные неправильно сформированы или не соответствуют требованиям.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "401":
+          description: Пользователь не существует или некорректен.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "403":
+          description: Недостаточно прав для выполнения действия.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "404":
+          description: Тендер не найден.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+
+  /tenders/{tenderId}/rollback/{version}:
+    put:
+      summary: Откат версии тендера
+      description: Откатить параметры тендера к указанной версии. Это считается новой правкой, поэтому версия инкрементируется.
+      operationId: rollbackTender
+      parameters:
+        - name: tenderId
+          in: path
+          required: true
+          schema:
+            $ref: "#/components/schemas/tenderId"
+        - name: version
+          in: path
+          required: true
+          schema:
+            type: integer
+            format: int32
+            minimum: 1
+          description: Номер версии, к которой нужно откатить тендер.
+        - name: username
+          in: query
+          required: true
+          schema:
+            $ref: "#/components/schemas/username"
+      responses:
+        "200":
+          description: Тендер успешно откатан и версия инкрементирована.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/tender"
+        "400":
+          description: Неверный формат запроса или его параметры.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "401":
+          description: Пользователь не существует или некорректен.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "403":
+          description: Недостаточно прав для выполнения действия.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "404":
+          description: Тендер или версия не найдены.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+
+  /bids/new:
+    post:
+      summary: Создание нового предложения
+      description: Создание предложения для существующего тендера.
+      operationId: createBid
+      requestBody:
+        description: Данные нового предложения.
+        required: true
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                name:
+                  $ref: "#/components/schemas/bidName"
+                description:
+                  $ref: "#/components/schemas/bidDescription"
+                tenderId:
+                  $ref: "#/components/schemas/tenderId"
+                authorType:
+                  $ref: "#/components/schemas/bidAuthorType"
+                authorId:
+                  $ref: "#/components/schemas/bidAuthorId"
+              required:
+                - name
+                - description
+                - tenderId
+                - authorType
+                - authorId
+      responses:
+        "200":
+          description: Предложение успешно создано. Сервер присваивает уникальный идентификатор и время создания.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/bid"
+        "401":
+          description: Пользователь не существует или некорректен.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "403":
+          description: Недостаточно прав для выполнения действия.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "404":
+          description: Тендер не найден.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+
+  /bids/my:
+    get:
+      summary: Получение списка ваших предложений
+      description: |
+        Получение списка предложений текущего пользователя.
+
+        Для удобства использования включена поддержка пагинации.
+      operationId: getUserBids
+      parameters:
+        - $ref: "#/components/parameters/paginationLimit"
+        - $ref: "#/components/parameters/paginationOffset"
+        - name: username
+          in: query
+          schema:
+            $ref: "#/components/schemas/username"
+      responses:
+        "200":
+          description: Список предложений пользователя, отсортированный по алфавиту.
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  $ref: "#/components/schemas/bid"
+        "401":
+          description: Пользователь не существует или некорректен.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+
+  /bids/{tenderId}/list:
+    get:
+      summary: Получение списка предложений для тендера
+      description: Получение предложений, связанных с указанным тендером.
+      operationId: getBidsForTender
+      parameters:
+        - name: tenderId
+          in: path
+          required: true
+          schema:
+            $ref: "#/components/schemas/tenderId"
+        - name: username
+          in: query
+          required: true
+          schema:
+            $ref: "#/components/schemas/username"
+        - $ref: "#/components/parameters/paginationLimit"
+        - $ref: "#/components/parameters/paginationOffset"
+      responses:
+        "200":
+          description: Список предложений, отсортированный по алфавиту.
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  $ref: "#/components/schemas/bid"
+        "400":
+          description: Неверный формат запроса или его параметры.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "401":
+          description: Пользователь не существует или некорректен.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "403":
+          description: Недостаточно прав для выполнения действия.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "404":
+          description: Тендер или предложение не найдено.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+
+  /bids/{bidId}/status:
+    get:
+      summary: Получение текущего статуса предложения
+      description: Получить статус предложения по его уникальному идентификатору.
+      operationId: getBidStatus
+      parameters:
+        - name: bidId
+          in: path
+          required: true
+          schema:
+            $ref: "#/components/schemas/bidId"
+        - name: username
+          in: query
+          required: true
+          schema:
+            $ref: "#/components/schemas/username"
+      responses:
+        "200":
+          description: Текущий статус предложения.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/bidStatus"
+        "401":
+          description: Пользователь не существует или некорректен.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "403":
+          description: Недостаточно прав для выполнения действия.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "404":
+          description: Предложение не найдено.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+    put:
+      summary: Изменение статуса предложения
+      description: Изменить статус предложения по его уникальному идентификатору.
+      operationId: updateBidStatus
+      parameters:
+        - name: bidId
+          in: path
+          required: true
+          schema:
+            $ref: "#/components/schemas/bidId"
+        - name: status
+          in: query
+          required: true
+          schema:
+            $ref: "#/components/schemas/bidStatus"
+        - name: username
+          in: query
+          required: true
+          schema:
+            $ref: "#/components/schemas/username"
+      responses:
+        "200":
+          description: Статус предложения успешно изменен.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/bid"
+        "400":
+          description: Неверный формат запроса или его параметры.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "401":
+          description: Пользователь не существует или некорректен.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "403":
+          description: Недостаточно прав для выполнения действия.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "404":
+          description: Предложение не найдено.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+
+  /bids/{bidId}/edit:
+    patch:
+      summary: Редактирование параметров предложения
+      description: Редактирование существующего предложения.
+      operationId: editBid
+      parameters:
+        - name: bidId
+          in: path
+          required: true
+          schema:
+            $ref: "#/components/schemas/bidId"
+        - name: username
+          in: query
+          required: true
+          schema:
+            $ref: "#/components/schemas/username"
+      requestBody:
+        description: |
+          Перечисление параметров и их новых значений для обновления предложения.
+
+          Если значение не передано, оно останется без изменений.
+        required: true
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                name:
+                  $ref: "#/components/schemas/bidName"
+                description:
+                  $ref: "#/components/schemas/bidDescription"
+      responses:
+        "200":
+          description: Предложение успешно изменено и возвращает обновленную информацию.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/bid"
+        "400":
+          description: Данные неправильно сформированы или не соответствуют требованиям.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "401":
+          description: Пользователь не существует или некорректен.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "403":
+          description: Недостаточно прав для выполнения действия.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "404":
+          description: Предложение не найдено.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+
+  /bids/{bidId}/submit_decision:
+    put:
+      summary: Отправка решения по предложению
+      description: Отправить решение (одобрить или отклонить) по предложению.
+      operationId: submitBidDecision
+      parameters:
+        - name: bidId
+          in: path
+          required: true
+          schema:
+            $ref: "#/components/schemas/bidId"
+        - name: decision
+          in: query
+          required: true
+          schema:
+            $ref: "#/components/schemas/bidDecision"
+        - name: username
+          in: query
+          required: true
+          schema:
+            $ref: "#/components/schemas/username"
+      responses:
+        "200":
+          description: Решение по предложению успешно отправлено.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/bid"
+        "400":
+          description: Решение не может быть отправлено.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "401":
+          description: Пользователь не существует или некорректен.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "403":
+          description: Недостаточно прав для выполнения действия.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "404":
+          description: Предложение не найдено.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+
+  /bids/{bidId}/feedback:
+    put:
+      summary: Отправка отзыва по предложению
+      description: Отправить отзыв по предложению.
+      operationId: submitBidFeedback
+      parameters:
+        - name: bidId
+          in: path
+          required: true
+          schema:
+            $ref: "#/components/schemas/bidId"
+        - name: bidFeedback
+          in: query
+          required: true
+          schema:
+            $ref: "#/components/schemas/bidFeedback"
+        - name: username
+          in: query
+          required: true
+          schema:
+            $ref: "#/components/schemas/username"
+      responses:
+        "200":
+          description: Отзыв по предложению успешно отправлен.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/bid"
+        "400":
+          description: Отзыв не может быть отправлен.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "401":
+          description: Пользователь не существует или некорректен.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "403":
+          description: Недостаточно прав для выполнения действия.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "404":
+          description: Предложение не найдено.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+
+  /bids/{bidId}/rollback/{version}:
+    put:
+      summary: Откат версии предложения
+      description: Откатить параметры предложения к указанной версии. Это считается новой правкой, поэтому версия инкрементируется.
+      operationId: rollbackBid
+      parameters:
+        - name: bidId
+          in: path
+          required: true
+          schema:
+            $ref: "#/components/schemas/bidId"
+        - name: version
+          in: path
+          required: true
+          schema:
+            type: integer
+            format: int32
+            minimum: 1
+          description: Номер версии, к которой нужно откатить предложение.
+        - name: username
+          in: query
+          required: true
+          schema:
+            $ref: "#/components/schemas/username"
+      responses:
+        "200":
+          description: Предложение успешно откатано и версия инкрементирована.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/bid"
+        "400":
+          description: Неверный формат запроса или его параметры.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "401":
+          description: Пользователь не существует или некорректен.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "403":
+          description: Недостаточно прав для выполнения действия.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "404":
+          description: Предложение или версия не найдены.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+
+  /bids/{tenderId}/reviews:
+    get:
+      summary: Просмотр отзывов на прошлые предложения
+      description: Ответственный за организацию может посмотреть прошлые отзывы на предложения автора, который создал предложение для его тендера.
+      operationId: getBidReviews
+      parameters:
+        - name: tenderId
+          in: path
+          required: true
+          schema:
+            $ref: "#/components/schemas/tenderId"
+        - name: authorUsername
+          in: query
+          required: true
+          schema:
+            $ref: "#/components/schemas/username"
+          description: Имя пользователя автора предложений, отзывы на которые нужно просмотреть.
+        - name: requesterUsername
+          in: query
+          required: true
+          schema:
+            $ref: "#/components/schemas/username"
+          description: Имя пользователя, который запрашивает отзывы.
+        - $ref: "#/components/parameters/paginationLimit"
+        - $ref: "#/components/parameters/paginationOffset"
+      responses:
+        "200":
+          description: Список отзывов на предложения указанного автора.
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  $ref: "#/components/schemas/bidReview"
+        "400":
+          description: Неверный формат запроса или его параметры.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "401":
+          description: Пользователь не существует или некорректен.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "403":
+          description: Недостаточно прав для выполнения действия.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+        "404":
+          description: Тендер или отзывы не найдены.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/errorResponse"
+
+components:
+  schemas:
+    username:
+      type: string
+      description: Уникальный slug пользователя.
+      example: test_user
+    tenderStatus:
+      type: string
+      description: Статус тендер
+      enum:
+        - Created
+        - Published
+        - Closed
+    tenderServiceType:
+      type: string
+      description: Вид услуги, к которой относиться тендер
+      enum:
+        - Construction
+        - Delivery
+        - Manufacture
+    tenderId:
+      type: string
+      description: Уникальный идентификатор тендера, присвоенный сервером.
+      example: 550e8400-e29b-41d4-a716-446655440000
+      maxLength: 100
+    tenderName:
+      type: string
+      description: Полное название тендера
+      maxLength: 100
+    tenderDescription:
+      type: string
+      description: Описание тендера
+      maxLength: 500
+    tenderVersion:
+      type: integer
+      description: Номер версии посел правок
+      format: int32
+      minimum: 1
+      default: 1
+    organizationId:
+      type: string
+      description: Уникальный идентификатор организации, присвоенный сервером.
+      example: 550e8400-e29b-41d4-a716-446655440000
+      maxLength: 100
+    tender:
+      type: object
+      description: Информация о тендере
+      properties:
+        id:
+          $ref: "#/components/schemas/tenderId"
+        name:
+          $ref: "#/components/schemas/tenderName"
+        description:
+          $ref: "#/components/schemas/tenderDescription"
+        serviceType:
+          $ref: "#/components/schemas/tenderServiceType"
+        status:
+          $ref: "#/components/schemas/tenderStatus"
+        organizationId:
+          $ref: "#/components/schemas/organizationId"
+        version:
+          $ref: "#/components/schemas/tenderVersion"
+        createdAt:
+          type: string
+          description: |
+            Серверная дата и время в момент, когда пользователь отправил тендер на создание.
+            Передается в формате RFC3339.
+          example: 2006-01-02T15:04:05Z07:00
+        
+      required:
+        - id
+        - name
+        - description
+        - serviceType
+        - status
+        - organizationId
+        - version
+        - createdAt
+      example:
+        id: 550e8400-e29b-41d4-a716-446655440000
+        name: Доставка товары Казань - Москва
+        description: Нужно доставить оборудовоние для олимпиады по робототехники
+        status: Created
+        serviceType: Delivery
+        version: 1
+        createdAt: 2006-01-02T15:04:05Z07:00
+    bidStatus:
+      type: string
+      description: Статус предложения
+      enum:
+        - Created
+        - Published
+        - Canceled
+    bidDecision:
+      type: string
+      description: Решение по предложению
+      enum:
+        - Approved
+        - Rejected
+    bidId:
+      type: string
+      description: Уникальный идентификатор предложения, присвоенный сервером.
+      example: 550e8400-e29b-41d4-a716-446655440000
+      maxLength: 100
+    bidName:
+      type: string
+      description: Полное название предложения
+      maxLength: 100
+    bidDescription:
+      type: string
+      description: Описание предложения
+      maxLength: 500
+    bidFeedback:
+      type: string
+      description: Отзыв на предложение
+      maxLength: 1000
+    bidAuthorType:
+      type: string
+      description: Тип автора
+      enum:
+        - Organization
+        - User
+    bidAuthorId:
+      type: string
+      description: Уникальный идентификатор автора предложения, присвоенный сервером.
+      example: 550e8400-e29b-41d4-a716-446655440000
+      maxLength: 100
+    bidVersion:
+      type: integer
+      description: Номер версии посел правок
+      format: int32
+      minimum: 1
+      default: 1
+    bidReviewId: 
+      type: string
+      description: Уникальный идентификатор отзыва, присвоенный сервером.
+      example: 550e8400-e29b-41d4-a716-446655440000
+      maxLength: 100
+    bidReviewDescription:
+      type: string
+      description: Описание предложения
+      maxLength: 1000
+      
+    bidReview:
+      type: object
+      description: Отзыв о предложении
+      properties:
+        id:
+          $ref: "#/components/schemas/bidReviewId"
+        description:
+          $ref: "#/components/schemas/bidReviewDescription"
+        createdAt:
+          type: string
+          description: |
+            Серверная дата и время в момент, когда пользователь отправил отзыв на предложение.
+            Передается в формате RFC3339.
+          example: 2006-01-02T15:04:05Z07:00
+        
+      required:
+        - id
+        - description
+        - createdAt
+      example:
+        id: 550e8400-e29b-41d4-a716-446655440000
+        description: All gooood!!!!
+        createdAt: 2006-01-02T15:04:05Z07:00
+    bid:
+      type: object
+      description: Информация о предложении
+      properties:
+        id:
+          $ref: "#/components/schemas/bidId"
+        name:
+          $ref: "#/components/schemas/bidName"
+        description:
+          $ref: "#/components/schemas/bidDescription"
+        status:
+          $ref: "#/components/schemas/bidStatus"
+        tenderId:
+          $ref: "#/components/schemas/tenderId"
+        authorType:
+          $ref: "#/components/schemas/bidAuthorType"
+        authorId:
+          $ref: "#/components/schemas/bidAuthorId"
+        version:
+          $ref: "#/components/schemas/bidVersion"
+        createdAt:
+          type: string
+          description: |
+            Серверная дата и время в момент, когда пользователь отправил предложение на создание.
+            Передается в формате RFC3339.
+          example: 2006-01-02T15:04:05Z07:00
+        
+      required:
+        - id
+        - name
+        - description
+        - status
+        - tenderId
+        - createdAt
+        - authorType
+        - authorId
+        - version
+      example:
+        id: 550e8400-e29b-41d4-a716-446655440000
+        name: Доставка товаров Алексей
+        status: Created
+        authorType: User
+        authorId: 61a485f0-e29b-41d4-a716-446655440000
+        version: 1
+        createdAt: 2006-01-02T15:04:05Z07:00
+        
+    errorResponse:
+      type: object
+      description: Используется для возвращения ошибки пользователю
+      properties:
+        reason:
+          type: string
+          description: Описание ошибки в свободной форме
+          minLength: 5
+      required:
+        - reason
+      example:
+        reason: <объяснение, почему запрос пользователя не может быть обработан>
+  parameters:
+    paginationLimit:
+      in: query
+      name: limit
+      required: false
+      description: |
+        Максимальное число возвращаемых объектов. Используется для запросов с пагинацией.
+
+        Сервер должен возвращать максимальное допустимое число объектов.
+      schema:
+        type: integer
+        format: int32
+        minimum: 0
+        maximum: 50
+        default: 5
+    paginationOffset:
+      in: query
+      name: offset
+      required: false
+      description: |
+        Какое количество объектов должно быть пропущено с начала. Используется для запросов с пагинацией.
+      schema:
+        type: integer
+        format: int32
+        default: 0
+        minimum: 0