from typing import List from datetime import datetime import logging from fastapi import FastAPI, HTTPException from pydantic import BaseModel app = FastAPI( title="Service 2 - Order Service", description="Микросервис для управления заказами и продуктами", version="1.0.0" ) # Логирование logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # Модели данных class Product(BaseModel): id: int name: str price: float quantity: int class ProductCreate(BaseModel): name: str price: float quantity: int class Order(BaseModel): id: int user_id: int product_id: int quantity: int total_price: float created_at: str class OrderCreate(BaseModel): user_id: int product_id: int quantity: int # Имитация базы данных products_db = { 1: {"id": 1, "name": "Ноутбук", "price": 50000.00, "quantity": 5}, 2: {"id": 2, "name": "Монитор", "price": 15000.00, "quantity": 10}, 3: {"id": 3, "name": "Клавиатура", "price": 3000.00, "quantity": 25}, } orders_db = { 1: { "id": 1, "user_id": 1, "product_id": 1, "quantity": 1, "total_price": 50000.00, "created_at": "2025-01-01T10:00:00" }, } next_product_id = 4 next_order_id = 2 # Маршруты @app.get("/", tags=["Health"]) async def root(): """Проверка работоспособности Service 2""" logger.info("Health check для Service 2") return { "service": "Service 2 - Order Service", "status": "operational", "version": "1.0.0" } @app.get("/health", tags=["Health"]) async def health_check(): """Health check endpoint""" return {"status": "healthy", "service": "order-service", "random-info": "yep"} # Endpoints для продуктов @app.get("/products", response_model=List[Product], tags=["Products"]) async def list_products(skip: int = 0, limit: int = 10): """Получить список всех продуктов""" logger.info(f"Получение списка продуктов (skip={skip}, limit={limit})") products_list = list(products_db.values()) return products_list[skip:skip + limit] @app.get("/products/{product_id}", response_model=Product, tags=["Products"]) async def get_product(product_id: int): """Получить продукт по ID""" logger.info(f"Получение продукта с ID: {product_id}") if product_id not in products_db: logger.warning(f"Продукт с ID {product_id} не найден") raise HTTPException(status_code=404, detail="Продукт не найден") return products_db[product_id] @app.post("/products", response_model=Product, tags=["Products"]) async def create_product(product: ProductCreate): """Создать новый продукт""" global next_product_id logger.info(f"Создание нового продукта: {product.name}") new_product = { "id": next_product_id, "name": product.name, "price": product.price, "quantity": product.quantity } products_db[next_product_id] = new_product next_product_id += 1 logger.info(f"Продукт создан с ID: {new_product['id']}") return new_product @app.put("/products/{product_id}", response_model=Product, tags=["Products"]) async def update_product(product_id: int, product: ProductCreate): """Обновить продукт""" logger.info(f"Обновление продукта с ID: {product_id}") if product_id not in products_db: raise HTTPException(status_code=404, detail="Продукт не найден") updated_product = { "id": product_id, "name": product.name, "price": product.price, "quantity": product.quantity } products_db[product_id] = updated_product return updated_product @app.delete("/products/{product_id}", tags=["Products"]) async def delete_product(product_id: int): """Удалить продукт""" logger.info(f"Удаление продукта с ID: {product_id}") if product_id not in products_db: raise HTTPException(status_code=404, detail="Продукт не найден") del products_db[product_id] return {"message": f"Продукт {product_id} удален"} # Endpoints для заказов @app.get("/orders", response_model=List[Order], tags=["Orders"]) async def list_orders(skip: int = 0, limit: int = 10): """Получить список всех заказов""" logger.info(f"Получение списка заказов (skip={skip}, limit={limit})") orders_list = list(orders_db.values()) return orders_list[skip:skip + limit] @app.get("/orders/{order_id}", response_model=Order, tags=["Orders"]) async def get_order(order_id: int): """Получить заказ по ID""" logger.info(f"Получение заказа с ID: {order_id}") if order_id not in orders_db: logger.warning(f"Заказ с ID {order_id} не найден") raise HTTPException(status_code=404, detail="Заказ не найден") return orders_db[order_id] @app.post("/orders", response_model=Order, tags=["Orders"]) async def create_order(order: OrderCreate): """Создать новый заказ""" global next_order_id logger.info(f"Создание нового заказа для пользователя {order.user_id}") if order.product_id not in products_db: raise HTTPException(status_code=404, detail="Продукт не найден") product = products_db[order.product_id] if product["quantity"] < order.quantity: raise HTTPException(status_code=400, detail="Недостаточно товара на складе") total_price = product["price"] * order.quantity new_order = { "id": next_order_id, "user_id": order.user_id, "product_id": order.product_id, "quantity": order.quantity, "total_price": total_price, "created_at": datetime.utcnow().isoformat() } orders_db[next_order_id] = new_order product["quantity"] -= order.quantity next_order_id += 1 logger.info(f"Заказ создан с ID: {new_order['id']}") return new_order @app.get("/stats", tags=["Stats"]) async def get_stats(): """Получить статистику по заказам""" logger.info("Получение статистики") total_revenue = sum(order["total_price"] for order in orders_db.values()) return { "total_orders": len(orders_db), "total_products": len(products_db), "total_revenue": total_revenue, "service": "order-service" } if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8002)