Files
fonrey/apps/property/models/follow_keys.py
ishenwei 3638fc0302 feat(property): add Chinese verbose_name and help_text to all property fields (Phase 4.1)
Sync DATA_MODEL_PROPERTY.md field-level Chinese annotations to Django
models across 23 property tables. Adds verbose_name= and help_text= to
every field in core.py, follow_keys.py, listings.py, media.py.

Pre-existing partitioned-table docstrings on FollowLog/PropertyPhoto
retained (signal Django ORM treats parent as unmanaged, RunSQL managed).
2026-04-30 09:15:43 +08:00

279 lines
9.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from django.db import models
from core.enums import (
PropertyFollowAiTag,
PropertyFollowAttachmentFileType,
PropertyFollowLogType,
PropertyKeyType,
)
from core.models.base import UUIDPrimaryKeyModel
class FollowLog(models.Model):
"""Partitioned table (PARTITION BY RANGE created_at).
Managed via RunSQL; Django ORM treats parent as unmanaged.
"""
id = models.UUIDField(primary_key=True, verbose_name="主键")
created_at = models.DateTimeField(
verbose_name="创建时间",
help_text="分区键,必须在最前声明;系统自动",
)
property = models.ForeignKey(
"fonrey_property.Property",
on_delete=models.CASCADE,
related_name="follow_logs",
verbose_name="所属房源",
)
log_type = models.CharField(
max_length=30,
choices=PropertyFollowLogType.choices,
verbose_name="跟进日志类型",
help_text="written=经纪人主动写入/modified=字段变更自动生成/sensitive_op=敏感操作跟进/sensitive_view=敏感信息查看(不可删)/other=其他/system=系统日志",
)
purpose = models.CharField(
max_length=50,
blank=True,
default="",
verbose_name="跟进目的",
help_text="枚举值由 lookup_items 维护,如:电话/业主跟进/议价/带看;仅 written 类型使用",
)
content = models.TextField(
blank=True,
default="",
verbose_name="跟进内容",
help_text="最少 6 字,最多 500 字;仅 written 类型必填",
)
ai_tag = models.CharField(
max_length=20,
blank=True,
default="",
choices=PropertyFollowAiTag.choices,
verbose_name="AI 辅助标签",
help_text="ai_for_sale=AI判断业主在售/ai_not_for_sale=AI判断业主不售由系统智能分析后打标",
)
change_detail = models.JSONField(
null=True,
blank=True,
verbose_name="字段变更明细",
help_text='格式:{"field": "sale_price", "old": 850, "new": 800, "label": "售价"}modified 类型使用',
)
log_tag = models.CharField(
max_length=50,
blank=True,
default="",
verbose_name="前端展示标签",
help_text="如:查看号码/图片下载/改状态/改价格/改等级/修改相关方;对应跟进时间线显示的方括号标签",
)
is_public = models.BooleanField(
default=True,
verbose_name="是否公开",
help_text="true=全员可见/false=仅本人及上级可见",
)
operator = models.ForeignKey(
"org.Staff",
null=True,
blank=True,
on_delete=models.SET_NULL,
verbose_name="操作人",
help_text="人员离职后置 NULL但 snapshot 保留",
)
operator_snapshot = models.JSONField(
null=True,
blank=True,
verbose_name="操作人快照",
help_text="{name, role, org_unit_name, store_group};防止人员离职后丢失显示信息",
)
is_deletable = models.BooleanField(
default=True,
verbose_name="是否可软删除",
help_text="false=敏感信息查看类型,合规要求不可删除",
)
deleted_at = models.DateTimeField(
null=True,
blank=True,
verbose_name="软删除时间戳",
help_text="仅 is_deletable=TRUE 时可软删NULL=未删除",
)
class Meta:
db_table = "follow_logs"
verbose_name = "房源跟进日志"
verbose_name_plural = "房源跟进日志"
managed = False
unique_together = (("id", "created_at"),)
class FollowLogAttachment(UUIDPrimaryKeyModel):
follow_log_id = models.UUIDField(
verbose_name="所属跟进日志ID",
help_text="跨分区外键,未通过 Django FK 强约束;日志删除时联级删除",
)
file_key = models.TextField(
verbose_name="图片存储路径",
help_text="Cloudflare R2 对象路径",
)
file_name = models.CharField(
max_length=255,
verbose_name="原始文件名",
help_text="用户上传时的文件名",
)
file_size = models.IntegerField(
verbose_name="文件大小",
help_text="bytes最大 20MB = 20971520",
)
file_type = models.CharField(
max_length=10,
blank=True,
default="",
choices=PropertyFollowAttachmentFileType.choices,
verbose_name="文件格式",
help_text="bmp/jpg/png/svg/gifPRD 限定格式)",
)
sort_order = models.SmallIntegerField(
default=0,
verbose_name="排序权重",
help_text="控制同一跟进附件的显示顺序",
)
created_at = models.DateTimeField(auto_now_add=True, verbose_name="上传时间")
class Meta:
db_table = "follow_log_attachments"
verbose_name = "跟进附件"
verbose_name_plural = "跟进附件"
indexes = [models.Index(fields=["follow_log_id"], name="idx_fla_log")]
class FollowLogRecording(UUIDPrimaryKeyModel):
follow_log_id = models.UUIDField(
verbose_name="所属跟进日志ID",
help_text="跨分区外键,未通过 Django FK 强约束;日志删除时联级删除",
)
file_key = models.TextField(
verbose_name="录音文件存储路径",
help_text="Cloudflare R2 对象路径",
)
duration_seconds = models.IntegerField(
null=True,
blank=True,
verbose_name="录音时长",
help_text="秒;可空,上传时若能解析则填写",
)
created_at = models.DateTimeField(auto_now_add=True, verbose_name="上传时间")
class Meta:
db_table = "follow_log_recordings"
verbose_name = "跟进录音"
verbose_name_plural = "跟进录音"
indexes = [models.Index(fields=["follow_log_id"], name="idx_flr_log")]
class PropertyKey(UUIDPrimaryKeyModel):
property = models.ForeignKey(
"fonrey_property.Property",
on_delete=models.CASCADE,
related_name="keys",
verbose_name="所属房源",
)
key_type = models.CharField(
max_length=20,
choices=PropertyKeyType.choices,
verbose_name="钥匙类型",
help_text="mechanical=机械钥匙/password=密码(如密码门锁)",
)
holder = models.ForeignKey(
"org.Staff",
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name="held_keys",
verbose_name="持有人",
help_text="人员离职后置 NULL",
)
holder_snapshot = models.JSONField(
null=True,
blank=True,
verbose_name="持有人快照",
help_text="{name, store_group};防止人员离职后丢失显示信息",
)
storage_unit = models.ForeignKey(
"org.OrgUnit",
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name="stored_keys",
verbose_name="保管部门",
help_text="钥匙存放在哪个部门",
)
is_other_agency = models.BooleanField(
default=False,
verbose_name="是否他司钥匙",
help_text="true=是他中介公司的钥匙/false=本司钥匙",
)
other_agency_info = models.CharField(
max_length=30,
blank=True,
default="",
verbose_name="他司中介信息",
help_text='最多 30 字is_other_agency=true 时填写,如"链家"',
)
remarks = models.TextField(
blank=True,
default="",
verbose_name="备注",
help_text="最多 200 字;如密码内容等补充说明",
)
is_active = models.BooleanField(
default=True,
verbose_name="是否有效",
help_text="true=在管中/false=已归还或失效",
)
created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
updated_at = models.DateTimeField(auto_now=True, verbose_name="最后更新时间")
created_by = models.ForeignKey(
"org.Staff",
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name="created_property_keys",
verbose_name="创建人",
)
class Meta:
db_table = "property_keys"
verbose_name = "房源钥匙"
verbose_name_plural = "房源钥匙"
indexes = [models.Index(fields=["property"], name="idx_pk_property")]
class KeyAttachment(UUIDPrimaryKeyModel):
key = models.ForeignKey(
PropertyKey,
on_delete=models.CASCADE,
related_name="attachments",
verbose_name="所属钥匙记录",
help_text="钥匙删除时联级删除",
)
file_key = models.TextField(
verbose_name="附件存储路径",
help_text="Cloudflare R2 对象路径",
)
file_name = models.CharField(max_length=255, verbose_name="原始文件名")
created_at = models.DateTimeField(auto_now_add=True, verbose_name="上传时间")
class Meta:
db_table = "key_attachments"
verbose_name = "钥匙附件"
verbose_name_plural = "钥匙附件"
indexes = [models.Index(fields=["key"], name="idx_ka_key")]