From b8d97e255790bccdd4e101137c60e198139c94a9 Mon Sep 17 00:00:00 2001 From: Claude AI Date: Thu, 29 Jan 2026 11:10:54 +0000 Subject: [PATCH] feat(fase4): add FlowTemplate model and API Co-Authored-By: Claude Opus 4.5 --- services/api-gateway/app/main.py | 3 +- services/api-gateway/app/models/__init__.py | 2 + .../api-gateway/app/models/flow_template.py | 21 +++++ .../api-gateway/app/routers/flow_templates.py | 86 +++++++++++++++++++ .../api-gateway/app/schemas/flow_template.py | 31 +++++++ 5 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 services/api-gateway/app/models/flow_template.py create mode 100644 services/api-gateway/app/routers/flow_templates.py create mode 100644 services/api-gateway/app/schemas/flow_template.py diff --git a/services/api-gateway/app/main.py b/services/api-gateway/app/main.py index e04f8d5..3820844 100644 --- a/services/api-gateway/app/main.py +++ b/services/api-gateway/app/main.py @@ -2,7 +2,7 @@ from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from app.core.config import get_settings from app.core.database import engine, Base -from app.routers import auth, whatsapp, flows, queues, supervisor +from app.routers import auth, whatsapp, flows, queues, supervisor, flow_templates settings = get_settings() @@ -31,6 +31,7 @@ app.include_router(whatsapp.router) app.include_router(flows.router) app.include_router(queues.router) app.include_router(supervisor.router) +app.include_router(flow_templates.router) @app.get("/health") diff --git a/services/api-gateway/app/models/__init__.py b/services/api-gateway/app/models/__init__.py index a45b9ad..a24d382 100644 --- a/services/api-gateway/app/models/__init__.py +++ b/services/api-gateway/app/models/__init__.py @@ -4,6 +4,7 @@ from app.models.flow import Flow, FlowSession, TriggerType from app.models.queue import Queue, QueueAgent, AssignmentMethod from app.models.quick_reply import QuickReply from app.models.global_variable import GlobalVariable +from app.models.flow_template import FlowTemplate __all__ = [ "User", @@ -19,4 +20,5 @@ __all__ = [ "AssignmentMethod", "QuickReply", "GlobalVariable", + "FlowTemplate", ] diff --git a/services/api-gateway/app/models/flow_template.py b/services/api-gateway/app/models/flow_template.py new file mode 100644 index 0000000..7f1d23a --- /dev/null +++ b/services/api-gateway/app/models/flow_template.py @@ -0,0 +1,21 @@ +import uuid +from datetime import datetime +from sqlalchemy import Column, String, Text, DateTime, Boolean, ForeignKey +from sqlalchemy.dialects.postgresql import UUID, JSONB +from app.core.database import Base + + +class FlowTemplate(Base): + __tablename__ = "flow_templates" + + id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) + name = Column(String(100), nullable=False) + description = Column(Text, nullable=True) + category = Column(String(50), default="general", nullable=False) + nodes = Column(JSONB, default=list) + edges = Column(JSONB, default=list) + variables = Column(JSONB, default=dict) + preview_image = Column(String(500), nullable=True) + is_public = Column(Boolean, default=True, nullable=False) + created_by = Column(UUID(as_uuid=True), ForeignKey("users.id"), nullable=False) + created_at = Column(DateTime, default=datetime.utcnow, nullable=False) diff --git a/services/api-gateway/app/routers/flow_templates.py b/services/api-gateway/app/routers/flow_templates.py new file mode 100644 index 0000000..f175671 --- /dev/null +++ b/services/api-gateway/app/routers/flow_templates.py @@ -0,0 +1,86 @@ +from fastapi import APIRouter, Depends, HTTPException +from sqlalchemy.orm import Session +from typing import List, Optional +from uuid import UUID +from app.core.database import get_db +from app.core.security import get_current_user +from app.models.user import User +from app.models.flow_template import FlowTemplate +from app.models.flow import Flow, TriggerType +from app.schemas.flow_template import FlowTemplateCreate, FlowTemplateResponse + +router = APIRouter(prefix="/api/flow-templates", tags=["flow-templates"]) + + +@router.get("", response_model=List[FlowTemplateResponse]) +def list_templates( + category: Optional[str] = None, + db: Session = Depends(get_db), + current_user: User = Depends(get_current_user), +): + query = db.query(FlowTemplate).filter(FlowTemplate.is_public == True) + if category: + query = query.filter(FlowTemplate.category == category) + return query.all() + + +@router.post("", response_model=FlowTemplateResponse) +def create_template( + request: FlowTemplateCreate, + db: Session = Depends(get_db), + current_user: User = Depends(get_current_user), +): + template = FlowTemplate( + **request.model_dump(), + created_by=current_user.id, + ) + db.add(template) + db.commit() + db.refresh(template) + return template + + +@router.post("/{template_id}/use") +def use_template( + template_id: UUID, + flow_name: str, + db: Session = Depends(get_db), + current_user: User = Depends(get_current_user), +): + """Create a new flow from template""" + template = db.query(FlowTemplate).filter(FlowTemplate.id == template_id).first() + if not template: + raise HTTPException(status_code=404, detail="Template not found") + + flow = Flow( + name=flow_name, + description=f"Created from template: {template.name}", + trigger_type=TriggerType.KEYWORD, + nodes=template.nodes, + edges=template.edges, + variables=template.variables, + is_active=False, + ) + db.add(flow) + db.commit() + db.refresh(flow) + + return {"success": True, "flow_id": str(flow.id)} + + +@router.delete("/{template_id}") +def delete_template( + template_id: UUID, + db: Session = Depends(get_db), + current_user: User = Depends(get_current_user), +): + template = db.query(FlowTemplate).filter(FlowTemplate.id == template_id).first() + if not template: + raise HTTPException(status_code=404, detail="Template not found") + + if template.created_by != current_user.id: + raise HTTPException(status_code=403, detail="Not authorized") + + db.delete(template) + db.commit() + return {"success": True} diff --git a/services/api-gateway/app/schemas/flow_template.py b/services/api-gateway/app/schemas/flow_template.py new file mode 100644 index 0000000..72eca17 --- /dev/null +++ b/services/api-gateway/app/schemas/flow_template.py @@ -0,0 +1,31 @@ +from pydantic import BaseModel +from typing import Optional, List +from uuid import UUID +from datetime import datetime + + +class FlowTemplateCreate(BaseModel): + name: str + description: Optional[str] = None + category: str = "general" + nodes: List[dict] = [] + edges: List[dict] = [] + variables: dict = {} + is_public: bool = True + + +class FlowTemplateResponse(BaseModel): + id: UUID + name: str + description: Optional[str] + category: str + nodes: List[dict] + edges: List[dict] + variables: dict + preview_image: Optional[str] + is_public: bool + created_by: UUID + created_at: datetime + + class Config: + from_attributes = True