feat(integrations): add Odoo API routes
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
|
from app.routers import odoo_router
|
||||||
|
|
||||||
app = FastAPI(title="WhatsApp Central - Integrations Service")
|
app = FastAPI(title="WhatsApp Central - Integrations Service")
|
||||||
|
|
||||||
@@ -11,6 +12,8 @@ app.add_middleware(
|
|||||||
allow_headers=["*"],
|
allow_headers=["*"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
app.include_router(odoo_router)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/health")
|
@app.get("/health")
|
||||||
def health_check():
|
def health_check():
|
||||||
|
|||||||
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