为所有 Django 模型添加 Meta.verbose_name 和 verbose_name_plural(中文表名), 覆盖 10 个 app 的全部 74 个业务模型。 Phase 4.0 范围: - 仅 Meta 类级别中文名(用于 Django Admin、drf-spectacular OpenAPI title、错误信息) - 字段级 verbose_name= 和 help_text= 留待 Phase 4.1(待 PM 补全 DATA_MODEL 后同步) 变更: - 20 个 models 文件改动(每个模型 +2 行) - 8 个 0002/0003 迁移文件(Meta options 变更) - apps/tenant/migrations/0001_initial.py(之前漏生成的 tenant 模型迁移) manage.py check: 0 issues。
154 lines
5.1 KiB
Python
154 lines
5.1 KiB
Python
from django.contrib.postgres.fields import ArrayField
|
|
from django.db import models
|
|
|
|
from core.enums import (
|
|
ClientPropertyMatchGroup,
|
|
ClientPropertyMatchSource,
|
|
ClientPropertyMatchStatus,
|
|
ClientStatusLogChangeType,
|
|
ClientViewingIntent,
|
|
ClientViewingType,
|
|
)
|
|
from core.models.base import UUIDPrimaryKeyModel
|
|
|
|
|
|
class ClientViewing(UUIDPrimaryKeyModel):
|
|
client = models.ForeignKey(
|
|
"fonrey_client.Client", on_delete=models.RESTRICT, related_name="viewings"
|
|
)
|
|
property = models.ForeignKey(
|
|
"fonrey_property.Property",
|
|
on_delete=models.RESTRICT,
|
|
related_name="client_viewings",
|
|
)
|
|
viewing_type = models.CharField(
|
|
max_length=20, choices=ClientViewingType.choices, default=ClientViewingType.VIEWING
|
|
)
|
|
|
|
agent = models.ForeignKey(
|
|
"org.Staff",
|
|
null=True,
|
|
blank=True,
|
|
on_delete=models.SET_NULL,
|
|
related_name="led_viewings",
|
|
)
|
|
companion_ids = ArrayField(models.UUIDField(), blank=True, default=list)
|
|
cooperator_ids = ArrayField(models.UUIDField(), blank=True, default=list)
|
|
|
|
scheduled_at = models.DateTimeField(null=True, blank=True)
|
|
viewing_start_at = models.DateTimeField(null=True, blank=True)
|
|
viewing_end_at = models.DateTimeField(null=True, blank=True)
|
|
|
|
situation = models.TextField(blank=True, default="")
|
|
client_intent = models.CharField(
|
|
max_length=20, choices=ClientViewingIntent.choices, blank=True, default=""
|
|
)
|
|
viewing_progress = models.SmallIntegerField(null=True, blank=True)
|
|
|
|
created_at = models.DateTimeField(auto_now_add=True)
|
|
deleted_at = models.DateTimeField(null=True, blank=True)
|
|
created_by = models.ForeignKey(
|
|
"org.Staff",
|
|
null=True,
|
|
blank=True,
|
|
on_delete=models.SET_NULL,
|
|
related_name="created_client_viewings",
|
|
)
|
|
|
|
class Meta:
|
|
db_table = "client_viewings"
|
|
verbose_name = "带看记录"
|
|
verbose_name_plural = "带看记录"
|
|
indexes = [
|
|
models.Index(
|
|
fields=["client", "-viewing_start_at"], name="idx_cv_client_time"
|
|
),
|
|
models.Index(fields=["property"], name="idx_cv_property"),
|
|
models.Index(fields=["agent"], name="idx_cv_agent"),
|
|
]
|
|
|
|
|
|
class ClientPropertyMatch(UUIDPrimaryKeyModel):
|
|
client = models.ForeignKey(
|
|
"fonrey_client.Client", on_delete=models.CASCADE, related_name="property_matches"
|
|
)
|
|
property = models.ForeignKey(
|
|
"fonrey_property.Property",
|
|
on_delete=models.CASCADE,
|
|
related_name="client_matches",
|
|
)
|
|
|
|
match_source = models.CharField(
|
|
max_length=20,
|
|
choices=ClientPropertyMatchSource.choices,
|
|
default=ClientPropertyMatchSource.RECORDED,
|
|
)
|
|
match_group = models.CharField(
|
|
max_length=30, choices=ClientPropertyMatchGroup.choices, blank=True, default=""
|
|
)
|
|
match_score = models.DecimalField(
|
|
max_digits=5, decimal_places=2, null=True, blank=True
|
|
)
|
|
match_reasons = models.JSONField(null=True, blank=True)
|
|
|
|
status = models.CharField(
|
|
max_length=20,
|
|
choices=ClientPropertyMatchStatus.choices,
|
|
default=ClientPropertyMatchStatus.SUGGESTED,
|
|
)
|
|
shared_at = models.DateTimeField(null=True, blank=True)
|
|
feedback = models.CharField(max_length=50, blank=True, default="")
|
|
calculated_at = models.DateTimeField(auto_now_add=True)
|
|
created_by = models.ForeignKey(
|
|
"org.Staff",
|
|
null=True,
|
|
blank=True,
|
|
on_delete=models.SET_NULL,
|
|
related_name="created_matches",
|
|
)
|
|
|
|
class Meta:
|
|
db_table = "client_property_matches"
|
|
verbose_name = "智能配房"
|
|
verbose_name_plural = "智能配房"
|
|
constraints = [
|
|
models.UniqueConstraint(
|
|
fields=["client", "property"], name="uq_client_match_pair"
|
|
),
|
|
]
|
|
indexes = [
|
|
models.Index(
|
|
fields=["client", "match_source", "match_group"],
|
|
name="idx_cpm_client_grp",
|
|
),
|
|
models.Index(fields=["client", "status"], name="idx_cpm_status"),
|
|
]
|
|
|
|
|
|
class ClientStatusLog(models.Model):
|
|
"""Audit log; record-level immutable (no deleted_at)."""
|
|
|
|
id = models.UUIDField(primary_key=True)
|
|
client = models.ForeignKey(
|
|
"fonrey_client.Client", on_delete=models.RESTRICT, related_name="status_logs"
|
|
)
|
|
change_type = models.CharField(
|
|
max_length=30, choices=ClientStatusLogChangeType.choices
|
|
)
|
|
old_value = models.JSONField(null=True, blank=True)
|
|
new_value = models.JSONField(null=True, blank=True)
|
|
reason = models.TextField(blank=True, default="")
|
|
operator = models.ForeignKey(
|
|
"org.Staff", on_delete=models.RESTRICT, related_name="client_status_changes"
|
|
)
|
|
operated_at = models.DateTimeField(auto_now_add=True)
|
|
|
|
class Meta:
|
|
db_table = "client_status_logs"
|
|
verbose_name = "客源状态变更日志"
|
|
verbose_name_plural = "客源状态变更日志"
|
|
indexes = [
|
|
models.Index(fields=["client", "-operated_at"], name="idx_csl_client"),
|
|
models.Index(fields=["change_type", "-operated_at"], name="idx_csl_type"),
|
|
]
|