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).
This commit is contained in:
@@ -15,32 +15,93 @@ class FollowLog(models.Model):
|
||||
Managed via RunSQL; Django ORM treats parent as unmanaged.
|
||||
"""
|
||||
|
||||
id = models.UUIDField(primary_key=True)
|
||||
created_at = models.DateTimeField()
|
||||
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"
|
||||
"fonrey_property.Property",
|
||||
on_delete=models.CASCADE,
|
||||
related_name="follow_logs",
|
||||
verbose_name="所属房源",
|
||||
)
|
||||
|
||||
log_type = models.CharField(max_length=30, choices=PropertyFollowLogType.choices)
|
||||
purpose = models.CharField(max_length=50, blank=True, default="")
|
||||
content = models.TextField(blank=True, default="")
|
||||
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
|
||||
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)
|
||||
log_tag = models.CharField(max_length=50, blank=True, default="")
|
||||
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)
|
||||
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
|
||||
"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};防止人员离职后丢失显示信息",
|
||||
)
|
||||
operator_snapshot = models.JSONField(null=True, blank=True)
|
||||
|
||||
is_deletable = models.BooleanField(default=True)
|
||||
deleted_at = models.DateTimeField(null=True, blank=True)
|
||||
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"
|
||||
@@ -51,15 +112,37 @@ class FollowLog(models.Model):
|
||||
|
||||
|
||||
class FollowLogAttachment(UUIDPrimaryKeyModel):
|
||||
follow_log_id = models.UUIDField() # cross-partitioned FK; not enforced via Django FK
|
||||
file_key = models.TextField()
|
||||
file_name = models.CharField(max_length=255)
|
||||
file_size = models.IntegerField()
|
||||
file_type = models.CharField(
|
||||
max_length=10, blank=True, default="", choices=PropertyFollowAttachmentFileType.choices
|
||||
follow_log_id = models.UUIDField(
|
||||
verbose_name="所属跟进日志ID",
|
||||
help_text="跨分区外键,未通过 Django FK 强约束;日志删除时联级删除",
|
||||
)
|
||||
sort_order = models.SmallIntegerField(default=0)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
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/gif(PRD 限定格式)",
|
||||
)
|
||||
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"
|
||||
@@ -69,10 +152,21 @@ class FollowLogAttachment(UUIDPrimaryKeyModel):
|
||||
|
||||
|
||||
class FollowLogRecording(UUIDPrimaryKeyModel):
|
||||
follow_log_id = models.UUIDField()
|
||||
file_key = models.TextField()
|
||||
duration_seconds = models.IntegerField(null=True, blank=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
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"
|
||||
@@ -83,9 +177,17 @@ class FollowLogRecording(UUIDPrimaryKeyModel):
|
||||
|
||||
class PropertyKey(UUIDPrimaryKeyModel):
|
||||
property = models.ForeignKey(
|
||||
"fonrey_property.Property", on_delete=models.CASCADE, related_name="keys"
|
||||
"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=密码(如密码门锁)",
|
||||
)
|
||||
key_type = models.CharField(max_length=20, choices=PropertyKeyType.choices)
|
||||
|
||||
holder = models.ForeignKey(
|
||||
"org.Staff",
|
||||
@@ -93,29 +195,58 @@ class PropertyKey(UUIDPrimaryKeyModel):
|
||||
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};防止人员离职后丢失显示信息",
|
||||
)
|
||||
holder_snapshot = models.JSONField(null=True, blank=True)
|
||||
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)
|
||||
other_agency_info = models.CharField(max_length=30, blank=True, default="")
|
||||
remarks = models.TextField(blank=True, default="")
|
||||
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)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
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:
|
||||
@@ -127,11 +258,18 @@ class PropertyKey(UUIDPrimaryKeyModel):
|
||||
|
||||
class KeyAttachment(UUIDPrimaryKeyModel):
|
||||
key = models.ForeignKey(
|
||||
PropertyKey, on_delete=models.CASCADE, related_name="attachments"
|
||||
PropertyKey,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="attachments",
|
||||
verbose_name="所属钥匙记录",
|
||||
help_text="钥匙删除时联级删除",
|
||||
)
|
||||
file_key = models.TextField()
|
||||
file_name = models.CharField(max_length=255)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
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"
|
||||
|
||||
Reference in New Issue
Block a user