Files
nexus/Project/fonrey/DATA_MODEL/DATA_MODEL_SETTING.md
Shen Wei 712a33fbac docs: 新增系统配置模块PRD及数据模型文档,更新TASK.md
- 新增 PRD/系统配置/系统配置模块PRD.md(v0.1 Draft)
  - MVP 范围:US-SETTING-001-A(Lookup Items)、B(房源字段必填规则)、C(客源录入规则)
- 新增 PRD/系统配置/系统配置数据模型设计说明_for_Atlas.md
- 新增 PRD/系统配置/系统配置参数数据.md(竞品参数数据)
- 删除旧版 PRD/系统配置/系统配置.md(已被新PRD替代)
- 新增 DATA_MODEL/DATA_MODEL_SETTING.md(系统配置数据模型)
- 新增 DATA_MODEL/ENUMS.md(枚举定义与约定)
- 新增 AGENTS.md(AI Agent 开发规范)
- 更新 PRD/TASK.md:US-SETTING-001 拆分为 A/B/C 三个子任务,修正参考文档路径与验收标准
- 新增 VIBE_CODING_开工前缺失清单.md
- 新增 TECH_STACK/房源管理技术方案.md
- 更新 DATA_MODEL/DATA_MODEL.md、DATA_MODEL_CLIENT.md、DATA_MODEL_LOGIN.md
- 更新 PRD/PRD_MVP.md、PRD/权限管理/权限管理模块PRD.md
- 更新 TECH_STACK/TECH_STACK.md、权限管理系统技术方案.md
- 更新 UI_DESIGN/preview.html、UI_SYSTEM/UI_SYSTEM.md
- 新增 prompt/PRD - 为系统设置生成PRD设计文档.md、更新 prompt 模板
2026-04-27 15:33:12 +08:00

17 KiB
Raw Blame History

For AI assistants: Read this entire file before writing any code. All decisions here are final. Do not suggest alternatives unless asked.

Fonrey — 系统配置模块数据模型DATA_MODEL_SETTING

定位:本文件是 apps/setting/ 模块的数据模型权威来源。
版本v1.0 | 日期2026-04-27
关联 PRDPRD/系统配置/系统配置模块PRD.md
关联文档DATA_MODEL/ENUMS.mdDATA_MODEL/DATA_MODEL.md


一、模块定位与架构边界

1.1 系统配置模块职责

系统配置模块(apps/setting/)负责管理三类性质不同的配置数据:

类型 说明 Schema
A. 固定系统枚举 平台级固定值域,所有租户共享 enum_labels Publicshared
B. 可配置枚举 各租户选项不同,管理员可增删排序 lookup_groups + lookup_items Tenant
C. 行为规则与开关 标量配置开关 + 字段必填规则 tenant_settings + field_requirement_rules Tenant

重要区分

  • 类型 A (enum_labels) 已在 DATA_MODEL/ENUMS.md 完整定义,本文件不重复
  • 类型 B/C 均存于 租户 Schema,由租户管理员通过界面维护
  • apps/setting/tenant_apps shared_apps

1.2 依赖关系

apps/setting/
    ├── 依赖 → core.cacheRedis统一租户前缀
    ├── 依赖 → org.Staffcreated_by / updated_by FK
    └── 被依赖 ← apps/property读取字段规则、枚举选项
              ← apps/client读取查重范围、枚举选项

