Coverage for src/inheritance_calculator_core/services/heir_validator.py: 0%

91 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-10-17 05:31 +0900

1"""相続人資格検証サービス 

2 

3日本の民法に基づいて相続人の資格を判定するサービス。 

4""" 

5from typing import List, Optional 

6from datetime import date 

7 

8from ..models.person import Person 

9from ..models.relationship import ( 

10 ChildOf, 

11 SpouseOf, 

12 SiblingOf, 

13 Renounced, 

14 Disqualified, 

15 Disinherited, 

16 BloodType, 

17) 

18from ..models.inheritance import HeritageRank, SubstitutionType 

19from .base import BaseService 

20 

21 

22class HeirValidator(BaseService[Person]): 

23 """ 

24 相続人資格検証サービス 

25 

26 相続人の資格を判定し、相続順位を確定する。 

27 """ 

28 

29 def __init__(self) -> None: 

30 """初期化""" 

31 super().__init__() 

32 self.decedent: Optional[Person] = None 

33 self.spouses: List[Person] = [] 

34 self.children: List[Person] = [] 

35 self.parents: List[Person] = [] 

36 self.siblings: List[Person] = [] 

37 self.renounced_persons: List[Person] = [] 

38 self.disqualified_persons: List[Person] = [] 

39 self.disinherited_persons: List[Person] = [] 

40 

41 def set_decedent(self, decedent: Person) -> None: 

42 """ 

43 被相続人を設定 

44 

45 Args: 

46 decedent: 被相続人 

47 """ 

48 if not decedent.is_decedent: 

49 self.log_warning("Person is not marked as decedent", person=decedent.name) 

50 

51 self.decedent = decedent 

52 self.log_operation("Set decedent", name=decedent.name) 

53 

54 def is_valid_heir(self, person: Person) -> bool: 

55 """ 

56 相続人として有効かチェック 

57 

58 Args: 

59 person: チェック対象の人物 

60 

61 Returns: 

62 相続人として有効な場合True 

63 """ 

64 if self.decedent is None: 

65 raise ValueError("Decedent must be set before validating heirs") 

66 

67 # 被相続人本人は相続人になれない 

68 if person.id == self.decedent.id: 

69 return False 

70 

71 # 死亡している場合の判定 

72 if not person.is_alive: 

73 # 遺産分割前に死亡した場合は再転相続の対象として一旦有効とする 

74 # (後で再転相続処理で実際の相続人に置き換える) 

75 if person.died_before_division: 

76 return True 

77 # それ以外の死亡者は相続人になれない(代襲相続を除く) 

78 return False 

79 

80 # 相続放棄している場合は相続人になれない 

81 if person in self.renounced_persons: 

82 self.log_info("Person has renounced inheritance", person=person.name) 

83 return False 

84 

85 # 相続欠格の場合は相続人になれない(ただし代襲相続は可能) 

86 if person in self.disqualified_persons: 

87 self.log_info("Person is disqualified", person=person.name) 

88 return False 

89 

90 # 相続廃除の場合は相続人になれない(ただし代襲相続は可能) 

91 if person in self.disinherited_persons: 

92 self.log_info("Person is disinherited", person=person.name) 

93 return False 

94 

95 return True 

96 

97 def validate_spouse(self, spouse: Person) -> bool: 

98 """ 

99 配偶者の相続資格を検証 

100 

101 民法890条:配偶者は常に相続人となる 

102 

103 Args: 

104 spouse: 配偶者 

105 

106 Returns: 

107 相続人として有効な場合True 

108 """ 

109 if not self.is_valid_heir(spouse): 

110 return False 

111 

112 # 配偶者は常に相続人(民法890条) 

113 self.log_operation( 

114 "Validated spouse", 

115 spouse=spouse.name, 

116 basis="民法890条" 

117 ) 

118 return True 

119 

120 def validate_child(self, child: Person) -> bool: 

121 """ 

122 子の相続資格を検証 

123 

124 民法887条1項:子は第1順位の相続人 

125 

126 Args: 

127 child: 子 

128 

129 Returns: 

130 相続人として有効な場合True 

131 """ 

132 if not self.is_valid_heir(child): 

133 return False 

134 

135 # 子は第1順位の相続人(民法887条1項) 

136 self.log_operation( 

137 "Validated child", 

138 child=child.name, 

139 basis="民法887条1項" 

140 ) 

141 return True 

142 

143 def validate_parent(self, parent: Person, has_first_rank: bool) -> bool: 

144 """ 

145 直系尊属の相続資格を検証 

146 

147 民法889条1項1号:第1順位の相続人がいない場合のみ相続 

148 

149 Args: 

150 parent: 直系尊属(父母、祖父母等) 

151 has_first_rank: 第1順位の相続人が存在するか 

152 

153 Returns: 

154 相続人として有効な場合True 

155 """ 

