Files
wecom_it_smart_desk/backend/app/models/business_contact.py
T

187 lines
5.8 KiB
Python
Raw Normal View History

# =============================================================================
# 企微IT智能服务台 — 业务联系人模型
# =============================================================================
# 说明:对应数据库 business_contacts 表,存储非IT业务部门联系人信息
# 当员工提出的问题不属于IT服务台服务范围时,系统通过 Dify 意图识别
# 判定业务类别,从本表查询对应联系人,推送名片卡片到聊天中。
# 员工点击「联系TA」可跳转企微单聊(openEnterpriseChat)。
#
# 业务类别(business_category)取值:
# 行政 / 人力资源 / 财务 / 法务 / 行政-物业
# =============================================================================
from datetime import datetime
from sqlalchemy import Boolean, DateTime, Index, Integer, String
from sqlalchemy.orm import Mapped, mapped_column
from app.database import Base
class BusinessContact(Base):
"""业务联系人模型 — 对应 business_contacts 表。
存储非IT业务部门联系人信息,用于路由推荐功能。
当 Dify 判定消息为非IT业务路由时,按 business_category 查询本表,
取第一条 is_active=True 的联系人,推送名片卡片。
Attributes:
id: 主键,自增
name: 联系人姓名
gender: 性别(male/female
department: 部门名称(如「行政部」)
position: 岗位(如「设备管理岗」)
responsibility: 负责业务描述(如「打印机/复印机/扫描仪」)
extension: 分机号
service_area: 服务区域/办公地点
wecom_userid: 企微用户ID(用于 openEnterpriseChat 调用)
avatar_url: 头像URL(为空时用姓名首字渲染)
business_category: 业务类别(行政/人力资源/财务/法务/行政-物业)
is_active: 是否启用
created_at: 创建时间
updated_at: 更新时间
"""
__tablename__ = "business_contacts"
# 主键:自增整数
id: Mapped[int] = mapped_column(
Integer,
primary_key=True,
autoincrement=True,
comment="主键",
)
# 联系人姓名
name: Mapped[str] = mapped_column(
String(50),
nullable=False,
comment="联系人姓名",
)
# 性别(male/female
gender: Mapped[str] = mapped_column(
String(10),
nullable=False,
default="male",
comment="性别(male/female",
)
# 部门名称
department: Mapped[str] = mapped_column(
String(100),
nullable=False,
comment="部门名称",
)
# 岗位
position: Mapped[str] = mapped_column(
String(100),
nullable=False,
comment="岗位",
)
# 负责业务描述
responsibility: Mapped[str] = mapped_column(
String(500),
nullable=False,
comment="负责业务描述",
)
# 分机号
extension: Mapped[str | None] = mapped_column(
String(20),
nullable=True,
default=None,
comment="分机号",
)
# 服务区域/办公地点
service_area: Mapped[str | None] = mapped_column(
String(200),
nullable=True,
default=None,
comment="服务区域/办公地点",
)
# 企微用户ID(用于 wx.invoke('openEnterpriseChat', {userids: '...'}) 调用)
wecom_userid: Mapped[str] = mapped_column(
String(100),
nullable=False,
comment="企微用户ID",
)
# 头像URL(为空时前端用姓名首字渐变色块渲染)
avatar_url: Mapped[str | None] = mapped_column(
String(500),
nullable=True,
default=None,
comment="头像URL(为空用姓名首字渲染)",
)
# 业务类别(与 Dify 输出的 business_category 对应)
# 取值:行政 / 人力资源 / 财务 / 法务 / 行政-物业
business_category: Mapped[str] = mapped_column(
String(50),
nullable=False,
comment="业务类别(行政/人力资源/财务/法务/行政-物业)",
)
# 是否启用
is_active: Mapped[bool] = mapped_column(
Boolean,
nullable=False,
default=True,
comment="是否启用",
)
# 创建时间
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
nullable=False,
default=datetime.now,
comment="创建时间",
)
# 更新时间
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
nullable=False,
default=datetime.now,
onupdate=datetime.now,
comment="更新时间",
)
# 索引定义
__table_args__ = (
# 按业务类别 + 是否启用查询(路由推荐时使用)
Index("idx_business_contacts_category", "business_category", "is_active"),
)
def to_dict(self) -> dict:
"""将联系人信息转为字典(用于 extra_data 透传给前端)。
Returns:
dict: 联系人完整信息
"""
return {
"id": self.id,
"name": self.name,
"gender": self.gender,
"department": self.department,
"position": self.position,
"responsibility": self.responsibility,
"extension": self.extension or "",
"service_area": self.service_area or "",
"wecom_userid": self.wecom_userid,
"avatar_url": self.avatar_url or "",
"business_category": self.business_category,
}
def __repr__(self) -> str:
"""联系人对象的字符串表示,方便调试。"""
return (
f"<BusinessContact(id={self.id}, name={self.name}, "
f"category={self.business_category})>"
)