REST-сервис для управления продавцами, транзакциями и базовой аналитикой продаж.
Проект выполнен на Java 17, Spring Boot 3, JDBI, PostgreSQL, Gradle, Docker.
- Управление продавцами (
Seller):- создание продавца;
- получение списка активных продавцов;
- получение продавца по
id; - обновление данных продавца;
- выборка продавцов с продажами ниже порога.
- Управление транзакциями (
Transaction):- создание транзакции;
- получение транзакции по
id; - получение списка всех транзакций;
- получение транзакций конкретного продавца.
- Аналитика:
- лучший продавец за период;
- наиболее продуктивный временной промежуток продавца.
- Централизованная обработка ошибок через
@ControllerAdvice. - SQL-инициализация схемы БД при старте (
schema.sql). - Unit/Web/Integration тесты (Spring Test, JUnit 5, Mockito, H2).
Java 17Spring Boot 3.5.14Spring WebSpring JDBCJDBI 3.45.0(jdbi3-spring5,jdbi3-sqlobject,jdbi3-postgres)PostgreSQL 15Gradle 8Docker,docker-composeJUnit 5,Mockito,Spring Boot TestH2(для тестов)
Ключевые зависимости определены в build.gradle:
org.springframework.boot:spring-boot-starter-weborg.springframework.boot:spring-boot-starter-jdbcorg.jdbi:jdbi3-spring5:3.45.0org.jdbi:jdbi3-sqlobject:3.45.0org.jdbi:jdbi3-postgres:3.45.0org.postgresql:postgresql(runtime)com.h2database:h2(runtime/test)org.springframework.boot:spring-boot-starter-test
- Установлен и запущен Docker.
Из корня проекта выполните:
docker-compose up --buildПосле запуска доступны:
- API:
http://localhost:8080 - PostgreSQL:
localhost:5432
Параметры БД (из docker-compose.yml):
- DB:
crm_db - User:
user - Password:
password
docker-compose downJDK 17- локальный
PostgreSQL(или другой доступный инстанс)
- Создайте БД
crm_db. - Проверьте параметры подключения в
src/main/resources/application.properties:spring.datasource.url=jdbc:postgresql://localhost:5432/crm_dbspring.datasource.username=userspring.datasource.password=password
- Схема создастся автоматически при старте приложения (
spring.sql.init.mode=always).
Windows (PowerShell):
.\gradlew.bat bootRunLinux/macOS:
./gradlew bootRunСборка JAR:
Windows:
.\gradlew.bat clean bootJarLinux/macOS:
./gradlew clean bootJarАртефакт будет в build/libs/.
Локально:
Windows:
.\gradlew.bat testLinux/macOS:
./gradlew testЧерез Docker-сервис tester:
docker-compose run --rm testerБазовый URL: http://localhost:8080
- Method:
POST - URL:
http://localhost:8080/api/sellers - Body (JSON):
{
"name": "Михаил Бобиков",
"contactInfo": "misha@example.com"
}- Method:
GET - URL:
http://localhost:8080/api/sellers
- Method:
GET - URL:
http://localhost:8080/api/sellers/1
- Method:
PUT - URL:
http://localhost:8080/api/sellers/1 - Body (JSON):
{
"name": "Михаил Новый",
"contactInfo": "new_misha@example.com"
}- Method:
DELETE - URL:
http://localhost:8080/api/sellers/1
- Method:
GET - URL:
http://localhost:8080/api/sellers/low-sales?threshold=1000
- Method:
POST - URL:
http://localhost:8080/api/transactions - Body (JSON):
{
"sellerId": 1,
"amount": 5000,
"paymentType": "CARD"
}- Method:
GET - URL:
http://localhost:8080/api/transactions
- Method:
GET - URL:
http://localhost:8080/api/transactions/1
- Method:
GET - URL:
http://localhost:8080/api/transactions/seller/1
- Method:
GET - URL:
http://localhost:8080/api/transactions/best-seller?start=2026-01-01T00:00:00&end=2026-12-31T23:59:59
- Method:
GET - URL:
http://localhost:8080/api/transactions/seller/1/productive-hour
В проекте есть готовая коллекция:
- Файл:
CRM_Full_API_Test.json - Название коллекции:
CRM System Final Testing
Как импортировать:
- Откройте Postman.
- Нажмите
Import. - Выберите файл
CRM_Full_API_Test.json. - Запустите приложение.
- Выполняйте запросы по группам:
Sellers->Transactions->Analytics.
contextLoads()— тест запуска Spring-контекста приложения.
getAllSellers_SHOULD_ReturnListAndOkStatus()— проверяетGET /api/sellers: код200, JSON-ответ и список продавцов.createSeller_SHOULD_ReturnCreatedStatus()— проверяетPOST /api/sellers: код201и вызовsellerService.createSeller(...).deleteSeller_SHOULD_ReturnNoContent()— проверяетDELETE /api/sellers/{id}: код204и вызовsellerService.deleteSeller(id).
createTransaction_SHOULD_ReturnCreated()— проверяетPOST /api/transactions: код201и вызовtransactionService.createTransaction(...).getBestSeller_SHOULD_ReturnSellerInfo()— проверяетGET /api/transactions/best-seller: код200и корректные данные лучшего продавца.getProductiveHour_SHOULD_ReturnInteger()— проверяетGET /api/transactions/seller/{id}/productive-hour: код200и числовой час в ответе.
createSeller_EXPECT_AutoSetRegistrationDate()— проверяет автозаполнениеregistrationDate, если дата не задана.createSeller_EXPECT_InvokeRepositoryInsert()— проверяет, что при создании продавца вызываетсяsellerRepository.insert(...).deleteSeller_EXPECT_InvokeRepositoryDelete()— проверяет, что удаление продавца делегируется вsellerRepository.delete(...).
createTransaction_EXPECT_AutoSetTransactionDate()— проверяет автозаполнениеtransactionDateпри создании транзакции.getBestSeller_EXPECT_ReturnSellerFromRepository()— проверяет, что сервис возвращает лучшего продавца из репозитория.getMostProductiveHour_EXPECT_ReturnCorrectHourValue()— проверяет корректность значения продуктивного часа.getSellersWithLowSales_EXPECT_ReturnFilteredList()— проверяет фильтрацию продавцов с низкими продажами.getBestSeller_EXPECT_PassCorrectDatesToRepository()— проверяет передачу корректного диапазона дат в репозиторий.
insertSeller_EXPECT_GeneratedIdInH2()— проверяет, что при вставке продавца в H2 генерируется ID.findSellersWithSalesLessThan_EXPECT_CorrectFilteringInH2()— проверяет SQL-фильтрацию продавцов по сумме продаж.findBestSeller_EXPECT_CorrectChampionInH2()— проверяет SQL-логику выбора лучшего продавца за период.findMostProductiveHour_EXPECT_CorrectHourValueInH2()— проверяет вычисление самого продуктивного часа продавца.findAll_EXPECT_ReturnAllNonDeletedSellers()— проверяет, чтоfindAll()возвращает активных (не удаленных) продавцов.deleteById_EXPECT_SellerIsMarkedAsDeleted()— проверяет soft delete: продавец скрывается из активных и получаетis_deleted=true.
Глобальный обработчик GlobalExceptionHandler возвращает единый JSON-ответ с полями:
statuserrormessagedetails(для части ошибок)
Обрабатываются, в том числе:
- ошибки БД (
UnableToExecuteStatementException); - неверные типы query/path параметров (
MethodArgumentTypeMismatchException); - некорректный JSON (
HttpMessageNotReadableException); - не найденные сущности (
NullPointerException->404).
idnamecontactInforegistrationDateisDeleted
idsellerIdamountpaymentTypetransactionDate
src/main/java/.../controller— REST-контроллерыsrc/main/java/.../service— бизнес-логикаsrc/main/java/.../repository— SQL-репозитории на JDBIsrc/main/java/.../entity— моделиsrc/main/java/.../exception— обработка ошибокsrc/main/resources/schema.sql— SQL-схемаsrc/test/java— тесты
- Удаление продавца реализовано как soft delete (
is_deleted=true). - В Docker-образе приложения тесты при сборке пропускаются (
bootJar -x test).