projects/org/pirotehnika/app/pim/API_DOCUMENTATION.md

PIM Service API Documentation

Overview

The PIM Service API provides REST endpoints for managing product information and pricing for pirotechnic products.

Base URL: /api/v1

Version: 1.0.0

Authentication

Currently, the API does not require authentication. This should be implemented in production.

Endpoints

Products

Get Product by Article

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


List Products

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"

Search Products

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 by Brand

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 by Category

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]


Pricing

Calculate Price

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}'

Calculate Bulk Prices

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 All Cost Rules

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 Cost Rule by Brand

GET /pricing/rules/{brand}

Get cost rule for a specific brand.

Parameters:
- brand (path, required): Brand name

Response: PimCostRuleResponse or null


Create Cost Rule

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


Update Cost Rule

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 Cost Rule

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


Data Models

PimProductResponse

{
    "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
}

PricingCalculateResponse

{
    "article": str,
    "base_price": Decimal,
    "cost_price": Decimal,
    "retail_price": Decimal,
    "markup_percent": Decimal,
    "discount_percent": Optional[Decimal]
}

PimCostRuleResponse

{
    "id": int,
    "brand": str,
    "discount_percent": Decimal,
    "description": Optional[str],
    "is_active": bool,
    "created_at": datetime,
    "updated_at": datetime
}

Error Responses

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

Rate Limiting

Not currently implemented. Should be added for production.

Running the Service

Development

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

Production

gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app

Interactive Documentation

Once the service is running, you can access:
- Swagger UI: http://localhost:8000/api/v1/docs
- ReDoc: http://localhost:8000/api/v1/redoc

Examples

Get a product

curl -X GET "http://localhost:8000/api/v1/products/НФ-00001234"

List all JF-Pyro products

curl -X GET "http://localhost:8000/api/v1/products/?brand=JF-Pyro&limit=20"

Search for products

curl -X POST "http://localhost:8000/api/v1/products/search" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "фейерверк",
    "limit": 10
  }'

Calculate price for a product

curl -X POST "http://localhost:8000/api/v1/pricing/calculate" \
  -H "Content-Type: application/json" \
  -d '{
    "article": "НФ-00001234",
    "markup_percent": 30
  }'

Create a cost rule

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"
  }'

Future Enhancements