feat(integrations): add Odoo API routes
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
3
services/integrations/app/routers/__init__.py
Normal file
3
services/integrations/app/routers/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from app.routers.odoo import router as odoo_router
|
||||
|
||||
__all__ = ["odoo_router"]
|
||||
233
services/integrations/app/routers/odoo.py
Normal file
233
services/integrations/app/routers/odoo.py
Normal file
@@ -0,0 +1,233 @@
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from typing import Optional
|
||||
|
||||
from app.services.partner import PartnerService
|
||||
from app.services.sale import SaleOrderService
|
||||
from app.services.product import ProductService
|
||||
from app.services.crm import CRMService
|
||||
from app.schemas.partner import PartnerCreate, PartnerUpdate
|
||||
from app.schemas.sale import QuotationCreate
|
||||
from app.schemas.crm import LeadCreate
|
||||
from app.odoo.exceptions import OdooError, OdooNotFoundError
|
||||
|
||||
router = APIRouter(prefix="/api/odoo", tags=["odoo"])
|
||||
|
||||
|
||||
# ============== Partners ==============
|
||||
|
||||
@router.get("/partners/search")
|
||||
def search_partner(phone: str = None, email: str = None):
|
||||
"""Search partner by phone or email"""
|
||||
service = PartnerService()
|
||||
|
||||
if phone:
|
||||
result = service.search_by_phone(phone)
|
||||
elif email:
|
||||
result = service.search_by_email(email)
|
||||
else:
|
||||
raise HTTPException(400, "Provide phone or email")
|
||||
|
||||
if not result:
|
||||
raise HTTPException(404, "Partner not found")
|
||||
return result
|
||||
|
||||
|
||||
@router.get("/partners/{partner_id}")
|
||||
def get_partner(partner_id: int):
|
||||
"""Get partner by ID"""
|
||||
try:
|
||||
service = PartnerService()
|
||||
return service.get_by_id(partner_id)
|
||||
except OdooNotFoundError:
|
||||
raise HTTPException(404, "Partner not found")
|
||||
|
||||
|
||||
@router.post("/partners")
|
||||
def create_partner(data: PartnerCreate):
|
||||
"""Create a new partner"""
|
||||
try:
|
||||
service = PartnerService()
|
||||
partner_id = service.create(data)
|
||||
return {"id": partner_id}
|
||||
except OdooError as e:
|
||||
raise HTTPException(400, str(e))
|
||||
|
||||
|
||||
@router.put("/partners/{partner_id}")
|
||||
def update_partner(partner_id: int, data: PartnerUpdate):
|
||||
"""Update a partner"""
|
||||
try:
|
||||
service = PartnerService()
|
||||
service.update(partner_id, data)
|
||||
return {"success": True}
|
||||
except OdooError as e:
|
||||
raise HTTPException(400, str(e))
|
||||
|
||||
|
||||
@router.get("/partners/{partner_id}/balance")
|
||||
def get_partner_balance(partner_id: int):
|
||||
"""Get partner balance"""
|
||||
try:
|
||||
service = PartnerService()
|
||||
return service.get_balance(partner_id)
|
||||
except OdooNotFoundError:
|
||||
raise HTTPException(404, "Partner not found")
|
||||
|
||||
|
||||
# ============== Sales ==============
|
||||
|
||||
@router.get("/sales/partner/{partner_id}")
|
||||
def get_partner_orders(partner_id: int, state: str = None, limit: int = 10):
|
||||
"""Get orders for a partner"""
|
||||
service = SaleOrderService()
|
||||
return service.search_by_partner(partner_id, state, limit)
|
||||
|
||||
|
||||
@router.get("/sales/{order_id}")
|
||||
def get_order(order_id: int):
|
||||
"""Get order details"""
|
||||
try:
|
||||
service = SaleOrderService()
|
||||
return service.get_by_id(order_id)
|
||||
except OdooNotFoundError:
|
||||
raise HTTPException(404, "Order not found")
|
||||
|
||||
|
||||
@router.get("/sales/name/{name}")
|
||||
def get_order_by_name(name: str):
|
||||
"""Get order by name (SO001)"""
|
||||
service = SaleOrderService()
|
||||
result = service.get_by_name(name)
|
||||
if not result:
|
||||
raise HTTPException(404, "Order not found")
|
||||
return result
|
||||
|
||||
|
||||
@router.post("/sales/quotation")
|
||||
def create_quotation(data: QuotationCreate):
|
||||
"""Create a quotation"""
|
||||
try:
|
||||
service = SaleOrderService()
|
||||
order_id = service.create_quotation(data)
|
||||
return {"id": order_id}
|
||||
except OdooError as e:
|
||||
raise HTTPException(400, str(e))
|
||||
|
||||
|
||||
@router.post("/sales/{order_id}/confirm")
|
||||
def confirm_order(order_id: int):
|
||||
"""Confirm quotation to sale order"""
|
||||
try:
|
||||
service = SaleOrderService()
|
||||
service.confirm_order(order_id)
|
||||
return {"success": True}
|
||||
except OdooError as e:
|
||||
raise HTTPException(400, str(e))
|
||||
|
||||
|
||||
# ============== Products ==============
|
||||
|
||||
@router.get("/products")
|
||||
def search_products(q: str = None, category_id: int = None, limit: int = 20):
|
||||
"""Search products"""
|
||||
service = ProductService()
|
||||
return service.search(q, category_id, limit)
|
||||
|
||||
|
||||
@router.get("/products/{product_id}")
|
||||
def get_product(product_id: int):
|
||||
"""Get product details"""
|
||||
try:
|
||||
service = ProductService()
|
||||
return service.get_by_id(product_id)
|
||||
except OdooNotFoundError:
|
||||
raise HTTPException(404, "Product not found")
|
||||
|
||||
|
||||
@router.get("/products/sku/{sku}")
|
||||
def get_product_by_sku(sku: str):
|
||||
"""Get product by SKU"""
|
||||
service = ProductService()
|
||||
result = service.get_by_sku(sku)
|
||||
if not result:
|
||||
raise HTTPException(404, "Product not found")
|
||||
return result
|
||||
|
||||
|
||||
@router.get("/products/{product_id}/stock")
|
||||
def check_product_stock(product_id: int):
|
||||
"""Check product stock"""
|
||||
try:
|
||||
service = ProductService()
|
||||
return service.check_stock(product_id)
|
||||
except OdooNotFoundError:
|
||||
raise HTTPException(404, "Product not found")
|
||||
|
||||
|
||||
@router.get("/products/{product_id}/availability")
|
||||
def check_availability(product_id: int, quantity: float):
|
||||
"""Check if quantity is available"""
|
||||
try:
|
||||
service = ProductService()
|
||||
return service.check_availability(product_id, quantity)
|
||||
except OdooNotFoundError:
|
||||
raise HTTPException(404, "Product not found")
|
||||
|
||||
|
||||
# ============== CRM ==============
|
||||
|
||||
@router.post("/crm/leads")
|
||||
def create_lead(data: LeadCreate):
|
||||
"""Create a new lead"""
|
||||
try:
|
||||
service = CRMService()
|
||||
lead_id = service.create_lead(data)
|
||||
return {"id": lead_id}
|
||||
except OdooError as e:
|
||||
raise HTTPException(400, str(e))
|
||||
|
||||
|
||||
@router.get("/crm/leads/{lead_id}")
|
||||
def get_lead(lead_id: int):
|
||||
"""Get lead details"""
|
||||
try:
|
||||
service = CRMService()
|
||||
return service.get_by_id(lead_id)
|
||||
except OdooNotFoundError:
|
||||
raise HTTPException(404, "Lead not found")
|
||||
|
||||
|
||||
@router.get("/crm/leads/partner/{partner_id}")
|
||||
def get_partner_leads(partner_id: int, limit: int = 10):
|
||||
"""Get leads for a partner"""
|
||||
service = CRMService()
|
||||
return service.search_by_partner(partner_id, limit)
|
||||
|
||||
|
||||
@router.put("/crm/leads/{lead_id}/stage")
|
||||
def update_lead_stage(lead_id: int, stage_id: int):
|
||||
"""Update lead stage"""
|
||||
try:
|
||||
service = CRMService()
|
||||
service.update_stage(lead_id, stage_id)
|
||||
return {"success": True}
|
||||
except OdooError as e:
|
||||
raise HTTPException(400, str(e))
|
||||
|
||||
|
||||
@router.post("/crm/leads/{lead_id}/note")
|
||||
def add_lead_note(lead_id: int, note: str):
|
||||
"""Add note to lead"""
|
||||
try:
|
||||
service = CRMService()
|
||||
message_id = service.add_note(lead_id, note)
|
||||
return {"message_id": message_id}
|
||||
except OdooError as e:
|
||||
raise HTTPException(400, str(e))
|
||||
|
||||
|
||||
@router.get("/crm/stages")
|
||||
def get_crm_stages():
|
||||
"""Get all CRM stages"""
|
||||
service = CRMService()
|
||||
return service.get_stages()
|
||||
Reference in New Issue
Block a user