Phase 1C: Frontend unified contact UI
This commit is contained in:
@@ -13,7 +13,7 @@ from app.ai.llm_client import get_llm_client
|
||||
from app.core.audit import log_audit
|
||||
from app.core.auth import check_permission
|
||||
from app.models.ai_conversation import AIConversation, AIMessage
|
||||
from app.models.contact import Contact as Company
|
||||
from app.models.contact import Contact
|
||||
from app.models.contact import Contact
|
||||
from app.models.workflow import Workflow
|
||||
|
||||
@@ -306,16 +306,14 @@ async def _execute_api_action(
|
||||
) -> dict[str, Any]:
|
||||
"""Execute an API action directly against the database.
|
||||
|
||||
Supports companies and contacts CRUD, plus workflow listing.
|
||||
Supports contacts CRUD (including company-type contacts), plus workflow listing.
|
||||
"""
|
||||
# Parse path to determine entity and operation
|
||||
parts = path.replace("/api/v1/", "").strip("/").split("/")
|
||||
entity = parts[0] if parts else ""
|
||||
entity_id = parts[1] if len(parts) > 1 else None
|
||||
|
||||
if entity == "companies":
|
||||
return await _exec_companies(db, tenant_id, user_id, method, entity_id, body)
|
||||
elif entity == "contacts":
|
||||
if entity in ("companies", "contacts"):
|
||||
return await _exec_contacts(db, tenant_id, user_id, method, entity_id, body)
|
||||
elif entity == "workflows":
|
||||
return await _exec_workflows(db, tenant_id, user_id, method, entity_id, body)
|
||||
@@ -323,7 +321,7 @@ async def _execute_api_action(
|
||||
return {"error": f"Unsupported entity: {entity}", "status_code": 400, "success": False}
|
||||
|
||||
|
||||
async def _exec_companies(
|
||||
async def _exec_contacts\(
|
||||
db: AsyncSession,
|
||||
tenant_id: uuid.UUID,
|
||||
user_id: uuid.UUID,
|
||||
@@ -331,99 +329,7 @@ async def _exec_companies(
|
||||
entity_id: str | None,
|
||||
body: dict[str, Any],
|
||||
) -> dict[str, Any]:
|
||||
"""Execute company operations."""
|
||||
if method == "GET":
|
||||
result = await db.execute(
|
||||
select(Company).where(
|
||||
Company.tenant_id == tenant_id,
|
||||
Company.deleted_at.is_(None),
|
||||
)
|
||||
)
|
||||
companies = result.scalars().all()
|
||||
return {
|
||||
"success": True,
|
||||
"status_code": 200,
|
||||
"data": [{"id": str(c.id), "name": c.name, "industry": c.industry} for c in companies],
|
||||
}
|
||||
|
||||
elif method == "POST":
|
||||
company = Company(
|
||||
tenant_id=tenant_id,
|
||||
name=body.get("name", "Untitled"),
|
||||
industry=body.get("industry"),
|
||||
phone=body.get("phone"),
|
||||
email=body.get("email"),
|
||||
website=body.get("website"),
|
||||
description=body.get("description"),
|
||||
created_by=user_id,
|
||||
updated_by=user_id,
|
||||
)
|
||||
db.add(company)
|
||||
await db.flush()
|
||||
return {
|
||||
"success": True,
|
||||
"status_code": 201,
|
||||
"data": {"id": str(company.id), "name": company.name},
|
||||
}
|
||||
|
||||
elif method == "DELETE":
|
||||
if not entity_id or entity_id == "{id}":
|
||||
return {"error": "Company ID required", "status_code": 400, "success": False}
|
||||
comp_uuid = uuid.UUID(entity_id)
|
||||
result = await db.execute(
|
||||
select(Company).where(
|
||||
Company.id == comp_uuid,
|
||||
Company.tenant_id == tenant_id,
|
||||
)
|
||||
)
|
||||
company = result.scalar_one_or_none()
|
||||
if company is None:
|
||||
return {"error": "Company not found", "status_code": 404, "success": False}
|
||||
company.deleted_at = datetime.now(UTC)
|
||||
await db.flush()
|
||||
return {
|
||||
"success": True,
|
||||
"status_code": 200,
|
||||
"data": {"id": str(company.id), "deleted": True},
|
||||
}
|
||||
|
||||
elif method == "PATCH":
|
||||
if not entity_id or entity_id == "{id}":
|
||||
return {"error": "Company ID required", "status_code": 400, "success": False}
|
||||
comp_uuid = uuid.UUID(entity_id)
|
||||
result = await db.execute(
|
||||
select(Company).where(
|
||||
Company.id == comp_uuid,
|
||||
Company.tenant_id == tenant_id,
|
||||
Company.deleted_at.is_(None),
|
||||
)
|
||||
)
|
||||
company = result.scalar_one_or_none()
|
||||
if company is None:
|
||||
return {"error": "Company not found", "status_code": 404, "success": False}
|
||||
for key in ("name", "industry", "phone", "email", "website", "description"):
|
||||
if key in body:
|
||||
setattr(company, key, body[key])
|
||||
company.updated_by = user_id
|
||||
await db.flush()
|
||||
return {
|
||||
"success": True,
|
||||
"status_code": 200,
|
||||
"data": {"id": str(company.id), "name": company.name, "industry": company.industry},
|
||||
}
|
||||
|
||||
return {"error": f"Unsupported method: {method}", "status_code": 400, "success": False}
|
||||
|
||||
|
||||
async def _exec_contacts(
|
||||
db: AsyncSession,
|
||||
tenant_id: uuid.UUID,
|
||||
user_id: uuid.UUID,
|
||||
method: str,
|
||||
entity_id: str | None,
|
||||
body: dict[str, Any],
|
||||
) -> dict[str, Any]:
|
||||
"""Execute contact operations."""
|
||||
"""Execute contact operations (unified: company + person)."""
|
||||
if method == "GET":
|
||||
result = await db.execute(
|
||||
select(Contact).where(
|
||||
@@ -435,15 +341,16 @@ async def _exec_contacts(
|
||||
return {
|
||||
"success": True,
|
||||
"status_code": 200,
|
||||
"data": [{"id": str(c.id), "name": c.name, "email": c.email} for c in contacts],
|
||||
"data": [{"id": str(c.id), "name": c.name or c.displayname, "email": c.email_1, "type": c.type} for c in contacts],
|
||||
}
|
||||
|
||||
elif method == "POST":
|
||||
contact = Contact(
|
||||
tenant_id=tenant_id,
|
||||
type=body.get("type", "company"),
|
||||
name=body.get("name", "Untitled"),
|
||||
email=body.get("email"),
|
||||
phone=body.get("phone"),
|
||||
email_1=body.get("email"),
|
||||
phone_1=body.get("phone"),
|
||||
created_by=user_id,
|
||||
updated_by=user_id,
|
||||
)
|
||||
@@ -452,7 +359,7 @@ async def _exec_contacts(
|
||||
return {
|
||||
"success": True,
|
||||
"status_code": 201,
|
||||
"data": {"id": str(contact.id), "name": contact.name},
|
||||
"data": {"id": str(contact.id), "name": contact.name, "type": contact.type},
|
||||
}
|
||||
|
||||
return {"error": f"Unsupported method: {method}", "status_code": 400, "success": False}
|
||||
|
||||
Reference in New Issue
Block a user