The PIM Service API provides REST endpoints for managing product information and pricing for pirotechnic products.
Base URL: /api/v1
Version: 1.0.0
Currently, the API does not require authentication. This should be implemented in production.
GET /products/{article}
Get a specific product by its article number (SKU).
Parameters:
- article (path, required): Product article/SKU
Response: PimProductResponse
{
"article": "НФ-00001234",
"name": "Product Name",
"brand": "JF-Pyro",
"category": "Фейерверки",
"base_price": 100.00,
"cost_price": 70.00,
"discount_percent": 30,
"product_type": "simple",
"code_1c": "1C-CODE",
"barcode": "1234567890",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z"
}
Status Codes:
- 200: Success
- 404: Product not found
GET /products/
Get a list of products with optional filtering.
Query Parameters:
- limit (optional, integer): Maximum number of products (1-1000, default 50)
- offset (optional, integer): Number of items to skip (default 0)
- brand (optional, string): Filter by brand name
- category (optional, string): Filter by category name
Response: List[PimProductResponse]
Example Request:
curl -X GET "http://localhost:8000/api/v1/products/?limit=10&brand=JF-Pyro"
POST /products/search
Search products by name or article number.
Request Body:
{
"query": "search string",
"limit": 50
}
Response: List[PimProductResponse]
Example Request:
curl -X POST "http://localhost:8000/api/v1/products/search" \
-H "Content-Type: application/json" \
-d '{"query": "фейерверк", "limit": 10}'
GET /products/brand/{brand}
Get all products from a specific brand.
Parameters:
- brand (path, required): Brand name
- limit (query, optional): Maximum number of products (default 50)
Response: List[PimProductResponse]
GET /products/category/{category}
Get all products from a specific category.
Parameters:
- category (path, required): Category name
- limit (query, optional): Maximum number of products (default 50)
Response: List[PimProductResponse]
POST /pricing/calculate
Calculate cost and retail prices for a product based on base price and markup.
Request Body:
{
"article": "НФ-00001234",
"markup_percent": 30
}
Response: PricingCalculateResponse
{
"article": "НФ-00001234",
"base_price": 100.00,
"cost_price": 70.00,
"retail_price": 91.00,
"markup_percent": 30,
"discount_percent": 30
}
Status Codes:
- 200: Success
- 404: Product not found or has no base price
- 400: Invalid request
Example Request:
curl -X POST "http://localhost:8000/api/v1/pricing/calculate" \
-H "Content-Type: application/json" \
-d '{"article": "НФ-00001234", "markup_percent": 25}'
POST /pricing/calculate-bulk
Calculate prices for multiple products in bulk.
Request Body:
{
"articles": ["НФ-00001234", "НФ-00001235"],
"markup_percent": 30
}
Response: PricingBulkCalculateResponse
{
"results": [
{
"article": "НФ-00001234",
"base_price": 100.00,
"cost_price": 70.00,
"retail_price": 91.00,
"markup_percent": 30,
"discount_percent": 30
}
],
"total_items": 2,
"success_count": 1,
"error_count": 1
}
GET /pricing/rules
Get all cost rules for brands.
Query Parameters:
- active_only (optional, boolean): Return only active rules (default true)
Response: List[PimCostRuleResponse]
GET /pricing/rules/{brand}
Get cost rule for a specific brand.
Parameters:
- brand (path, required): Brand name
Response: PimCostRuleResponse or null
POST /pricing/rules
Create a new cost rule for a brand.
Request Body:
{
"brand": "JF-Pyro",
"discount_percent": 30,
"description": "Standard JF-Pyro discount"
}
Response: PimCostRuleResponse
Status Codes:
- 200: Success
- 400: Rule for brand already exists
PUT /pricing/rules/{brand}
Update an existing cost rule for a brand.
Parameters:
- brand (path, required): Brand name
Request Body:
{
"discount_percent": 35,
"description": "Updated discount",
"is_active": true
}
Response: PimCostRuleResponse
Status Codes:
- 200: Success
- 404: Rule not found
DELETE /pricing/rules/{brand}
Delete a cost rule for a brand.
Parameters:
- brand (path, required): Brand name
Response:
{
"message": "Cost rule for brand 'JF-Pyro' deleted successfully"
}
Status Codes:
- 200: Success
- 404: Rule not found
{
"article": str, # Артикул
"name": str, # Название товара
"brand": Optional[str], # Бренд (JF-Pyro, Maxsem)
"category": Optional[str],# Категория товара
"base_price": Optional[Decimal], # Базовая цена
"cost_price": Optional[Decimal], # Себестоимость
"discount_percent": Optional[Decimal],
"product_type": Optional[str], # simple/bundle
"code_1c": Optional[str], # Код в 1С
"barcode": Optional[str], # Штрихкод
"created_at": datetime,
"updated_at": datetime
}
{
"article": str,
"base_price": Decimal,
"cost_price": Decimal,
"retail_price": Decimal,
"markup_percent": Decimal,
"discount_percent": Optional[Decimal]
}
{
"id": int,
"brand": str,
"discount_percent": Decimal,
"description": Optional[str],
"is_active": bool,
"created_at": datetime,
"updated_at": datetime
}
All error responses follow this format:
{
"detail": "Error message describing what went wrong"
}
Common error codes:
- 400: Bad Request - Invalid input parameters
- 404: Not Found - Resource not found
- 422: Unprocessable Entity - Validation error
- 500: Internal Server Error
Not currently implemented. Should be added for production.
cd /opt/claude-workspace/L1-SERVICE/pirotehnika/pim
pip install -r requirements.txt
python -m uvicorn main:app --reload --host 0.0.0.0 --port 8000
gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app
Once the service is running, you can access:
- Swagger UI: http://localhost:8000/api/v1/docs
- ReDoc: http://localhost:8000/api/v1/redoc
curl -X GET "http://localhost:8000/api/v1/products/НФ-00001234"
curl -X GET "http://localhost:8000/api/v1/products/?brand=JF-Pyro&limit=20"
curl -X POST "http://localhost:8000/api/v1/products/search" \
-H "Content-Type: application/json" \
-d '{
"query": "фейерверк",
"limit": 10
}'
curl -X POST "http://localhost:8000/api/v1/pricing/calculate" \
-H "Content-Type: application/json" \
-d '{
"article": "НФ-00001234",
"markup_percent": 30
}'
curl -X POST "http://localhost:8000/api/v1/pricing/rules" \
-H "Content-Type: application/json" \
-d '{
"brand": "JF-Pyro",
"discount_percent": 30,
"description": "Standard JF-Pyro discount"
}'