Coverage for src/inheritance_calculator_core/models/relationship.py: 100%

1"""関係性モデル"""

2 from datetime import date

3 from typing import Optional, Any

4 from enum import Enum

5 from uuid import UUID

6

7 from pydantic import Field, field_validator

8

9 from .base import Neo4jRelationship

10

11

12 class BloodType(str, Enum):

13 """血縁タイプ"""

14 FULL = "full" # 全血（父母が同じ）

15 HALF = "half" # 半血（父または母が同じ）

16

17

18 class SharedParent(str, Enum):

19 """共通の親"""

20 BOTH = "both" # 両親とも同じ

21 MOTHER = "mother" # 母のみ同じ

22 FATHER = "father" # 父のみ同じ

23

24

25 class ChildOf(Neo4jRelationship):

26 """

27 子関係（CHILD_OF）

28

29 子から親への関係を表現。

30 """

31

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="養子縁組日")

37

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

47

48

49 class SpouseOf(Neo4jRelationship):

50 """

51 配偶者関係（SPOUSE_OF）

52

53 配偶者間の関係を表現。

54 """

55

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="現在の配偶者か")

61

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

71

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

82

83

84 class SiblingOf(Neo4jRelationship):

85 """

86 兄弟姉妹関係（SIBLING_OF）

87

88 兄弟姉妹間の関係を表現。

89 """

90

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="共通の親")

95

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')

102

103 # 全血の場合、両親とも同じでなければならない

104 if blood_type == BloodType.FULL and v != SharedParent.BOTH:

105 raise ValueError("Full blood siblings must share both parents")

106

107 # 半血の場合、片親のみ同じでなければならない

108 if blood_type == BloodType.HALF and v == SharedParent.BOTH:

109 raise ValueError("Half blood siblings cannot share both parents")

110

111 return v

112

113

114 class Renounced(Neo4jRelationship):

115 """

116 相続放棄（RENOUNCED）

117

118 相続放棄の関係を表現。

119 """

120

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="放棄理由")

125

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

135

136

137 class Disqualified(Neo4jRelationship):

138 """

139 相続欠格（DISQUALIFIED）

140

141 相続欠格の関係を表現。

142 """

143

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="確定日")

148

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

157

158

159 class Disinherited(Neo4jRelationship):

160 """

161 相続廃除（DISINHERITED）

162

163 相続廃除の関係を表現。

164 """

165

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="審判確定日")

170

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