- Python 68.4%
- JavaScript 18.9%
- HTML 6.7%
- CSS 5.9%
- Dockerfile 0.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| docs | ||
| src | ||
| .gitignore | ||
| docker-compose.yml | ||
| Dockerfile | ||
| local_settings_template.py | ||
| README.md | ||
| requirements.txt | ||
| settings.py | ||
| test.py | ||
МиСПрИС API
REST API для классификатора комплектующих ПК и серверов на FastAPI и PostgreSQL.
Что реализовано
- хранение дерева категорий в таблице
categories; - хранение конечных комплектующих в таблице
products; - хранение справочника уникальных характеристик в таблице
specifications; - хранение справочника единиц измерения в таблице
measurement_units; - хранение справочника параметров изделий в таблице
parameters; - хранение классификаторов в таблице
enumerations; - хранение значений классификаторов в таблице
enumeration_values; - связь many-to-many между товарами и характеристиками через
product_specifications; - создание, изменение, удаление и перемещение категорий;
- создание, изменение, удаление и перемещение товаров;
- создание, изменение, удаление перечислений и их значений;
- добавление одних перечислений внутрь других перечислений;
- получение полного дерева классификатора через API;
- переиспользование спецификаций по
idили автоматическое создание новых; - Swagger UI для тестирования запросов.
Структура БД
Сервис использует фиксированную схему:
categoriesхранит категории классификатора и ссылки на родительские категории;productsхранит конечные комплектующие;specificationsхранит уникальные характеристики в форматеname + valueилиname + enum_value_id;measurement_unitsхранит единицы измерения: полное название, сокращенное название и описание;parametersхранит метаданные параметров изделий: код, название, тип, единицу измерения или перечисление;category_parametersхранит состав параметров классов изделий, порядок, обязательность и числовые ограничения;product_parameter_valuesхранит значения параметров конкретных изделий в отдельных полях по типам;enumerationsхранит сами классификаторы;enumeration_valuesхранит конечные значения классификаторов и ссылки на вложенные перечисления;product_specificationsхранит связи между товарами и характеристиками.
Запуск
Через Docker
docker compose up --build
После запуска будут доступны:
- API:
http://localhost:8000 - Swagger UI:
http://localhost:8000/docs - ReDoc:
http://localhost:8000/redoc
Локально
Нужен PostgreSQL с параметрами из local_settings.py.
Установка зависимостей:
pip install -r requirements.txt
Запуск:
uvicorn src.main:app --reload
Основные эндпоинты
Служебные
GET /info/ping— проверка доступности APIGET /database/info— краткая информация о БДPOST /database/tables/create— явное создание таблиц и подготовка корня
Категории
GET /database/categories— получить список категорийGET /database/categories/{category_id}— получить категориюPOST /database/categories— создать категориюPATCH /database/categories/{category_id}— переименовать категориюPATCH /database/categories/{category_id}/move— переместить категориюDELETE /database/categories/{category_id}— удалить категорию
Пример создания категории:
{
"name": "Процессоры для ПК",
"parent_id": 2
}
Если parent_id не передан, категория создается под корнем.
Товары
GET /database/products— получить список товаровGET /database/products/{product_id}— получить товарPOST /database/products— создать товарPATCH /database/products/{product_id}— изменить товарPATCH /database/products/{product_id}/move— переместить товарDELETE /database/products/{product_id}— удалить товар
Пример создания товара:
{
"category_id": 7,
"name": "AMD Ryzen 7 5700X, AM4, OEM",
"price": 14990,
"quantity": 7,
"description": "Процессор для ПК",
"specifications": [
{ "name": "socket", "value": "AM4" },
{ "name": "form_factor", "value": "OEM" }
]
}
Спецификации
GET /database/specifications— получить справочник всех уникальных спецификаций
Единицы измерения
GET /database/measurement-units— получить список единиц измеренияPOST /database/measurement-units— создать единицу измеренияGET /database/measurement-units/{unit_id}— получить единицу измеренияPATCH /database/measurement-units/{unit_id}— изменить единицу измеренияDELETE /database/measurement-units/{unit_id}— удалить единицу измерения
Пример создания единицы измерения:
{
"full_name": "нанометры",
"short_name": "нм",
"description": "Единица измерения длины"
}
Параметры изделий
GET /database/parameters— получить список параметровPOST /database/parameters— создать параметрGET /database/parameters/{parameter_id}— получить параметрPATCH /database/parameters/{parameter_id}— изменить параметрDELETE /database/parameters/{parameter_id}— удалить параметр
Пример числового параметра:
{
"code": "tech_process",
"name": "Техпроцесс",
"description": "Технологический процесс производства",
"parameter_type": "integer",
"unit_id": 1,
"enum_id": null
}
Пример параметра-перечисления:
{
"code": "socket",
"name": "Сокет",
"description": "Процессорный разъем",
"parameter_type": "enum",
"unit_id": null,
"enum_id": 1
}
Параметры категорий
GET /database/categories/{category_id}/parameters— получить параметры категорииPOST /database/categories/{category_id}/parameters— назначить параметр категорииPATCH /database/category-parameters/{category_parameter_id}— изменить настройки параметра категорииDELETE /database/category-parameters/{category_parameter_id}— удалить параметр из категорииPOST /database/categories/{category_id}/parameters/copy-from-parent— скопировать параметры родителя
Пример назначения числового параметра категории:
{
"parameter_id": 1,
"priority": 10,
"is_required": true,
"min_value": 1,
"max_value": 100
}
Значения параметров изделий
GET /database/products/{product_id}/parameters— получить значения параметров изделияPUT /database/products/{product_id}/parameters/{parameter_id}— записать или обновить значение параметра изделияDELETE /database/products/{product_id}/parameters/{parameter_id}— удалить значение параметра изделияGET /database/categories/{category_id}/products-with-parameters— получить изделия категории со значениями параметровPOST /database/categories/{category_id}/products/search— отфильтровать изделия категории по значениям параметров
Пример целочисленного значения:
{
"val_int": 8
}
Пример вещественного значения:
{
"val_real": 3.5
}
Пример значения-перечисления:
{
"enum_value_id": 1
}
Пример фильтрации по числовому параметру:
{
"filters": [
{
"parameter_id": 2,
"operator": "gte",
"val_int": 8
}
]
}
Пример фильтрации по перечислению:
{
"filters": [
{
"parameter_id": 1,
"operator": "eq",
"enum_value_id": 3
}
]
}
Пример ответа:
[
{
"id": 1,
"name": "tech_process",
"value": "3",
"enum_value_id": null,
"unit_id": 1,
"custom_unit_full_name": null,
"custom_unit_short_name": null
}
]
При создании или обновлении товара спецификацию можно передать тремя способами.
- Как новую или переиспользуемую пару
name/value:
{
"name": "socket",
"value": "AM4"
}
Спецификация со ссылкой на единицу измерения из справочника:
{
"name": "tech_process",
"value": "3",
"unit_id": 1
}
Спецификация с частной единицей измерения, которая не добавляется в общий справочник:
{
"name": "custom_length",
"value": "12",
"custom_unit_full_name": "условные единицы",
"custom_unit_short_name": "у.е."
}
- Как новую или переиспользуемую пару
name/enum_value_id, если значение берется из классификатора:
{
"name": "form_factor",
"enum_value_id": 3
}
- Как ссылку на уже существующую запись справочника:
{
"specification_id": 1
}
Пример товара с переиспользуемой спецификацией:
{
"category_id": 7,
"name": "AMD Ryzen 9 7900",
"price": 32000,
"quantity": 4,
"description": "Процессор для ПК",
"specifications": [
{ "specification_id": 1 },
{ "name": "cores", "value": "12" },
{ "name": "form_factor", "enum_value_id": 3 }
]
}
Перечисления
GET /database/enumerations— получить список перечисленийPOST /database/enumerations— создать перечислениеGET /database/enumerations/{enumeration_id}— получить перечисление вместе со значениямиPATCH /database/enumerations/{enumeration_id}— изменить перечислениеDELETE /database/enumerations/{enumeration_id}— удалить перечислениеGET /database/enumerations/{enumeration_id}/values— получить значения перечисленияPOST /database/enumerations/{enumeration_id}/values— добавить конечное значение или вложенное перечислениеPATCH /database/enumeration-values/{value_id}— изменить элемент перечисленияDELETE /database/enumeration-values/{value_id}— удалить элемент перечисления
Пример создания перечисления:
{
"name": "Форматы материнских плат",
"description": "Допустимые форм-факторы материнских плат"
}
Пример добавления значения в перечисление:
{
"item_type": "value",
"value": "ATX",
"priority": 10,
"description": "Стандартный полноразмерный форм-фактор"
}
Пример добавления другого перечисления внутрь перечисления:
{
"item_type": "enum",
"child_enum_id": 2,
"priority": 20,
"description": "Вложенный классификатор совместимых форм-факторов"
}
Дерево классификатора
GET /database/tree— получить все дерево целиком
В ответе возвращаются:
- корневая категория;
- все дочерние категории;
- все товары в соответствующих категориях;
- список спецификаций у каждого товара.
Бизнес-ограничения
Сервис возвращает ошибку, если:
- указана несуществующая родительская категория;
- создается дублирующаяся категория на одном уровне дерева;
- создается дублирующийся товар в одной категории;
- удаляется несуществующая категория или товар;
- удаляется категория, в которой есть подкатегории или товары;
- категория переносится в саму себя или в собственного потомка;
- товар переносится в категорию, где уже есть товар с таким же именем;
- передан несуществующий
specification_id; - передан несуществующий
enum_value_id; - создается перечисление с уже существующим именем;
- создается дублирующееся значение внутри одного перечисления;
- перечисление добавляется внутрь самого себя;
- добавление вложенного перечисления создает цикл.
Полезные файлы проекта
- src/main.py — запуск приложения
- src/db/database.py — схема БД и логика работы с данными
- src/api/database.py — HTTP-методы
- src/api/models.py — Pydantic-модели
- docs/database_description.md — раздел про БД для отчета
- docs/server_description.md — раздел про серверную часть
- docs/conclusion.md — заключение
- docs/appendix_a.md — приложение А