二、可配置枚举表(类型 B

2.1 lookup_groups(枚举分组)

每个分组代表一类可配置枚举(如「客源来源」「跟进目的」),由研发预置,租户管理员不可新增或删除分组,仅可管理分组内的选项。

-- ============================================================
-- 可配置枚举分组Tenant Schema
-- 研发预置,租户不可修改分组本身
-- ============================================================
CREATE TABLE lookup_groups (
    id          UUID        PRIMARY KEY DEFAULT gen_random_uuid(),
    module      VARCHAR(50)  NOT NULL,   -- 'client' | 'property'
    key         VARCHAR(100) NOT NULL,   -- 'source' | 'follow_purpose'
    label_zh    VARCHAR(50)  NOT NULL,   -- 界面显示名称,如「客源来源」
    description TEXT,                   -- 说明文案(前端 tooltip 使用)
    sort_order  SMALLINT     NOT NULL DEFAULT 0,
    created_at  TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
    updated_at  TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
    UNIQUE (module, key)
);

MVP 预置分组(种子数据)

module key label_zh description
client source 客源来源 客源从何处获取,用于来源渠道分析
client follow_purpose 跟进目的 客源跟进时选择的目的分类
property source 房源来源 房源从何处获取

2.2 lookup_items(枚举选项)

-- ============================================================
-- 可配置枚举选项Tenant Schema
-- 租户管理员可增删排序is_system=True 的预制项不可物理删除
-- ============================================================
CREATE TABLE lookup_items (
    id          UUID        PRIMARY KEY DEFAULT gen_random_uuid(),
    group_id    UUID         NOT NULL REFERENCES lookup_groups(id) ON DELETE CASCADE,
    value       VARCHAR(100) NOT NULL,   -- 存储值,英文 snake_case如 'door_to_door'
    label_zh    VARCHAR(50)  NOT NULL,   -- 显示文本(如「上门」)
    is_system   BOOLEAN      NOT NULL DEFAULT FALSE, -- True=系统预制,不可删除,仅可停用
    is_active   BOOLEAN      NOT NULL DEFAULT TRUE,
    sort_order  SMALLINT     NOT NULL DEFAULT 0,
    created_by  UUID         REFERENCES staff(id) ON DELETE SET NULL,  -- 系统预制时为 NULL
    created_at  TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
    updated_at  TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
    UNIQUE (group_id, value)
);

CREATE INDEX idx_lookup_items_group_active
    ON lookup_items(group_id, is_active, sort_order);

关键约束

  • is_system = TRUE 的记录不允许物理删除Service 层强制拦截)
  • is_active = FALSE 后:前端录入下拉不展示;历史已选该值的记录保留原值,展示时追加「(已停用)」后缀
  • value 一旦写入不允许修改(历史数据依赖);如需改名,停用旧项、新增新项

