增加定时同步组织架构
This commit is contained in:
15
lifespan.py
15
lifespan.py
@@ -4,6 +4,20 @@ from fastapi import FastAPI
|
|||||||
from uvicorn.server import logger
|
from uvicorn.server import logger
|
||||||
|
|
||||||
|
|
||||||
|
async def test_init():
|
||||||
|
from service.sync.department import sync_department, check_department_datebase
|
||||||
|
from service.sync.employee import sync_department_user, check_employee_datebase
|
||||||
|
|
||||||
|
if not check_department_datebase():
|
||||||
|
logger.info("[数据库] 开始同步部门 📦")
|
||||||
|
await sync_department()
|
||||||
|
logger.info("[数据库] 同步部门完成 📦")
|
||||||
|
if not check_employee_datebase():
|
||||||
|
logger.info("[数据库] 开始同步员工 📦")
|
||||||
|
await sync_department_user()
|
||||||
|
logger.info("[数据库] 同步员工完成 📦")
|
||||||
|
|
||||||
|
|
||||||
def init_database():
|
def init_database():
|
||||||
from model import create_db_and_tables
|
from model import create_db_and_tables
|
||||||
|
|
||||||
@@ -49,5 +63,6 @@ async def lifespan(app: FastAPI):
|
|||||||
import_router(app)
|
import_router(app)
|
||||||
init_scheduler(app)
|
init_scheduler(app)
|
||||||
await import_mcp_server(app)
|
await import_mcp_server(app)
|
||||||
|
await test_init()
|
||||||
yield
|
yield
|
||||||
logger.info(f"[生命周期] 应用关闭 🔧✅")
|
logger.info(f"[生命周期] 应用关闭 🔧✅")
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from sqlmodel import Session, SQLModel, create_engine
|
from sqlmodel import Session, SQLModel, create_engine
|
||||||
|
|
||||||
from config import Settings
|
from config import Settings
|
||||||
from model.model import Department, Employee, Tenant
|
from model.model import Department, Employee
|
||||||
|
|
||||||
PGSQL = Settings().PGSQL
|
PGSQL = Settings().PGSQL
|
||||||
|
|
||||||
@@ -18,3 +18,9 @@ def get_engine():
|
|||||||
|
|
||||||
def get_session():
|
def get_session():
|
||||||
return Session(get_engine())
|
return Session(get_engine())
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"Department",
|
||||||
|
"Employee",
|
||||||
|
]
|
||||||
|
|||||||
125
model/model.py
125
model/model.py
@@ -1,85 +1,92 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
from sqlalchemy import JSON, Column, DateTime, func
|
from sqlalchemy import Column, DateTime, JSON, func
|
||||||
from sqlmodel import JSON, Field, SQLModel
|
from sqlmodel import Field, SQLModel
|
||||||
|
|
||||||
|
|
||||||
class TenantTimeMixin(SQLModel):
|
class Department(SQLModel, table=True):
|
||||||
tenant_id: int = Field(index=True, description="租户ID")
|
id: Optional[int] = Field(default=None, primary_key=True)
|
||||||
|
|
||||||
created_at: datetime = Field(
|
wecom_dept_id: str = Field(default=None, index=True)
|
||||||
sa_column=Column(
|
|
||||||
DateTime(timezone=True),
|
dname: str = Field(
|
||||||
server_default=func.now(),
|
max_length=100,
|
||||||
nullable=False,
|
description="部门名称",
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
updated_at: datetime = Field(
|
name_en: str = Field(
|
||||||
sa_column=Column(
|
max_length=100,
|
||||||
DateTime(timezone=True),
|
description="部门英文名",
|
||||||
server_default=func.now(),
|
|
||||||
onupdate=func.now(),
|
|
||||||
nullable=False,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
department_leader: list[str] = Field(
|
||||||
|
default_factory=list,
|
||||||
|
sa_column=Column(JSON),
|
||||||
|
description="部门负责人 user_id 列表",
|
||||||
|
)
|
||||||
|
|
||||||
class Department(TenantTimeMixin, SQLModel, table=True):
|
parent_id: str = Field(default=0, index=True)
|
||||||
id: int | None = Field(default=None, primary_key=True)
|
|
||||||
|
|
||||||
dname: str = Field(max_length=100)
|
|
||||||
name_en: str = Field(max_length=100)
|
|
||||||
|
|
||||||
department_leader: list[int] = Field(default_factory=list, sa_column=Column(JSON))
|
|
||||||
|
|
||||||
parent_id: int = Field(default=0, index=True)
|
|
||||||
order: int = Field(default=0)
|
order: int = Field(default=0)
|
||||||
|
|
||||||
|
|
||||||
class Employee(TenantTimeMixin, SQLModel, table=True):
|
|
||||||
id: int | None = Field(default=None, primary_key=True)
|
|
||||||
|
|
||||||
ename: str = Field(max_length=100)
|
|
||||||
|
|
||||||
dept_id: int = Field(foreign_key="department.id", index=True)
|
|
||||||
|
|
||||||
open_userid: str = Field(max_length=100, index=True)
|
|
||||||
|
|
||||||
|
|
||||||
class Tenant(SQLModel, table=True):
|
|
||||||
id: int | None = Field(default=None, primary_key=True)
|
|
||||||
|
|
||||||
# ========== 基础信息 ==========
|
|
||||||
name: str = Field(max_length=100, index=True, description="租户名称 / 企业名称")
|
|
||||||
|
|
||||||
# ========== 企业微信配置 ==========
|
|
||||||
wecom_corp_id: str = Field(max_length=64, index=True, description="企业微信 CorpID")
|
|
||||||
|
|
||||||
wecom_corp_secret: str = Field(max_length=128, description="企业微信应用 Secret")
|
|
||||||
|
|
||||||
wecom_agent_id: int = Field(description="企业微信应用 AgentId")
|
|
||||||
|
|
||||||
wecom_token: str = Field(max_length=64, description="企业微信回调 Token")
|
|
||||||
|
|
||||||
wecom_encoding_aes_key: str = Field(
|
|
||||||
max_length=64, description="企业微信回调 EncodingAESKey"
|
|
||||||
)
|
|
||||||
|
|
||||||
# ========== 时间字段 ==========
|
|
||||||
created_at: datetime = Field(
|
created_at: datetime = Field(
|
||||||
|
default_factory=datetime.now,
|
||||||
sa_column=Column(
|
sa_column=Column(
|
||||||
DateTime(timezone=True),
|
DateTime(timezone=True),
|
||||||
server_default=func.now(),
|
server_default=func.now(),
|
||||||
nullable=False,
|
nullable=False,
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
updated_at: datetime = Field(
|
updated_at: datetime = Field(
|
||||||
|
default_factory=datetime.now,
|
||||||
sa_column=Column(
|
sa_column=Column(
|
||||||
DateTime(timezone=True),
|
DateTime(timezone=True),
|
||||||
server_default=func.now(),
|
server_default=func.now(),
|
||||||
onupdate=func.now(),
|
onupdate=func.now(),
|
||||||
nullable=False,
|
nullable=False,
|
||||||
)
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Employee(SQLModel, table=True):
|
||||||
|
id: Optional[int] = Field(default=None, primary_key=True)
|
||||||
|
|
||||||
|
wecom_user_id: str = Field(default=None, index=True)
|
||||||
|
|
||||||
|
ename: str = Field(
|
||||||
|
max_length=100,
|
||||||
|
description="员工姓名",
|
||||||
|
)
|
||||||
|
|
||||||
|
dept_ids: list[str] = Field(
|
||||||
|
default_factory=list,
|
||||||
|
sa_column=Column(JSON),
|
||||||
|
description="部门ID",
|
||||||
|
)
|
||||||
|
|
||||||
|
open_userid: str | None = Field(
|
||||||
|
default=None,
|
||||||
|
max_length=100,
|
||||||
|
index=True,
|
||||||
|
description="企业微信 user_id",
|
||||||
|
)
|
||||||
|
|
||||||
|
created_at: datetime = Field(
|
||||||
|
default_factory=datetime.now,
|
||||||
|
sa_column=Column(
|
||||||
|
DateTime(timezone=True),
|
||||||
|
server_default=func.now(),
|
||||||
|
nullable=False,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
updated_at: datetime = Field(
|
||||||
|
default_factory=datetime.now,
|
||||||
|
sa_column=Column(
|
||||||
|
DateTime(timezone=True),
|
||||||
|
server_default=func.now(),
|
||||||
|
onupdate=func.now(),
|
||||||
|
nullable=False,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
from fastscheduler import FastScheduler
|
from fastscheduler import FastScheduler
|
||||||
|
from service.sync.department import sync_department
|
||||||
from service import get_wecom
|
from service.sync.employee import sync_department_user
|
||||||
|
|
||||||
scheduler = FastScheduler(quiet=True)
|
scheduler = FastScheduler(quiet=True)
|
||||||
|
|
||||||
|
|
||||||
@scheduler.every(4).hours
|
@scheduler.daily.at("04:00")
|
||||||
async def background_task():
|
async def background_task():
|
||||||
wecom = get_wecom()
|
await sync_department()
|
||||||
|
await sync_department_user()
|
||||||
await wecom.get_departments()
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ def get_wecom_single() -> Wecom:
|
|||||||
wecom = Wecom(Settings().WECOM_CORPID, Settings().WECOM_CORPSECRET)
|
wecom = Wecom(Settings().WECOM_CORPID, Settings().WECOM_CORPSECRET)
|
||||||
WECOM_PROXY = Settings().WECOM_PROXY
|
WECOM_PROXY = Settings().WECOM_PROXY
|
||||||
if WECOM_PROXY and WECOM_PROXY != "":
|
if WECOM_PROXY and WECOM_PROXY != "":
|
||||||
wecom.BASE_URL = WECOM_PROXY
|
wecom.BASE_URL = WECOM_PROXY + wecom.BASE_URL
|
||||||
return wecom
|
return wecom
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
0
service/sync/__init__.py
Normal file
0
service/sync/__init__.py
Normal file
38
service/sync/department.py
Normal file
38
service/sync/department.py
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
from service import get_wecom
|
||||||
|
from model import get_session, Department
|
||||||
|
from sqlmodel import delete, select
|
||||||
|
|
||||||
|
|
||||||
|
async def sync_department():
|
||||||
|
wecom = get_wecom()
|
||||||
|
|
||||||
|
department_res = await wecom.get_departments()
|
||||||
|
|
||||||
|
with get_session() as session:
|
||||||
|
# 删除原来的数据
|
||||||
|
stmt = delete(Department)
|
||||||
|
session.execute(stmt)
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
# DepartmentInfoItem(id=302, name='亮剑一部一组-梁鹏涛', name_en=None, department_leader=['LiangPengTao'], parentid=96, order=100000000)
|
||||||
|
# 插入新的数据
|
||||||
|
for index, item in enumerate(department_res):
|
||||||
|
new_dept = Department(
|
||||||
|
id=index + 1,
|
||||||
|
wecom_dept_id=str(item.id),
|
||||||
|
dname=str(item.name),
|
||||||
|
name_en=str(item.name_en),
|
||||||
|
department_leader=item.department_leader or [],
|
||||||
|
parent_id=str(item.parentid),
|
||||||
|
order=item.order or 0,
|
||||||
|
)
|
||||||
|
session.add(new_dept)
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
|
||||||
|
def check_department_datebase():
|
||||||
|
with get_session() as session:
|
||||||
|
has = session.exec(select(Department)).first()
|
||||||
|
if not has:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
37
service/sync/employee.py
Normal file
37
service/sync/employee.py
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
from service import get_wecom
|
||||||
|
from model import get_session, Employee
|
||||||
|
from sqlmodel import delete, select
|
||||||
|
|
||||||
|
|
||||||
|
async def sync_department_user():
|
||||||
|
wecom = get_wecom()
|
||||||
|
|
||||||
|
dept_res = await wecom.get_departments()
|
||||||
|
|
||||||
|
with get_session() as session:
|
||||||
|
# 删除原来的数据
|
||||||
|
stmt = delete(Employee)
|
||||||
|
session.execute(stmt)
|
||||||
|
session.commit()
|
||||||
|
index_id = 1
|
||||||
|
for dept in dept_res:
|
||||||
|
user_res = await wecom.get_user_in_department(dept.id)
|
||||||
|
for item in user_res:
|
||||||
|
new_employee = Employee(
|
||||||
|
id=index_id,
|
||||||
|
wecom_user_id=item.userid,
|
||||||
|
ename=item.name,
|
||||||
|
dept_ids=[str(i) for i in item.department],
|
||||||
|
open_userid=item.open_userid,
|
||||||
|
)
|
||||||
|
index_id += 1
|
||||||
|
session.add(new_employee)
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
|
||||||
|
def check_employee_datebase():
|
||||||
|
with get_session() as session:
|
||||||
|
has = session.exec(select(Employee)).first()
|
||||||
|
if not has:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
from wecom.exceptions.general import SDKException
|
from service.wecom.exceptions.general import SDKException
|
||||||
from wecom.schemas.token import AccessTokenInfo, AccessTokenParams
|
from service.wecom.schemas.token import AccessTokenInfo, AccessTokenParams
|
||||||
from wecom.utils.requests import HttpxRequest
|
from service.wecom.utils.requests import HttpxRequest
|
||||||
|
|
||||||
BASE_URL: str = "https://qyapi.weixin.qq.com/cgi-bin"
|
BASE_URL: str = "https://qyapi.weixin.qq.com/cgi-bin"
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
from wecom.exceptions.general import SDKException
|
from service.wecom.exceptions.general import SDKException
|
||||||
from wecom.modules.base import WecomBaseClient
|
from service.wecom.modules.base import WecomBaseClient
|
||||||
from wecom.schemas.departments import (
|
from service.wecom.schemas.departments import (
|
||||||
CreateDepartmentInfo,
|
CreateDepartmentInfo,
|
||||||
CreateDepartmentParams,
|
CreateDepartmentParams,
|
||||||
DepartmentInfo,
|
DepartmentInfo,
|
||||||
|
DepartmentInfoItem,
|
||||||
UpdateDepartmentInfo,
|
UpdateDepartmentInfo,
|
||||||
UpdateDepartmentParams,
|
UpdateDepartmentParams,
|
||||||
)
|
)
|
||||||
from wecom.utils.requests import HttpxRequest
|
from service.wecom.utils.requests import HttpxRequest
|
||||||
|
|
||||||
|
|
||||||
class WecomDepartmentClient(WecomBaseClient):
|
class WecomDepartmentClient(WecomBaseClient):
|
||||||
@@ -63,7 +64,7 @@ class WecomDepartmentClient(WecomBaseClient):
|
|||||||
else:
|
else:
|
||||||
raise SDKException(resp.errcode, resp.errmsg)
|
raise SDKException(resp.errcode, resp.errmsg)
|
||||||
|
|
||||||
async def get_departments(self, id: int = None) -> list[DepartmentInfo]:
|
async def get_departments(self, id: int = None) -> list[DepartmentInfoItem]:
|
||||||
"""
|
"""
|
||||||
获取部门列表
|
获取部门列表
|
||||||
@param id: 部门id。获取指定部门及其下的子部门。
|
@param id: 部门id。获取指定部门及其下的子部门。
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
from typing import Literal
|
from typing import Literal
|
||||||
|
|
||||||
from wecom.exceptions.general import SDKException
|
from service.wecom.exceptions.general import SDKException
|
||||||
from wecom.modules.base import WecomBaseClient
|
from service.wecom.modules.base import WecomBaseClient
|
||||||
from wecom.schemas.message import (
|
from service.wecom.schemas.message import (
|
||||||
MessageParams,
|
MessageParams,
|
||||||
RecallMessageInfo,
|
RecallMessageInfo,
|
||||||
RecallMessageParams,
|
RecallMessageParams,
|
||||||
SendMessageInfo,
|
SendMessageInfo,
|
||||||
)
|
)
|
||||||
from wecom.utils.requests import HttpxRequest
|
from service.wecom.utils.requests import HttpxRequest
|
||||||
|
|
||||||
|
|
||||||
class WecomMessageClient(WecomBaseClient):
|
class WecomMessageClient(WecomBaseClient):
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from wecom.modules.base import WecomBaseClient
|
from service.wecom.modules.base import WecomBaseClient
|
||||||
from wecom.modules.department import WecomDepartmentClient
|
from service.wecom.modules.department import WecomDepartmentClient
|
||||||
from wecom.modules.message import WecomMessageClient
|
from service.wecom.modules.message import WecomMessageClient
|
||||||
from wecom.modules.users import WecomUsersClient
|
from service.wecom.modules.users import WecomUsersClient
|
||||||
|
|
||||||
|
|
||||||
class Wecom(
|
class Wecom(
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
from wecom.exceptions.general import SDKException
|
from service.wecom.exceptions.general import SDKException
|
||||||
from wecom.modules.base import WecomBaseClient
|
from service.wecom.modules.base import WecomBaseClient
|
||||||
from wecom.schemas.departments import DepartmentInfo
|
from service.wecom.schemas.departments import DepartmentInfo
|
||||||
from wecom.schemas.users import DepartmentUserDetailInfo, DepartmentUserInfo, UserInfo
|
from service.wecom.schemas.users import (
|
||||||
from wecom.utils.requests import HttpxRequest
|
DepartmentUserDetailInfo,
|
||||||
|
DepartmentUserInfo,
|
||||||
|
UserInfo,
|
||||||
|
UserSimpleInfo,
|
||||||
|
)
|
||||||
|
from service.wecom.utils.requests import HttpxRequest
|
||||||
|
|
||||||
|
|
||||||
class WecomUsersClient(WecomBaseClient):
|
class WecomUsersClient(WecomBaseClient):
|
||||||
@@ -45,7 +50,7 @@ class WecomUsersClient(WecomBaseClient):
|
|||||||
else:
|
else:
|
||||||
raise SDKException(resp.errcode, resp.errmsg)
|
raise SDKException(resp.errcode, resp.errmsg)
|
||||||
|
|
||||||
async def get_user_in_department(self, department_id: int) -> dict:
|
async def get_user_in_department(self, department_id: int) -> list[UserSimpleInfo]:
|
||||||
"""
|
"""
|
||||||
读取部门成员简要信息
|
读取部门成员简要信息
|
||||||
@param department_id: 获取的部门id
|
@param department_id: 获取的部门id
|
||||||
@@ -61,7 +66,7 @@ class WecomUsersClient(WecomBaseClient):
|
|||||||
resp = DepartmentUserInfo(**await HttpxRequest.get(url=url, params=params))
|
resp = DepartmentUserInfo(**await HttpxRequest.get(url=url, params=params))
|
||||||
|
|
||||||
if resp.errcode == 0:
|
if resp.errcode == 0:
|
||||||
return resp.model_dump(exclude={"errcode", "errmsg"})
|
return resp.userlist
|
||||||
else:
|
else:
|
||||||
raise SDKException(resp.errcode, resp.errmsg)
|
raise SDKException(resp.errcode, resp.errmsg)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from typing import AnyStr, List
|
from typing import List
|
||||||
|
|
||||||
from wecom.schemas.base import BaseSchema
|
from service.wecom.schemas.base import BaseSchema
|
||||||
|
|
||||||
|
|
||||||
class CreateDepartmentParams(BaseSchema):
|
class CreateDepartmentParams(BaseSchema):
|
||||||
@@ -26,23 +26,23 @@ class UpdateDepartmentParams(CreateDepartmentParams): ...
|
|||||||
|
|
||||||
class UpdateDepartmentInfo(BaseSchema):
|
class UpdateDepartmentInfo(BaseSchema):
|
||||||
errcode: int
|
errcode: int
|
||||||
errmsg: AnyStr
|
errmsg: str
|
||||||
|
|
||||||
|
|
||||||
class CreateDepartmentInfo(BaseSchema):
|
class CreateDepartmentInfo(BaseSchema):
|
||||||
errcode: int
|
errcode: int
|
||||||
errmsg: AnyStr
|
errmsg: str
|
||||||
id: int
|
id: int
|
||||||
|
|
||||||
|
|
||||||
class DepartmentInfo(BaseSchema):
|
class DepartmentInfoItem(BaseSchema):
|
||||||
"""
|
"""
|
||||||
部门单体响应数据
|
部门单体响应数据
|
||||||
"""
|
"""
|
||||||
|
|
||||||
id: int
|
id: int
|
||||||
name: AnyStr
|
name: str
|
||||||
name_en: AnyStr | None = None
|
name_en: str | None = None
|
||||||
department_leader: List[str] | None = None
|
department_leader: List[str] | None = None
|
||||||
parentid: int | None = None
|
parentid: int | None = None
|
||||||
order: int | None = None
|
order: int | None = None
|
||||||
@@ -54,5 +54,5 @@ class DepartmentInfo(BaseSchema):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
errcode: int
|
errcode: int
|
||||||
errmsg: AnyStr
|
errmsg: str
|
||||||
department: List[DepartmentInfo]
|
department: List[DepartmentInfoItem]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from typing import AnyStr, Literal
|
from typing import Literal
|
||||||
|
|
||||||
from wecom.schemas.base import BaseSchema
|
from service.wecom.schemas.base import BaseSchema
|
||||||
|
|
||||||
|
|
||||||
class MessageParams(BaseSchema):
|
class MessageParams(BaseSchema):
|
||||||
@@ -24,9 +24,9 @@ class MessageParams(BaseSchema):
|
|||||||
touser、toparty、totag不能同时为空,后面不再强调
|
touser、toparty、totag不能同时为空,后面不再强调
|
||||||
"""
|
"""
|
||||||
|
|
||||||
touser: AnyStr | None = None
|
touser: str | None = None
|
||||||
toparty: AnyStr | None = None
|
toparty: str | None = None
|
||||||
totag: AnyStr | None = None
|
totag: str | None = None
|
||||||
msgtype: Literal[
|
msgtype: Literal[
|
||||||
"text", "image", "voice", "video", "textcard", "news", "mpnews", "markdown"
|
"text", "image", "voice", "video", "textcard", "news", "mpnews", "markdown"
|
||||||
]
|
]
|
||||||
@@ -55,13 +55,13 @@ class SendMessageInfo(BaseSchema):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
errcode: int
|
errcode: int
|
||||||
errmsg: AnyStr
|
errmsg: str
|
||||||
invaliduser: AnyStr | None = None
|
invaliduser: str | None = None
|
||||||
invalidparty: AnyStr | None = None
|
invalidparty: str | None = None
|
||||||
invalidtag: AnyStr | None = None
|
invalidtag: str | None = None
|
||||||
unlicenseduser: AnyStr | None = None
|
unlicenseduser: str | None = None
|
||||||
msgid: AnyStr | None = None
|
msgid: str | None = None
|
||||||
response_code: AnyStr | None = None
|
response_code: str | None = None
|
||||||
|
|
||||||
|
|
||||||
class SendMessageInvalid(BaseSchema):
|
class SendMessageInvalid(BaseSchema):
|
||||||
@@ -70,11 +70,11 @@ class SendMessageInvalid(BaseSchema):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
errmsg: AnyStr
|
errmsg: str
|
||||||
invaliduser: AnyStr | None = None
|
invaliduser: str | None = None
|
||||||
invalidparty: AnyStr | None = None
|
invalidparty: str | None = None
|
||||||
invalidtag: AnyStr | None = None
|
invalidtag: str | None = None
|
||||||
unlicenseduser: AnyStr | None = None
|
unlicenseduser: str | None = None
|
||||||
|
|
||||||
|
|
||||||
class RecallMessageParams(BaseSchema):
|
class RecallMessageParams(BaseSchema):
|
||||||
@@ -82,7 +82,7 @@ class RecallMessageParams(BaseSchema):
|
|||||||
撤回消息请求参数
|
撤回消息请求参数
|
||||||
"""
|
"""
|
||||||
|
|
||||||
msgid: AnyStr
|
msgid: str
|
||||||
|
|
||||||
|
|
||||||
class RecallMessageInfo(BaseSchema):
|
class RecallMessageInfo(BaseSchema):
|
||||||
@@ -91,4 +91,4 @@ class RecallMessageInfo(BaseSchema):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
errcode: int
|
errcode: int
|
||||||
errmsg: AnyStr
|
errmsg: str
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from wecom.schemas.base import BaseSchema
|
from service.wecom.schemas.base import BaseSchema
|
||||||
|
|
||||||
|
|
||||||
class AccessTokenParams(BaseSchema):
|
class AccessTokenParams(BaseSchema):
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from typing import AnyStr, List
|
from typing import List
|
||||||
|
|
||||||
from wecom.schemas.base import BaseSchema
|
from service.wecom.schemas.base import BaseSchema
|
||||||
|
|
||||||
|
|
||||||
class UserInfo(BaseSchema):
|
class UserInfo(BaseSchema):
|
||||||
@@ -9,31 +9,31 @@ class UserInfo(BaseSchema):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
errcode: int
|
errcode: int
|
||||||
errmsg: AnyStr
|
errmsg: str
|
||||||
userid: AnyStr | None = None
|
userid: str | None = None
|
||||||
name: AnyStr | None = None
|
name: str | None = None
|
||||||
department: List[int] | None = None
|
department: List[int] | None = None
|
||||||
position: AnyStr | None = None
|
position: str | None = None
|
||||||
moblie: AnyStr | None = None
|
moblie: str | None = None
|
||||||
gender: int | None = None
|
gender: int | None = None
|
||||||
email: AnyStr | None = None
|
email: str | None = None
|
||||||
status: int | None = None
|
status: int | None = None
|
||||||
|
|
||||||
|
|
||||||
class UserSimpleInfo(BaseSchema):
|
class UserSimpleInfo(BaseSchema):
|
||||||
userid: AnyStr
|
userid: str
|
||||||
name: AnyStr
|
name: str
|
||||||
department: List[int]
|
department: List[int]
|
||||||
open_userid: AnyStr | None = None
|
open_userid: str | None = None
|
||||||
|
|
||||||
|
|
||||||
class DepartmentUserInfo(BaseSchema):
|
class DepartmentUserInfo(BaseSchema):
|
||||||
errcode: int
|
errcode: int
|
||||||
errmsg: AnyStr
|
errmsg: str
|
||||||
userlist: List[UserSimpleInfo]
|
userlist: List[UserSimpleInfo]
|
||||||
|
|
||||||
|
|
||||||
class DepartmentUserDetailInfo(BaseSchema):
|
class DepartmentUserDetailInfo(BaseSchema):
|
||||||
errcode: int
|
errcode: int
|
||||||
errmsg: AnyStr
|
errmsg: str
|
||||||
userlist: List[UserInfo]
|
userlist: List[UserInfo]
|
||||||
|
|||||||
Reference in New Issue
Block a user