Commit e64c8865 authored by Mahmoud Aglan's avatar Mahmoud Aglan

Fix divorce fee calculation: add both_working case, restore child <12 to 15%, unify 50%

- Added 'both_working' case type detection via spouse.classification field
  (annual subscription only, 0% separation fee per bylaws)
- Restored DIVORCE_CHILD_UNDER_12 percentage from 5% back to 15% per bylaws
- Unified joined_after suggested percentage to 50% regardless of spouse order
- Updated show.php to display both_working scenario in board panel
- Updated architecture map with corrected business rules
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent 92781c0b
...@@ -34,6 +34,13 @@ final class DivorceFeeCalculator ...@@ -34,6 +34,13 @@ final class DivorceFeeCalculator
public static function getSuggestedPercentage(int $spouseOrder, string $caseType): array public static function getSuggestedPercentage(int $spouseOrder, string $caseType): array
{ {
if ($caseType === 'both_working') {
return [
'percentage' => '0.00',
'label' => 'كلاهما عامل قبل الزواج — الاشتراك السنوي فقط',
];
}
if ($caseType === 'same_form') { if ($caseType === 'same_form') {
$data = RuleEngine::get('DIVORCE_SAME_FORM_FEE'); $data = RuleEngine::get('DIVORCE_SAME_FORM_FEE');
return [ return [
...@@ -42,17 +49,10 @@ final class DivorceFeeCalculator ...@@ -42,17 +49,10 @@ final class DivorceFeeCalculator
]; ];
} }
if ($spouseOrder <= 1) {
$data = RuleEngine::get('DIVORCE_JOINED_AFTER_FEE'); $data = RuleEngine::get('DIVORCE_JOINED_AFTER_FEE');
return [ return [
'percentage' => $data['percentage'] ?? '50.00', 'percentage' => $data['percentage'] ?? '50.00',
'label' => 'الزوج/ة الأولى — 50%', 'label' => 'الزوج/ة مكتسب عضوية — 50%',
];
}
return [
'percentage' => '75.00',
'label' => 'الزوج/ة الثانية — 75%',
]; ];
} }
...@@ -153,16 +153,20 @@ final class DivorceFeeCalculator ...@@ -153,16 +153,20 @@ final class DivorceFeeCalculator
return ['success' => false, 'error' => "الحد الأدنى لسنوات العضوية {$minYears} سنوات من تاريخ انضمام الزوج/ة (يُعفى في حالة وجود أبناء)"]; return ['success' => false, 'error' => "الحد الأدنى لسنوات العضوية {$minYears} سنوات من تاريخ انضمام الزوج/ة (يُعفى في حالة وجود أبناء)"];
} }
// Determine case type based on join dates // Determine case type based on spouse classification and join dates
$spouseClassification = $spouse['classification'] ?? '';
$caseType = 'joined_after'; $caseType = 'joined_after';
if ($spouseClassification === 'working') {
$caseType = 'both_working';
} else {
$memberCreated = substr($member['created_at'] ?? $member['form_date'] ?? '', 0, 10); $memberCreated = substr($member['created_at'] ?? $member['form_date'] ?? '', 0, 10);
$spouseJoinDateStr = substr($spouseJoinDate, 0, 10); $spouseJoinDateStr = substr($spouseJoinDate, 0, 10);
if ($memberCreated === $spouseJoinDateStr || $spouseClassification === 'initial_form') {
if ($memberCreated === $spouseJoinDateStr) {
$caseType = 'same_form'; $caseType = 'same_form';
} }
}
// Spouse order determines suggested fee (50% first, 75% second)
$spouseOrder = (int) ($spouse['spouse_order'] ?? 1); $spouseOrder = (int) ($spouse['spouse_order'] ?? 1);
$suggested = self::getSuggestedPercentage($spouseOrder, $caseType); $suggested = self::getSuggestedPercentage($spouseOrder, $caseType);
......
...@@ -94,12 +94,12 @@ $statusLabel = $statusLabels[$case['status']] ?? $case['status']; ...@@ -94,12 +94,12 @@ $statusLabel = $statusLabels[$case['status']] ?? $case['status'];
$spouseOrder = (int) ($case['spouse_order'] ?? 1); $spouseOrder = (int) ($case['spouse_order'] ?? 1);
$caseType = $case['divorce_case_type'] ?? 'joined_after'; $caseType = $case['divorce_case_type'] ?? 'joined_after';
?> ?>
<?php if ($caseType === 'same_form'): ?> <?php if ($caseType === 'both_working'): ?>
<span style="font-weight:700;color:#059669;">0%</span> — كلاهما عامل قبل الزواج (الاشتراك السنوي فقط)
<?php elseif ($caseType === 'same_form'): ?>
<span style="font-weight:700;color:#2563EB;">10%</span> — قُبلا في استمارة واحدة <span style="font-weight:700;color:#2563EB;">10%</span> — قُبلا في استمارة واحدة
<?php elseif ($spouseOrder <= 1): ?>
<span style="font-weight:700;color:#2563EB;">50%</span> — الزوج/ة الأولى
<?php else: ?> <?php else: ?>
<span style="font-weight:700;color:#2563EB;">75%</span> — الزوج/ة الثانية <span style="font-weight:700;color:#2563EB;">50%</span> — الزوج/ة مكتسب عضوية
<?php endif; ?> <?php endif; ?>
</div> </div>
</div> </div>
......
<?php
declare(strict_types=1);
return [
'up' => "UPDATE business_rules SET current_value_json = '{\"percentage\": \"15.00\"}', updated_at = NOW() WHERE rule_code = 'DIVORCE_CHILD_UNDER_12'",
'down' => "UPDATE business_rules SET current_value_json = '{\"percentage\": \"5.00\"}', updated_at = NOW() WHERE rule_code = 'DIVORCE_CHILD_UNDER_12'",
];
# Divorce Module — Architecture Map # Divorce Module — Architecture Map
> **Last updated:** 2026-06-13 (fixed eligibility date, child transfer, rule correction, suggested percentage) > **Last updated:** 2026-06-17 (added both_working case type, restored child <12 to 15%, unified joined_after to 50%)
> **Status:** Living document — incrementally updated as new information is discovered > **Status:** Living document — incrementally updated as new information is discovered
--- ---
...@@ -174,20 +174,21 @@ Eligibility Check: ...@@ -174,20 +174,21 @@ Eligibility Check:
2. Member must have >= DIVORCE_MIN_MEMBERSHIP_YEARS (default 5 years) 2. Member must have >= DIVORCE_MIN_MEMBERSHIP_YEARS (default 5 years)
EXCEPTION: Waived if member has children (waived_if_children = true) EXCEPTION: Waived if member has children (waived_if_children = true)
Case Type: Case Type (determined by spouse.classification field):
- 'same_form': spouse joined on SAME DATE as member (joined together) - 'both_working': spouse classification='working' (both were working members before marriage merge)
- 'joined_after': spouse joined AFTER member acquired membership - 'same_form': spouse classification='initial_form' OR joined on SAME DATE as member
- 'joined_after': spouse joined AFTER member acquired membership (default)
Fee Components: Fee Components:
- Form Fee: FORM_TRANSFER_FEE rule OR SVC_ADDITION_FORM (default 570 EGP) - Form Fee: FORM_TRANSFER_FEE rule OR SVC_ADDITION_FORM (default 570 EGP)
- Annual Subscription: SVC_ANNUAL_CHILD rate + DEVELOPMENT_FEE (default 222 + 35 = 257 EGP) - Annual Subscription: SVC_ANNUAL_CHILD rate + DEVELOPMENT_FEE (default 222 + 35 = 257 EGP)
- Percentage Fee: SET BY BOARD (system suggests based on spouse_order): - Percentage Fee: SET BY BOARD (system suggests based on case type):
- same_form (joined together) → suggested 10% - both_working → suggested 0% (annual subscription only — no percentage fee)
- joined_after, spouse_order=1 (first spouse) → suggested 50% - same_form (on original form) → suggested 10%, treated as membership basis
- joined_after, spouse_order=2 (second spouse) → suggested 75% - joined_after (acquired membership) → suggested 50%, treated as acquired member
Board can override with ANY percentage Board can override with ANY percentage
- Children Transfer Fees (age-based, per bylaws): - Children Transfer Fees (age-based, per bylaws):
- Under 12: 5% of membership_value (DIVORCE_CHILD_UNDER_12) - Under 12: 15% of membership_value (DIVORCE_CHILD_UNDER_12)
- 12 to <16: 20% (DIVORCE_CHILD_12_TO_16) - 12 to <16: 20% (DIVORCE_CHILD_12_TO_16)
- 16 to <18: 25% (DIVORCE_CHILD_16_TO_18) - 16 to <18: 25% (DIVORCE_CHILD_16_TO_18)
- 18+: 30% (DIVORCE_CHILD_OVER_18) - 18+: 30% (DIVORCE_CHILD_OVER_18)
...@@ -305,10 +306,11 @@ The Divorce module has **no own permissions**. It reuses Transfers module permis ...@@ -305,10 +306,11 @@ The Divorce module has **no own permissions**. It reuses Transfers module permis
- But could be a bug if the intent was to charge full member subscription rate - But could be a bug if the intent was to charge full member subscription rate
### 11.6 Case Type Determination ### 11.6 Case Type Determination
- `same_form`: member creation date === spouse join date (joined together) - `both_working`: spouse.classification = 'working' (both were working members before marriage merge)
- `joined_after`: any other case - `same_form`: spouse.classification = 'initial_form' OR member creation date === spouse join date
- The case type is informational for the board — board still manually sets percentage - `joined_after`: any other case (default)
- No `both_working` case type handled in the controller (only in TransferEligibility) - The case type drives the suggested percentage: 0% / 10% / 50% respectively
- Board can still override with any percentage
--- ---
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment