Files
fonrey/apps/property/models/media.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

375 lines
12 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 (
PropertyAttachmentCategory,
PropertyFieldSurveyStatus,
PropertyPhotoCategory,
PropertySurveyPhotoCategory,
)
from core.models.base import UUIDPrimaryKeyModel
class FieldSurvey(UUIDPrimaryKeyModel):
property = models.ForeignKey(
"fonrey_property.Property",
on_delete=models.CASCADE,
related_name="field_surveys",
verbose_name="所属房源",
)
status = models.CharField(
max_length=10,
choices=PropertyFieldSurveyStatus.choices,
default=PropertyFieldSurveyStatus.DRAFT,
verbose_name="实勘状态",
help_text="draft=草稿(未提交)/submitted=已提交(已完成)",
)
gps_latitude = models.DecimalField(
max_digits=10,
decimal_places=7,
null=True,
blank=True,
verbose_name="GPS 纬度",
help_text="实勘打卡位置;精度 7 位小数",
)
gps_longitude = models.DecimalField(
max_digits=10,
decimal_places=7,
null=True,
blank=True,
verbose_name="GPS 经度",
help_text="实勘打卡位置;精度 7 位小数",
)
gps_accuracy = models.DecimalField(
max_digits=6,
decimal_places=2,
null=True,
blank=True,
verbose_name="GPS 精度",
help_text="米;标注定位误差",
)
description = models.TextField(
blank=True,
default="",
verbose_name="实勘说明",
help_text="最多 200 字;经纪人现场情况描述",
)
submitted_at = models.DateTimeField(
null=True,
blank=True,
verbose_name="提交时间",
help_text="status 变为 submitted 时记录NULL=尚未提交",
)
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",
on_delete=models.RESTRICT,
verbose_name="实勘人",
help_text="禁止置 NULL 保留审计",
)
class Meta:
db_table = "field_surveys"
verbose_name = "实勘记录"
verbose_name_plural = "实勘记录"
indexes = [
models.Index(fields=["property"], name="idx_fs_property"),
models.Index(fields=["property", "status"], name="idx_fs_submitted"),
]
class SurveyPhoto(UUIDPrimaryKeyModel):
survey = models.ForeignKey(
FieldSurvey,
on_delete=models.CASCADE,
related_name="photos",
verbose_name="所属实勘",
help_text="实勘删除时联级删除",
)
category = models.CharField(
max_length=20,
choices=PropertySurveyPhotoCategory.choices,
verbose_name="照片空间分类",
help_text="layout=户型图/living_room=客厅/dining_room=餐厅/bedroom=卧室/bathroom=卫生间/kitchen=厨房/entrance=门厅/balcony=阳台/study=书房/indoor_other=室内其他/outdoor=外景",
)
file_key = models.TextField(
verbose_name="原图存储路径",
help_text="Cloudflare R2 对象路径",
)
thumbnail_key = models.TextField(
blank=True,
default="",
verbose_name="缩略图路径",
help_text="Cloudflare Images 自动生成",
)
file_size = models.IntegerField(
null=True,
blank=True,
verbose_name="文件大小",
help_text="bytes",
)
width = models.IntegerField(
null=True,
blank=True,
verbose_name="图片宽度",
help_text="像素;上传时解析",
)
height = models.IntegerField(
null=True,
blank=True,
verbose_name="图片高度",
help_text="像素;上传时解析",
)
sort_order = models.SmallIntegerField(
default=0,
verbose_name="排序权重",
help_text="同一空间分类内,数值越小越靠前",
)
is_vr_screenshot = models.BooleanField(
default=False,
verbose_name="是否为VR截图",
help_text="true=全景/VR截图区别于普通实拍照片",
)
created_at = models.DateTimeField(auto_now_add=True, verbose_name="上传时间")
class Meta:
db_table = "survey_photos"
verbose_name = "实勘照片"
verbose_name_plural = "实勘照片"
indexes = [
models.Index(fields=["survey"], name="idx_sp_survey"),
models.Index(fields=["survey", "category"], name="idx_sp_category"),
]
class PropertyPhoto(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="photos",
verbose_name="所属房源",
)
category = models.CharField(
max_length=20,
choices=PropertyPhotoCategory.choices,
verbose_name="照片分类",
help_text="cover=封面/entrance=门厅/living_room=客厅/dining_room=餐厅/bedroom=卧室/bathroom=卫生间/kitchen=厨房/balcony=阳台/study=书房/indoor_other=室内其他/outdoor=外景/panorama=全景",
)
file_key = models.TextField(
verbose_name="原图存储路径",
help_text="Cloudflare R2/S3 对象路径",
)
thumbnail_key = models.TextField(
blank=True,
default="",
verbose_name="缩略图路径",
help_text="Cloudflare Images 自动生成",
)
file_name = models.CharField(
max_length=255,
blank=True,
default="",
verbose_name="原始文件名",
)
file_size = models.IntegerField(
null=True,
blank=True,
verbose_name="文件大小",
help_text="bytes",
)
width = models.IntegerField(
null=True,
blank=True,
verbose_name="图片宽度",
help_text="像素;上传时解析",
)
height = models.IntegerField(
null=True,
blank=True,
verbose_name="图片高度",
help_text="像素;上传时解析",
)
is_cover = models.BooleanField(
default=False,
verbose_name="是否为封面图",
help_text="true=封面;每套房源只能有一张封面(唯一约束保证)",
)
sort_order = models.SmallIntegerField(
default=0,
verbose_name="排序权重",
help_text="同一房源内,数值越小越靠前",
)
updated_at = models.DateTimeField(auto_now=True, verbose_name="最后更新时间")
created_by = models.ForeignKey(
"org.Staff",
null=True,
blank=True,
on_delete=models.SET_NULL,
verbose_name="上传人",
)
class Meta:
db_table = "property_photos"
verbose_name = "房源图片"
verbose_name_plural = "房源图片"
managed = False
unique_together = (("id", "created_at"),)
class PropertyAttachment(UUIDPrimaryKeyModel):
property = models.ForeignKey(
"fonrey_property.Property",
on_delete=models.CASCADE,
related_name="attachments",
verbose_name="所属房源",
)
category = models.CharField(
max_length=20,
choices=PropertyAttachmentCategory.choices,
default=PropertyAttachmentCategory.OTHER,
verbose_name="附件分类",
help_text="id_card=身份证/property_cert=产权证书/commission_letter=委托书/other=其他材料",
)
file_key = models.TextField(
verbose_name="附件存储路径",
help_text="Cloudflare R2 对象路径",
)
file_name = models.CharField(max_length=255, verbose_name="原始文件名")
file_size = models.IntegerField(
verbose_name="文件大小",
help_text="bytes",
)
file_type = models.CharField(
max_length=50,
blank=True,
default="",
verbose_name="MIME 类型",
help_text="如 application/pdf、image/jpeg",
)
sort_order = models.SmallIntegerField(
default=0,
verbose_name="排序权重",
help_text="控制同一房源附件的显示顺序",
)
created_at = models.DateTimeField(auto_now_add=True, verbose_name="上传时间")
created_by = models.ForeignKey(
"org.Staff",
null=True,
blank=True,
on_delete=models.SET_NULL,
verbose_name="上传人",
)
class Meta:
db_table = "property_attachments"
verbose_name = "房源附件"
verbose_name_plural = "房源附件"
indexes = [
models.Index(fields=["property"], name="idx_pa_property"),
models.Index(fields=["property", "category"], name="idx_pa_category"),
]
class PropertyTag(UUIDPrimaryKeyModel):
name = models.CharField(
max_length=50,
verbose_name="标签名称",
help_text="最多 50 字;如:学区/地铁口/满五唯一",
)
color = models.CharField(
max_length=7,
blank=True,
default="",
verbose_name="显示颜色",
help_text="HEX 色值,如 #FF5733前端标签徽章颜色",
)
is_system = models.BooleanField(
default=False,
verbose_name="是否系统预置",
help_text="true=系统内置标签不可删除false=运营自定义标签可删",
)
sort_order = models.IntegerField(
default=0,
verbose_name="排序权重",
help_text="数值越小越靠前",
)
is_active = models.BooleanField(
default=True,
verbose_name="是否启用",
help_text="false=已停用不再展示",
)
class Meta:
db_table = "property_tags"
verbose_name = "房源标签"
verbose_name_plural = "房源标签"
class PropertyTagRelation(models.Model):
property = models.ForeignKey(
"fonrey_property.Property",
on_delete=models.CASCADE,
related_name="tag_relations",
verbose_name="所属房源",
)
tag = models.ForeignKey(
PropertyTag,
on_delete=models.CASCADE,
related_name="property_relations",
verbose_name="所属标签",
)
class Meta:
db_table = "property_tag_relations"
verbose_name = "房源标签关联"
verbose_name_plural = "房源标签关联"
constraints = [
models.UniqueConstraint(fields=["property", "tag"], name="uq_ptr_property_tag"),
]
indexes = [
models.Index(fields=["property"], name="idx_ptr_property"),
models.Index(fields=["tag"], name="idx_ptr_tag"),
]
class PropertyFavorite(models.Model):
staff = models.ForeignKey(
"org.Staff",
on_delete=models.CASCADE,
related_name="favorite_properties",
verbose_name="收藏人",
help_text="员工注销时删除收藏记录",
)
property = models.ForeignKey(
"fonrey_property.Property",
on_delete=models.CASCADE,
related_name="favorited_by",
verbose_name="收藏的房源",
)
created_at = models.DateTimeField(auto_now_add=True, verbose_name="收藏时间")
class Meta:
db_table = "property_favorites"
verbose_name = "房源收藏"
verbose_name_plural = "房源收藏"
constraints = [
models.UniqueConstraint(fields=["staff", "property"], name="uq_pfav_staff_property"),
]
indexes = [models.Index(fields=["staff"], name="idx_pfav_staff")]