from django.db import models from core.enums import OrgUnitAttribute, OrgUnitType from core.models.base import SoftDeleteModel class OrgUnit(SoftDeleteModel): name = models.CharField( max_length=100, verbose_name="部门名称", help_text="部门/组织名称", ) type = models.CharField( max_length=20, choices=OrgUnitType.choices, verbose_name="组织类型", help_text="company=公司 / division=事业部 / region=大区 / area=区域 / district=片区 / store=门店 / group=店组 / functional=职能", ) parent = models.ForeignKey( "self", null=True, blank=True, on_delete=models.RESTRICT, related_name="children", db_index=True, verbose_name="父节点", help_text="父节点,根节点为 NULL", ) path = models.TextField( verbose_name="物化路径", help_text='/root_id/.../self_id/,用于子树查询', ) depth = models.SmallIntegerField( default=0, verbose_name="节点深度", help_text="根=0,最大支持 8 层", ) sort_order = models.IntegerField( default=0, verbose_name="排序顺序", help_text="同级排序", ) attribute = models.CharField( max_length=10, choices=OrgUnitAttribute.choices, null=True, blank=True, verbose_name="经营属性", help_text="direct=直营 / franchise=加盟", ) address_city = models.CharField( max_length=50, blank=True, default="", verbose_name="所在城市", ) address_district = models.CharField( max_length=50, blank=True, default="", verbose_name="所在县区", ) address_detail = models.CharField( max_length=200, blank=True, default="", verbose_name="详细地址", ) latitude = models.DecimalField( max_digits=10, decimal_places=7, null=True, blank=True, verbose_name="纬度", help_text="部门定位针 WGS84", ) longitude = models.DecimalField( max_digits=10, decimal_places=7, null=True, blank=True, verbose_name="经度", help_text="部门定位针 WGS84", ) manager = models.ForeignKey( "org.Staff", null=True, blank=True, on_delete=models.SET_NULL, related_name="managed_org_units", verbose_name="部门负责人", help_text="循环依赖,Application 层维护", ) established_at = models.DateField( null=True, blank=True, verbose_name="成立时间", ) phone = models.CharField( max_length=30, blank=True, default="", verbose_name="部门联系电话", ) ext_start = models.IntegerField( null=True, blank=True, verbose_name="分机号起始", ) ext_end = models.IntegerField( null=True, blank=True, verbose_name="分机号结束", ) is_active = models.BooleanField( default=True, verbose_name="是否启用", help_text="FALSE=已关闭部门,仍可在筛选中显示", ) class Meta: db_table = "org_units" verbose_name = "组织节点" verbose_name_plural = "组织节点" indexes = [ models.Index(fields=["parent"], name="idx_org_units_parent"), models.Index(fields=["type"], name="idx_org_units_type"), models.Index(fields=["path"], name="idx_org_units_path"), ] ordering = ["sort_order", "name"] def __str__(self) -> str: return f"{self.name} ({self.type})"