156 if not self.is_valid_heir(parent): 

157 return False 

158 

159 # 第1順位の相続人がいる場合は相続できない 

160 if has_first_rank: 

161 self.log_info( 

162 "Parent cannot inherit (first rank heirs exist)", 

163 parent=parent.name 

164 ) 

165 return False 

166 

167 # 直系尊属は第2順位の相続人(民法889条1項1号) 

168 self.log_operation( 

169 "Validated parent", 

170 parent=parent.name, 

171 basis="民法889条1項1号" 

172 ) 

173 return True 

174 

175 def validate_sibling( 

176 self, 

177 sibling: Person, 

178 has_first_rank: bool, 

179 has_second_rank: bool 

180 ) -> bool: 

181 """ 

182 兄弟姉妹の相続資格を検証 

183 

184 民法889条1項2号:第1順位、第2順位の相続人がいない場合のみ相続 

185 

186 Args: 

187 sibling: 兄弟姉妹 

188 has_first_rank: 第1順位の相続人が存在するか 

189 has_second_rank: 第2順位の相続人が存在するか 

190 

191 Returns: 

192 相続人として有効な場合True 

193 """ 

194 if not self.is_valid_heir(sibling): 

195 return False 

196 

197 # 第1順位または第2順位の相続人がいる場合は相続できない 

198 if has_first_rank or has_second_rank: 

199 self.log_info( 

200 "Sibling cannot inherit (higher rank heirs exist)", 

201 sibling=sibling.name 

202 ) 

203 return False 

204 

205 # 兄弟姉妹は第3順位の相続人(民法889条1項2号) 

206 self.log_operation( 

207 "Validated sibling", 

208 sibling=sibling.name, 

209 basis="民法889条1項2号" 

210 ) 

211 return True 

212 

213 def can_substitute( 

214 self, 

215 deceased_heir: Person, 

216 substitute: Person, 

217 rank: HeritageRank 

218 ) -> bool: 

219 """ 

220 代襲相続が可能かチェック 

221 

222 民法887条2項・3項:子の代襲相続(制限なし) 

223 民法889条2項:兄弟姉妹の代襲相続(1代限り) 

224 

225 Args: 

226 deceased_heir: 死亡した相続人(被代襲者) 

227 substitute: 代襲相続人候補 

228 rank: 相続順位 

229 

230 Returns: 

231 代襲相続が可能な場合True 

232 """ 

233 if self.decedent is None: 

234 raise ValueError("Decedent must be set") 

235 

236 # 代襲相続人候補が生存していなければならない 

237 if not substitute.is_alive: 

238 return False 

239 

240 # 被代襲者が被相続人より先に死亡しているか、 

241 # 相続欠格・相続廃除されている必要がある 

242 valid_substitution_reason = ( 

243 (deceased_heir.death_date is not None and 

244 self.decedent.death_date is not None and 

245 deceased_heir.death_date < self.decedent.death_date) or 

246 deceased_heir in self.disqualified_persons or 

247 deceased_heir in self.disinherited_persons 

248 ) 

249 

250 if not valid_substitution_reason: 

251 return False 

252 

253 # 相続放棄は代襲原因にならない 

254 if deceased_heir in self.renounced_persons: 

255 self.log_info( 

256 "No substitution for renounced heir", 

257 deceased=deceased_heir.name 

258 ) 

259 return False 

260 

261 # 第1順位(子)の代襲:制限なし(民法887条2項・3項) 

262 if rank == HeritageRank.FIRST: 

263 self.log_operation( 

264 "Substitution allowed for child", 

265 substitute=substitute.name, 

266 deceased=deceased_heir.name, 

267 basis="民法887条2項・3項" 

268 ) 

269 return True 

270 

271 # 第3順位(兄弟姉妹)の代襲:1代限り(民法889条2項) 

272 if rank == HeritageRank.THIRD: 

273 # 兄弟姉妹の子(甥・姪)までのみ代襲可能 

274 self.log_operation( 

275 "Substitution allowed for sibling (1 generation only)", 

276 substitute=substitute.name, 

277 deceased=deceased_heir.name, 

278 basis="民法889条2項" 

279 ) 

280 return True 

281 

282 return False 

283 

284 def get_substitution_type(self, rank: HeritageRank) -> SubstitutionType: 

285 """ 

286 代襲相続のタイプを取得 

287 

288 Args: 

289 rank: 相続順位 

290 

291 Returns: 

292 代襲相続タイプ 

293 """ 

294 if rank == HeritageRank.FIRST: 

295 return SubstitutionType.CHILD 

296 elif rank == HeritageRank.THIRD: 

297 return SubstitutionType.SIBLING 

298 else: 

299 return SubstitutionType.NONE