Coverage for src/inheritance_calculator_core/models/relationship.py: 100%
99 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-10-17 05:31 +0900
« prev ^ index » next coverage.py v7.11.0, created at 2025-10-17 05:31 +0900
1"""関係性モデル"""
2from datetime import date
3from typing import Optional, Any
4from enum import Enum
5from uuid import UUID
7from pydantic import Field, field_validator
9from .base import Neo4jRelationship
12class BloodType(str, Enum):
13 """血縁タイプ"""
14 FULL = "full" # 全血(父母が同じ)
15 HALF = "half" # 半血(父または母が同じ)
18class SharedParent(str, Enum):
19 """共通の親"""
20 BOTH = "both" # 両親とも同じ
21 MOTHER = "mother" # 母のみ同じ
22 FATHER = "father" # 父のみ同じ
25class ChildOf(Neo4jRelationship):
26 """
27 子関係(CHILD_OF)
29 子から親への関係を表現。
30 """
32 parent_id: UUID = Field(..., description="親のID")
33 child_id: UUID = Field(..., description="子のID")
34 is_adoption: bool = Field(default=False, description="養子縁組であるか")
35 is_biological: bool = Field(default=True, description="実子であるか")
36 adoption_date: Optional[date] = Field(default=None, description="養子縁組日")
38 @field_validator('is_biological')
39 @classmethod
40 def validate_biological(cls, v: bool, info: Any) -> bool:
41 """実子フラグの検証"""
42 # 養子の場合、実子ではない
43 values = info.data
44 if values.get('is_adoption', False) and v:
45 raise ValueError("Adopted child cannot be biological")
46 return v
49class SpouseOf(Neo4jRelationship):
50 """
51 配偶者関係(SPOUSE_OF)
53 配偶者間の関係を表現。
54 """
56 person1_id: UUID = Field(..., description="配偶者1のID")
57 person2_id: UUID = Field(..., description="配偶者2のID")
58 marriage_date: Optional[date] = Field(default=None, description="婚姻日")
59 divorce_date: Optional[date] = Field(default=None, description="離婚日")
60 is_current: bool = Field(default=True, description="現在の配偶者か")
62 @field_validator('is_current')
63 @classmethod
64 def validate_current(cls, v: bool, info: Any) -> bool:
65 """現在の配偶者フラグの検証"""
66 values = info.data
67 # 離婚日がある場合、is_currentはFalseであるべき
68 if values.get('divorce_date') is not None and v:
69 raise ValueError("Divorced spouse cannot be current")
70 return v
72 @field_validator('divorce_date')
73 @classmethod
74 def validate_divorce_date(cls, v: Optional[date], info: Any) -> Optional[date]:
75 """離婚日の検証"""
76 if v is not None:
77 values = info.data
78 marriage_date = values.get('marriage_date')
79 if marriage_date is not None and v < marriage_date:
80 raise ValueError("Divorce date cannot be before marriage date")
81 return v
84class SiblingOf(Neo4jRelationship):
85 """
86 兄弟姉妹関係(SIBLING_OF)
88 兄弟姉妹間の関係を表現。
89 """
91 person1_id: UUID = Field(..., description="人物1のID")
92 person2_id: UUID = Field(..., description="人物2のID")
93 blood_type: BloodType = Field(..., description="血縁タイプ")
94 shared_parent: SharedParent = Field(..., description="共通の親")
96 @field_validator('shared_parent')
97 @classmethod
98 def validate_shared_parent(cls, v: SharedParent, info: Any) -> SharedParent:
99 """共通の親の検証"""
100 values = info.data
101 blood_type = values.get('blood_type')
103 # 全血の場合、両親とも同じでなければならない
104 if blood_type == BloodType.FULL and v != SharedParent.BOTH:
105 raise ValueError("Full blood siblings must share both parents")
107 # 半血の場合、片親のみ同じでなければならない
108 if blood_type == BloodType.HALF and v == SharedParent.BOTH:
109 raise ValueError("Half blood siblings cannot share both parents")
111 return v
114class Renounced(Neo4jRelationship):
115 """
116 相続放棄(RENOUNCED)
118 相続放棄の関係を表現。
119 """
121 heir_id: UUID = Field(..., description="相続人のID")
122 decedent_id: UUID = Field(..., description="被相続人のID")
123 renounce_date: date = Field(..., description="放棄日")
124 reason: Optional[str] = Field(default=None, description="放棄理由")
126 @field_validator('renounce_date')
127 @classmethod
128 def validate_renounce_date(cls, v: date) -> date:
129 """放棄日の検証"""
130 from datetime import date as date_class
131 # 未来の日付は不可
132 if v > date_class.today():
133 raise ValueError("Renounce date cannot be in the future")
134 return v
137class Disqualified(Neo4jRelationship):
138 """
139 相続欠格(DISQUALIFIED)
141 相続欠格の関係を表現。
142 """
144 heir_id: UUID = Field(..., description="相続人のID")
145 decedent_id: UUID = Field(..., description="被相続人のID")
146 reason: str = Field(..., description="欠格事由", min_length=1)
147 determination_date: date = Field(..., description="確定日")
149 @field_validator('determination_date')
150 @classmethod
151 def validate_determination_date(cls, v: date) -> date:
152 """確定日の検証"""
153 from datetime import date as date_class
154 if v > date_class.today():
155 raise ValueError("Determination date cannot be in the future")
156 return v
159class Disinherited(Neo4jRelationship):
160 """
161 相続廃除(DISINHERITED)
163 相続廃除の関係を表現。
164 """
166 heir_id: UUID = Field(..., description="相続人のID")
167 decedent_id: UUID = Field(..., description="被相続人のID")
168 reason: str = Field(..., description="廃除事由", min_length=1)
169 court_decision_date: date = Field(..., description="審判確定日")
171 @field_validator('court_decision_date')
172 @classmethod
173 def validate_court_decision_date(cls, v: date) -> date:
174 """審判確定日の検証"""
175 from datetime import date as date_class
176 if v > date_class.today():
177 raise ValueError("Court decision date cannot be in the future")
178 return v