2.3 MVP 预置种子数据(is_system = TRUE

以下选项在租户初始化时自动写入:

客源来源(client.source

value label_zh sort_order
store_reception 门店接待 1
old_client_referral 老客户转介绍 2
stationed_dispatch 驻守派单 3
walk_in 上门 4
online_58 网络-58同城 5
online_anjuke 网络-安居客 6
wechat 微信 7
friend_referral 朋友介绍 8

跟进目的(client.follow_purpose

value label_zh sort_order
callback 回拨 1
push_property 推房 2
showing 带看 3
maintain 维护 4
other 其他 5

房源来源(property.source

value label_zh sort_order
proactive_development 主动开发 1
owner_walk_in 业主上门 2
old_client_referral 老客户转介绍 3
online_inquiry 网络来电 4

三、行为规则与开关(类型 C

3.1 tenant_settings(标量配置键值表)

存储开关bool、阈值int、单选枚举string等标量类型配置项。

-- ============================================================
-- 租户标量配置键值对Tenant Schema
-- ============================================================
CREATE TABLE tenant_settings (
    id          UUID        PRIMARY KEY DEFAULT gen_random_uuid(),
    category    VARCHAR(50)  NOT NULL,   -- 配置分类:'client' | 'property' | 'showroom'
    key         VARCHAR(100) NOT NULL,   -- 配置 key如 'duplicate_check_scope'
    value       JSONB        NOT NULL,   -- 存储任意类型bool/int/str如 {"v": "self"}
    value_type  VARCHAR(20)  NOT NULL    -- 'bool' | 'int' | 'string' | 'enum'(用于前端渲染控件)
                CHECK (value_type IN ('bool', 'int', 'string', 'enum')),
    updated_by  UUID         REFERENCES staff(id) ON DELETE SET NULL,
    updated_at  TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
    UNIQUE (category, key)
);

CREATE INDEX idx_tenant_settings_category ON tenant_settings(category);

存储格式约定

  • bool{"v": true}{"v": false}
  • int{"v": 30}
  • string{"v": "some_value"}
  • enum{"v": "self", "choices": ["self", "dept", "company"]}choices 由代码硬编码,不存 DB

MVP 阶段预置 key

category key value_type 默认值 说明
client duplicate_check_scope enum {"v": "self"} 新增私客查重范围:self(本人)/ dept(本部门)/ company(全公司)

未来 P1 阶段可按需追加 key无需修改表结构。


3.2 field_requirement_rules(字段必填规则表)

按「模块 × 房源用途 × 交易状态 × 字段」四元组确定一条规则,控制录入界面的字段显示状态。

-- ============================================================
-- 字段必填/隐藏规则Tenant Schema
-- MVP 仅支持 module='property'
-- ============================================================
CREATE TABLE field_requirement_rules (
    id           UUID        PRIMARY KEY DEFAULT gen_random_uuid(),
    module       VARCHAR(20)  NOT NULL,  -- 'property' | 'client'MVP 只用 'property'
    entity_type  VARCHAR(50)  NOT NULL,  -- 与 property.property_type CHECK 约束值对齐
                                         -- 'residential'|'villa'|'commercial_residential'|'shop'|'office'|'other'
    trade_status VARCHAR(20)  NOT NULL,  -- 交易大类:'sale'|'rent'|'sale_rent'|'*'(全部)
                 CHECK (trade_status IN ('sale', 'rent', 'sale_rent', '*')),
    field_key    VARCHAR(50)  NOT NULL,  -- 字段 key如 'orientation'|'decoration'|'floor'
    requirement  VARCHAR(10)  NOT NULL   -- 规则值
                 CHECK (requirement IN ('required', 'optional', 'hidden')),
    updated_by   UUID         REFERENCES staff(id) ON DELETE SET NULL,
    updated_at   TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
    UNIQUE (module, entity_type, trade_status, field_key)
);

CREATE INDEX idx_field_req_lookup
    ON field_requirement_rules(module, entity_type, trade_status);

property.property_type 对齐说明

entity_type 的值域与 property.property_type 的 CHECK 约束完全一致:

entity_type property_type label_zh
residential 住宅
villa 别墅
commercial_residential 商住
shop 商铺
office 写字楼
other 其他

trade_statusproperty.status 的映射关系

trade_status 对应 property.status 值
sale for_sale
rent for_rent
sale_rent for_sale_rent
* 所有状态通用规则fallback

重要trade_status 是录入场景的交易意图分类,不是 property.status 的完整枚举。规则匹配逻辑:先查精确匹配(entity_type + trade_status),不存在则查 * 通配规则。

MVP 初始规则(研发预置,管理员可覆盖)

module entity_type trade_status field_key requirement
property residential sale orientation optional
property residential sale decoration optional
property residential sale floor optional
property residential sale building_area required
property residential sale inner_area optional
property residential sale room_layout required
property residential rent decoration optional
property residential rent floor optional
property residential rent building_area required
property residential rent room_layout required

MVP 可配置字段范围(对应 PRD AC-4

field_key 说明 字段类型
orientation 朝向(property.orientation 枚举) 枚举
decoration 装修情况(property.decoration 枚举) 枚举
floor 所在楼层/总楼层 数值
building_area 建筑面积(㎡) 数值
inner_area 套内面积(㎡) 数值
room_layout 房型(室/厅/卫) 数值组
ownership_years 产权年限(年) 数值
parking_count 车位数 数值

四、服务层设计

所有业务模块禁止直接查询配置表,必须通过统一服务层读取:

# apps/setting/services/tenant_settings_service.py

class TenantSettingsService:
    """
    系统配置统一读取服务。
    所有配置均经 Redis 缓存TTL 5min写入时主动 invalidate。
    Redis Key 规范:{tenant_schema}:setting:{type}:{key}
    """

    def get(self, category: str, key: str, default=None):
        """
        读取标量配置tenant_settings 表)
        Cache Key: {tenant_schema}:setting:kv:{category}.{key}
        返回 JSONB value 字段中 'v' 的值(已解包)
        """

    def set(self, category: str, key: str, value, updated_by_id) -> None:
        """
        写入标量配置 + 主动 invalidate 缓存
        """

    def get_lookup_items(self, module: str, key: str) -> list[dict]:
        """
        获取可配置枚举选项lookup_items 表)
        仅返回 is_active=True 的项,按 sort_order 排序
        Cache Key: {tenant_schema}:setting:lookup:{module}.{key}
        返回格式:[{"value": "walk_in", "label_zh": "上门", "is_system": True}, ...]
        """

    def get_field_requirements(
        self, module: str, entity_type: str, trade_status: str
    ) -> dict[str, str]:
        """
        获取字段必填规则
        匹配顺序:精确匹配(entity_type + trade_status) > 通配规则(trade_status='*')
        Cache Key: {tenant_schema}:setting:field_req:{module}.{entity_type}.{trade_status}
        返回格式:{"orientation": "optional", "decoration": "required", ...}
        """

五、Redis 缓存键规范

用途 Cache Key TTL 失效触发
标量配置 {schema}:setting:kv:{category}.{key} 300s TenantSettingsService.set()
可配置枚举 {schema}:setting:lookup:{module}.{key} 300s 管理员保存 lookup_items
字段规则 {schema}:setting:field_req:{module}.{entity_type}.{trade_status} 300s 管理员保存 field_requirement_rules
客源规则(整体) {schema}:setting:client_rules 300s 任意客源规则变更

TTL 300s5 分钟)对应 PRD 成功指标「配置变更生效时延 ≤ 5 分钟」。


六、目录结构

apps/setting/
├── models/
│   ├── lookup.py              # LookupGroup, LookupItem
│   └── setting.py             # TenantSetting, FieldRequirementRule
├── services/
│   └── tenant_settings_service.py  # 统一配置读取服务(禁止直接查表)
├── views/
│   ├── lookup_views.py        # 参数配置页面US-SETTING-001-A
│   ├── field_rule_views.py    # 房源字段规则US-SETTING-001-B
│   └── client_rule_views.py   # 客源规则US-SETTING-001-C
├── templates/setting/
├── fixtures/
│   ├── lookup_groups.json     # 分组种子数据3 组)
│   ├── lookup_items.json      # 选项种子数据is_system=True
│   ├── tenant_settings.json   # 默认配置种子数据
│   └── field_requirement_rules.json  # 默认字段规则
├── migrations/
│   ├── 0001_lookup_groups.py
│   ├── 0002_lookup_items.py
│   ├── 0003_tenant_settings.py
│   └── 0004_field_requirement_rules.py
└── urls.py

七、迁移执行顺序

0001_lookup_groups        # 先建分组表(无外键依赖)
0002_lookup_items         # 再建选项表(依赖 lookup_groups + staff
0003_tenant_settings      # 独立,无外键依赖
0004_field_requirement_rules  # 独立,仅依赖 staff

迁移执行后,通过 call_command('loaddata', 'lookup_groups') 等方式加载 fixtures 种子数据。


八、关键约束与禁止项

约束 规则
不可删除系统预制项 lookup_items.is_system = True 的记录Service 层硬拦截物理删除请求
不可修改已有 value lookup_items.value 写入后只读;修改请停用旧项 + 新增新项
不可直接查询配置表 业务模块property/client必须通过 TenantSettingsService 读取,禁止 ORM 直查
entity_type 值域 必须与 property.property_type CHECK 约束完全一致(见第三章)
Redis Key 前缀 必须携带租户 schema 前缀,格式:{tenant_schema}:setting:{type}:{key}

九、设计决策ADR

决策 选择 理由
枚举两级架构 enum_labelsPublic/固定)+ lookup_itemsTenant/可配置)分离 保障系统一致性的同时给租户灵活度
lookup_groups 由研发预置 防止租户随意创建不规范分组,控制可配置范围边界
tenant_settings 使用 JSONB 支持 bool/int/string 等多类型,无需为每类型单独建列
field_requirement_rules 不新增字段 规则层只控制「必填/选填/隐藏」,字段存在性由 DATA_MODEL_PROPERTY 决定
服务层统一读取 TenantSettingsService 统一缓存管理,业务层与配置存储解耦
trade_status 不复用 property.status 独立 sale/rent/sale_rent/* 录入场景的交易意图与房源全生命周期状态不同,避免耦合