File size: 6,859 Bytes
b4f2238
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
"""Module for material."""

from __future__ import annotations

from typing import ClassVar

from django.db import models
from django.utils.translation import gettext_lazy as _

from .case import Case, SupervisingAuthority
from .log import CaseLogAttachment
from .party import CaseParty


class CaseMaterialCategory(models.TextChoices):
    PARTY = "party", _("当事人材料")
    NON_PARTY = "non_party", _("非当事人材料")


class CaseMaterialSide(models.TextChoices):
    OUR = "our", _("我方当事人材料")
    OPPONENT = "opponent", _("对方当事人材料")


class CaseMaterialType(models.Model):
    id: int
    category = models.CharField(max_length=32, choices=CaseMaterialCategory.choices, verbose_name=_("材料大类"))
    name = models.CharField(max_length=64, verbose_name=_("类型名称"))
    law_firm = models.ForeignKey(
        "organization.LawFirm",
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        related_name="case_material_types",
        verbose_name=_("律所"),
    )
    is_active = models.BooleanField(default=True, verbose_name=_("是否启用"))
    created_at = models.DateTimeField(auto_now_add=True, verbose_name=_("创建时间"))

    class Meta:
        verbose_name = _("案件材料类型")
        verbose_name_plural = _("案件材料类型")
        constraints: ClassVar = [
            models.UniqueConstraint(fields=["law_firm", "category", "name"], name="uniq_case_material_type_scope"),
        ]
        indexes: ClassVar = [
            models.Index(fields=["category", "name"]),
            models.Index(fields=["law_firm", "category"]),
            models.Index(fields=["is_active"]),
        ]

    def __str__(self) -> str:
        scope = self.law_firm.name if self.law_firm_id and self.law_firm else "全局"
        category_display = self.get_category_display()
        return f"{scope}-{category_display}-{self.name}"


class CaseMaterial(models.Model):
    id: int
    case = models.ForeignKey(Case, on_delete=models.CASCADE, related_name="materials", verbose_name=_("案件"))
    category = models.CharField(max_length=32, choices=CaseMaterialCategory.choices, verbose_name=_("材料大类"))
    type = models.ForeignKey(
        CaseMaterialType,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="materials",
        verbose_name=_("材料类型"),
    )
    type_name = models.CharField(max_length=64, verbose_name=_("类型名称"))
    source_attachment = models.OneToOneField(
        CaseLogAttachment,
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        related_name="bound_material",
        verbose_name=_("来源日志附件"),
    )
    side = models.CharField(
        max_length=32,
        choices=CaseMaterialSide.choices,
        null=True,
        blank=True,
        verbose_name=_("当事人方向"),
    )
    parties = models.ManyToManyField(CaseParty, blank=True, related_name="materials", verbose_name=_("关联当事人"))
    supervising_authority = models.ForeignKey(
        SupervisingAuthority,
        on_delete=models.PROTECT,
        null=True,
        blank=True,
        related_name="materials",
        verbose_name=_("主管机关"),
    )
    created_at = models.DateTimeField(auto_now_add=True, verbose_name=_("创建时间"))

    class Meta:
        verbose_name = _("案件材料")
        verbose_name_plural = _("案件材料")
        indexes: ClassVar = [
            models.Index(fields=["case", "category", "created_at"]),
            models.Index(fields=["case", "category", "side"]),
            models.Index(fields=["case", "category", "supervising_authority"]),
            models.Index(fields=["type_name"]),
        ]

    def __str__(self) -> str:
        category_display = self.get_category_display()
        return f"{self.case_id}-{category_display}-{self.type_name}"


class CaseMaterialGroupOrder(models.Model):
    id: int
    case = models.ForeignKey(
        Case, on_delete=models.CASCADE, related_name="material_group_orders", verbose_name=_("案件")
    )
    category = models.CharField(max_length=32, choices=CaseMaterialCategory.choices, verbose_name=_("材料大类"))
    side = models.CharField(
        max_length=32,
        choices=CaseMaterialSide.choices,
        null=True,
        blank=True,
        verbose_name=_("当事人方向"),
    )
    supervising_authority = models.ForeignKey(
        SupervisingAuthority,
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        related_name="material_group_orders",
        verbose_name=_("主管机关"),
    )
    type = models.ForeignKey(
        CaseMaterialType, on_delete=models.CASCADE, related_name="group_orders", verbose_name=_("材料类型")
    )
    sort_index = models.PositiveIntegerField(default=0, verbose_name=_("排序"))

    class Meta:
        verbose_name = _("案件材料分组顺序")
        verbose_name_plural = _("案件材料分组顺序")
        constraints: ClassVar = [
            models.UniqueConstraint(
                fields=["case", "category", "side", "supervising_authority", "type"],
                name="uniq_case_material_group_order",
            ),
        ]
        indexes: ClassVar = [
            models.Index(fields=["case", "category", "side", "sort_index"]),
            models.Index(fields=["case", "category", "supervising_authority", "sort_index"]),
        ]

    def __str__(self) -> str:
        return f"{self.case_id}-{self.category}-{self.sort_index}"


class CaseFolderBinding(models.Model):
    """案件文件夹绑定"""

    id: int
    case = models.OneToOneField(Case, on_delete=models.CASCADE, related_name="folder_binding", verbose_name=_("案件"))
    folder_path = models.CharField(
        max_length=1000, verbose_name=_("文件夹路径"), help_text=_("绑定的本地或网络文件夹路径")
    )
    created_at = models.DateTimeField(auto_now_add=True, verbose_name=_("绑定时间"))
    updated_at = models.DateTimeField(auto_now=True, verbose_name=_("更新时间"))

    class Meta:
        verbose_name = _("案件文件夹绑定")
        verbose_name_plural = _("案件文件夹绑定")
        indexes: ClassVar = [
            models.Index(fields=["case"]),
            models.Index(fields=["created_at"]),
        ]

    def __str__(self) -> str:
        return f"{self.case.name} - {self.folder_path}"

    @property
    def folder_path_display(self) -> str:
        """格式化显示路径"""
        if not self.folder_path:
            return ""
        max_length = 50
        if len(self.folder_path) <= max_length:
            return self.folder_path
        start_len = max_length // 2 - 2
        end_len = max_length - start_len - 3
        return f"{self.folder_path[:start_len]}...{self.folder_path[-end_len:]}"