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
« prev ^ index » next coverage.py v7.11.0, created at 2025-10-17 05:31 +0900
1"""相続割合計算サービス
3日本の民法に基づいて相続割合(法定相続分)を計算するサービス。
4"""
5from typing import List, Dict, Optional
6from fractions import Fraction
8from ..models.person import Person
9from ..models.relationship import BloodType
10from ..models.inheritance import HeritageRank
11from .base import BaseService
14class ShareCalculator(BaseService[Person]):
15 """
16 相続割合計算サービス
18 法定相続分を計算する。
19 """
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 相続割合を計算
32 Args:
33 spouses: 配偶者のリスト
34 first_rank: 第1順位の相続人(子)
35 second_rank: 第2順位の相続人(直系尊属)
36 third_rank: 第3順位の相続人(兄弟姉妹)
37 third_rank_blood_types: 第3順位の血縁タイプ(人物ID → BloodType)
39 Returns:
40 人物ID → 相続割合の辞書
41 """
42 if third_rank_blood_types is None:
43 third_rank_blood_types = {}
45 shares: Dict[str, Fraction] = {}
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
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
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
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
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
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
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
116 # 相続人がいない場合
117 self.log_warning("No heirs found")
118 return shares
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
128 def _calculate_spouse_and_children(
129 self, spouses: List[Person], children: List[Person]
130 ) -> Dict[str, Fraction]:
131 """
132 配偶者と子の場合
134 民法900条1号:
135 - 配偶者: 1/2
136 - 子: 1/2を均等に分割
137 """
138 shares = {}
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
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
152 return shares
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
162 def _calculate_spouse_and_parents(
163 self, spouses: List[Person], parents: List[Person]
164 ) -> Dict[str, Fraction]:
165 """
166 配偶者と直系尊属の場合
168 民法900条2号:
169 - 配偶者: 2/3
170 - 直系尊属: 1/3を均等に分割
171 """
172 shares = {}
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
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
186 return shares
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
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 配偶者と兄弟姉妹の場合
205 民法900条3号:
206 - 配偶者: 3/4
207 - 兄弟姉妹: 1/4を分割
209 民法900条4号:
210 - 半血兄弟姉妹の相続分は全血兄弟姉妹の1/2
211 """
212 shares = {}
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
220 # 兄弟姉妹: 1/4を血縁タイプに応じて分割
221 siblings_total = Fraction(1, 4)
222 shares.update(
223 self._calculate_sibling_shares(siblings, siblings_total, blood_types)
224 )
226 return shares
228 def _calculate_siblings_only(
229 self,
230 siblings: List[Person],
231 blood_types: Dict[str, BloodType]
232 ) -> Dict[str, Fraction]:
233 """
234 兄弟姉妹のみの場合
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
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 兄弟姉妹の相続分を計算
253 民法900条4号:半血兄弟姉妹の相続分は全血兄弟姉妹の1/2
255 Args:
256 siblings: 兄弟姉妹のリスト
257 total: 兄弟姉妹全体の相続分
258 blood_types: 血縁タイプ(人物ID → BloodType)
260 Returns:
261 人物ID → 相続割合の辞書
262 """
263 shares = {}
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
272 # 全血を1、半血を0.5として重み付けした総数を計算
273 # 全血1人 = 重み1.0、半血1人 = 重み0.5
274 total_weight = full_blood_count + (half_blood_count * Fraction(1, 2))
276 # 各兄弟姉妹の相続分を計算
277 for sibling in siblings:
278 blood_type = blood_types.get(str(sibling.id), BloodType.FULL)
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)
287 return shares