Files
FastapiAdmin/backend/app/api/v1/module_system/customer/model.py
T
zhangtao 0c86069efa feat: 统一状态字段类型为字符串并重构基础类型
refactor: 重构前后端状态字段类型从布尔值改为字符串
feat: 新增基础类型定义和通用类型接口
refactor: 移除不必要的时间范围字段并统一使用created_time
style: 更新前端组件以匹配新的字段命名
docs: 更新接口文档和类型定义
2025-11-27 23:47:23 +08:00

57 lines
1.9 KiB
Python

# -*- coding: utf-8 -*-
from typing import TYPE_CHECKING
from sqlalchemy import String
from sqlalchemy.orm import Mapped, mapped_column, relationship, validates
from app.core.base_model import ModelMixin, UserMixin, TenantMixin
if TYPE_CHECKING:
from app.api.v1.module_system.user.model import UserModel
class CustomerModel(ModelMixin, UserMixin, TenantMixin):
"""
客户表
客户是租户下的业务实体,用于业务数据的二级隔离:
- 一个租户可以有多个客户
- 客户用户(user.customer_id>0)只能访问其所属客户的数据
- 客户表需要tenant_id(属于哪个租户)
- 客户表不需要customer_id(客户不属于客户,避免循环)
典型场景:
- 代理商系统: 租户=总公司, 客户=各地代理商
- SaaS平台: 租户=企业, 客户=企业下的子公司/部门
"""
__tablename__: str = 'system_customer'
__table_args__: dict[str, str] = ({'comment': '客户表'})
__loader_options__: list[str] = ["created_by", "updated_by", "tenant"]
name: Mapped[str] = mapped_column(String(64), nullable=False, comment='客户名称')
code: Mapped[str] = mapped_column(String(20), nullable=False, index=True, comment='客户编码')
users: Mapped[list["UserModel"]] = relationship(
back_populates="customer",
foreign_keys="UserModel.customer_id",
lazy="selectin"
)
@validates('name')
def validate_name(self, key: str, name: str) -> str:
"""验证名称不为空"""
if not name or not name.strip():
raise ValueError('名称不能为空')
return name
@validates('code')
def validate_code(self, key: str, code: str) -> str:
"""验证编码格式校验"""
if not code or not code.strip():
raise ValueError('编码不能为空')
if not code.isalnum():
raise ValueError('编码只能包含字母和数字')
return code