# app/routes/partners.py """ Маршруты API для управления партнерами Соответствует модулям 1-3 ТЗ """ from fastapi import APIRouter, HTTPException from app.database import db from app.models import Partner, PartnerCreate, PartnerUpdate, DiscountResponse from decimal import Decimal router = APIRouter() @router.get("/") async def get_partners(): """ Получение списка всех партнеров Соответствует требованию просмотра списка партнеров """ try: result = db.execute_query(""" SELECT partner_id, partner_type, company_name, legal_address, inn, director_name, phone, email, rating, sales_locations FROM partners ORDER BY company_name """) partners_list = [] for row in result: partner_dict = dict(row) # Преобразуем рейтинг к int если нужно if isinstance(partner_dict.get('rating'), float): partner_dict['rating'] = int(partner_dict['rating']) partners_list.append(partner_dict) return partners_list except Exception as e: if "relation \"partners\" does not exist" in str(e): return [] raise HTTPException(status_code=500, detail=str(e)) @router.get("/{partner_id}") async def get_partner(partner_id: int): """Получение информации о конкретном партнере""" try: result = db.execute_query( "SELECT * FROM partners WHERE partner_id = %s", (partner_id,) ) if not result: raise HTTPException(status_code=404, detail="Partner not found") partner_data = dict(result[0]) # Преобразуем рейтинг к int если нужно if isinstance(partner_data.get('rating'), float): partner_data['rating'] = int(partner_data['rating']) return partner_data except Exception as e: if "relation \"partners\" does not exist" in str(e): raise HTTPException(status_code=404, detail="Partner not found") raise HTTPException(status_code=500, detail=str(e)) @router.post("/") async def create_partner(partner: PartnerCreate): """ Создание нового партнера Включает валидацию данных согласно ТЗ """ try: result = db.execute_query(""" INSERT INTO partners (partner_type, company_name, legal_address, inn, director_name, phone, email, rating, sales_locations) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s) RETURNING partner_id """, ( partner.partner_type, partner.company_name, partner.legal_address, partner.inn, partner.director_name, partner.phone, partner.email, partner.rating, partner.sales_locations )) return {"partner_id": result[0]["partner_id"]} except Exception as e: if "duplicate key value violates unique constraint" in str(e): raise HTTPException(status_code=400, detail="Partner with this INN already exists") raise HTTPException(status_code=500, detail=str(e)) @router.put("/{partner_id}") async def update_partner(partner_id: int, partner: PartnerUpdate): """ Обновление данных партнера Соответствует требованию редактирования данных партнера """ try: db.execute_query(""" UPDATE partners SET partner_type = %s, company_name = %s, legal_address = %s, inn = %s, director_name = %s, phone = %s, email = %s, rating = %s, sales_locations = %s WHERE partner_id = %s """, ( partner.partner_type, partner.company_name, partner.legal_address, partner.inn, partner.director_name, partner.phone, partner.email, partner.rating, partner.sales_locations, partner_id )) return {"message": "Partner updated successfully"} except Exception as e: if "duplicate key value violates unique constraint" in str(e): raise HTTPException(status_code=400, detail="Partner with this INN already exists") raise HTTPException(status_code=500, detail=str(e)) @router.delete("/{partner_id}") async def delete_partner(partner_id: int): """Удаление партнера""" try: db.execute_query( "DELETE FROM partners WHERE partner_id = %s", (partner_id,) ) return {"message": "Partner deleted successfully"} except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.get("/{partner_id}/discount", response_model=DiscountResponse) async def calculate_partner_discount(partner_id: int): """ Расчет скидки для партнера на основе общего количества продаж Соответствует модулю 2 ТЗ """ try: # Получаем общее количество продаж партнера result = db.execute_query(""" SELECT COALESCE(SUM(quantity), 0) as total_sales FROM sales WHERE partner_id = %s """, (partner_id,)) total_sales = result[0]["total_sales"] if result else Decimal('0') # Расчет скидки согласно бизнес-правилам ТЗ if total_sales < 10000: discount = 0 elif total_sales < 50000: discount = 5 elif total_sales < 300000: discount = 10 else: discount = 15 return DiscountResponse( partner_id=partner_id, total_sales=total_sales, discount_percent=discount ) except Exception as e: raise HTTPException(status_code=500, detail=str(e))