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

1"""相続割合計算サービス

2

3日本の民法に基づいて相続割合（法定相続分）を計算するサービス。

4"""

5 from typing import List, Dict, Optional

6 from fractions import Fraction

7

8 from ..models.person import Person

9 from ..models.relationship import BloodType

10 from ..models.inheritance import HeritageRank

11 from .base import BaseService

12

13

14 class 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