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

106 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, Dict, Optional 

6from fractions import Fraction 

7 

8from ..models.person import Person 

9from ..models.relationship import BloodType 

10from ..models.inheritance import HeritageRank 

11from .base import BaseService 

12 

13 

14class ShareCalculator(BaseService[Person]): 

15 """ 

16 相続割合計算サービス 

17 

18 法定相続分を計算する。 

19 """ 

20 

21 def calculate_shares( 

22 self, 

23 spouses: List[Person], 

24 first_rank: List[Person], 

25 second_rank: List[Person], 

26 third_rank: List[Person], 

27 third_rank_blood_types: Optional[Dict[str, BloodType]] = None 

28 ) -> Dict[str, Fraction]: 

29 """ 

30 相続割合を計算 

31 

32 Args: 

33 spouses: 配偶者のリスト 

34 first_rank: 第1順位の相続人(子) 

35 second_rank: 第2順位の相続人(直系尊属) 

36 third_rank: 第3順位の相続人(兄弟姉妹) 

37 third_rank_blood_types: 第3順位の血縁タイプ(人物ID → BloodType) 

38 

39 Returns: 

40 人物ID → 相続割合の辞書 

41 """ 

42 if third_rank_blood_types is None: 

43 third_rank_blood_types = {} 

44 

45 shares: Dict[str, Fraction] = {} 

46 

47 # 配偶者のみの場合 

48 if spouses and not first_rank and not second_rank and not third_rank: 

49 shares.update(self._calculate_spouse_only(spouses)) 

50 self.log_operation( 

51 "Calculated shares: spouse only", 

52 basis="配偶者のみ(全部相続)" 

53 ) 

54 return shares 

55 

56 # 配偶者と子 

57 if spouses and first_rank: 

58 shares.update(self._calculate_spouse_and_children(spouses, first_rank)) 

59 self.log_operation( 

60 "Calculated shares: spouse and children", 

61 basis="民法900条1号" 

62 ) 

63 return shares 

64 

65 # 子のみ 

66 if first_rank and not spouses: 

67 shares.update(self._calculate_children_only(first_rank)) 

68 self.log_operation( 

69 "Calculated shares: children only", 

70 basis="子のみ(均等分割)" 

71 ) 

72 return shares 

73 

74 # 配偶者と直系尊属 

75 if spouses and second_rank: 

76 shares.update(self._calculate_spouse_and_parents(spouses, second_rank)) 

77 self.log_operation( 

78 "Calculated shares: spouse and parents", 

79 basis="民法900条2号" 

80 ) 

81 return shares 

82 

83 # 直系尊属のみ 

84 if second_rank and not spouses: 

85 shares.update(self._calculate_parents_only(second_rank)) 

86 self.log_operation( 

87 "Calculated shares: parents only", 

88 basis="直系尊属のみ(均等分割)" 

89 ) 

90 return shares 

91 

92 # 配偶者と兄弟姉妹 

93 if spouses and third_rank: 

94 shares.update( 

95 self._calculate_spouse_and_siblings( 

96 spouses, third_rank, third_rank_blood_types 

97 ) 

98 ) 

99 self.log_operation( 

100 "Calculated shares: spouse and siblings", 

101 basis="民法900条3号・4号" 

102 ) 

103 return shares 

104 

105 # 兄弟姉妹のみ 

106 if third_rank and not spouses: 

107 shares.update( 

108 self._calculate_siblings_only(third_rank, third_rank_blood_types) 

109 ) 

110 self.log_operation( 

111 "Calculated shares: siblings only", 

112 basis="兄弟姉妹のみ(民法900条4号)" 

113 ) 

114 return shares 

115 

116 # 相続人がいない場合 

117 self.log_warning("No heirs found") 

118 return shares 

119 

120 def _calculate_spouse_only(self, spouses: List[Person]) -> Dict[str, Fraction]: 

121 """配偶者のみの場合(全部相続)""" 

122 shares = {} 

123 share_per_spouse = Fraction(1, len(spouses)) 

124 for spouse in spouses: 

125 shares[str(spouse.id)] = share_per_spouse 

126 return shares 

127 

128 def _calculate_spouse_and_children( 

129 self, spouses: List[Person], children: List[Person] 

130 ) -> Dict[str, Fraction]: 

131 """ 

132 配偶者と子の場合 

133 

134 民法900条1号: 

135 - 配偶者: 1/2 

136 - 子: 1/2を均等に分割 

137 """ 

138 shares = {} 

139 

140 # 配偶者: 1/2 

141 spouse_total = Fraction(1, 2) 

142 share_per_spouse = spouse_total / len(spouses) 

143 for spouse in spouses: 

144 shares[str(spouse.id)] = share_per_spouse 

145 

146 # 子: 1/2を均等に分割 

147 children_total = Fraction(1, 2) 

148 share_per_child = children_total / len(children) 

149 for child in children: 

150 shares[str(child.id)] = share_per_child 

151 

152 return shares 

153 

154 def _calculate_children_only(self, children: List[Person]) -> Dict[str, Fraction]: 

155 """子のみの場合(均等分割)""" 

156 shares = {} 

157 share_per_child = Fraction(1, len(children)) 

158 for child in children: 

159 shares[str(child.id)] = share_per_child 

160 return shares 

161 

162 def _calculate_spouse_and_parents( 

163 self, spouses: List[Person], parents: List[Person] 

164 ) -> Dict[str, Fraction]: 

165 """ 

166 配偶者と直系尊属の場合 

167 

168 民法900条2号: 

169 - 配偶者: 2/3 

170 - 直系尊属: 1/3を均等に分割 

171 """ 

172 shares = {} 

173 

174 # 配偶者: 2/3 

175 spouse_total = Fraction(2, 3) 

176 share_per_spouse = spouse_total / len(spouses) 

177 for spouse in spouses: 

178 shares[str(spouse.id)] = share_per_spouse 

179 

180 # 直系尊属: 1/3を均等に分割 

181 parents_total = Fraction(1, 3) 

182 share_per_parent = parents_total / len(parents) 

183 for parent in parents: 

184 shares[str(parent.id)] = share_per_parent 

185 

186 return shares 

187 

188 def _calculate_parents_only(self, parents: List[Person]) -> Dict[str, Fraction]: 

189 """直系尊属のみの場合(均等分割)""" 

190 shares = {} 

191 share_per_parent = Fraction(1, len(parents)) 

192 for parent in parents: 

193 shares[str(parent.id)] = share_per_parent 

194 return shares 

195 

196 def _calculate_spouse_and_siblings( 

197 self, 

198 spouses: List[Person], 

199 siblings: List[Person], 

200 blood_types: Dict[str, BloodType] 

201 ) -> Dict[str, Fraction]: 

202 """ 

203 配偶者と兄弟姉妹の場合 

204 

205 民法900条3号: 

206 - 配偶者: 3/4 

207 - 兄弟姉妹: 1/4を分割 

208 

209 民法900条4号: 

210 - 半血兄弟姉妹の相続分は全血兄弟姉妹の1/2 

211 """ 

212 shares = {} 

213 

214 # 配偶者: 3/4 

215 spouse_total = Fraction(3, 4) 

216 share_per_spouse = spouse_total / len(spouses) 

217 for spouse in spouses: 

218 shares[str(spouse.id)] = share_per_spouse 

219 

220 # 兄弟姉妹: 1/4を血縁タイプに応じて分割 

221 siblings_total = Fraction(1, 4) 

222 shares.update( 

223 self._calculate_sibling_shares(siblings, siblings_total, blood_types) 

224 ) 

225 

226 return shares 

227 

228 def _calculate_siblings_only( 

229 self, 

230 siblings: List[Person], 

231 blood_types: Dict[str, BloodType] 

232 ) -> Dict[str, Fraction]: 

233 """ 

234 兄弟姉妹のみの場合 

235 

236 民法900条4号: 

237 - 半血兄弟姉妹の相続分は全血兄弟姉妹の1/2 

238 """ 

239 shares = {} 

240 total = Fraction(1, 1) 

241 shares.update(self._calculate_sibling_shares(siblings, total, blood_types)) 

242 return shares 

243 

244 def _calculate_sibling_shares( 

245 self, 

246 siblings: List[Person], 

247 total: Fraction, 

248 blood_types: Dict[str, BloodType] 

249 ) -> Dict[str, Fraction]: 

250 """ 

251 兄弟姉妹の相続分を計算 

252 

253 民法900条4号:半血兄弟姉妹の相続分は全血兄弟姉妹の1/2 

254 

255 Args: 

256 siblings: 兄弟姉妹のリスト 

257 total: 兄弟姉妹全体の相続分 

258 blood_types: 血縁タイプ(人物ID → BloodType) 

259 

260 Returns: 

261 人物ID → 相続割合の辞書 

262 """ 

263 shares = {} 

264 

265 # 全血・半血の人数をカウント 

266 full_blood_count = sum( 

267 1 for s in siblings 

268 if blood_types.get(str(s.id), BloodType.FULL) == BloodType.FULL 

269 ) 

270 half_blood_count = len(siblings) - full_blood_count 

271 

272 # 全血を1、半血を0.5として重み付けした総数を計算 

273 # 全血1人 = 重み1.0、半血1人 = 重み0.5 

274 total_weight = full_blood_count + (half_blood_count * Fraction(1, 2)) 

275 

276 # 各兄弟姉妹の相続分を計算 

277 for sibling in siblings: 

278 blood_type = blood_types.get(str(sibling.id), BloodType.FULL) 

279 

280 if blood_type == BloodType.FULL: 

281 # 全血: total / total_weight 

282 shares[str(sibling.id)] = total / total_weight 

283 else: 

284 # 半血: (total / total_weight) * 1/2 

285 shares[str(sibling.id)] = (total / total_weight) * Fraction(1, 2) 

286 

287 return shares