Commit 42f0ccc6 authored by Mahmoud Aglan's avatar Mahmoud Aglan

Remove child fees from divorce transfer — fees only on new additions post-separation

Per bylaws clarification: children transferred during divorce separation move
without fees. Age-based fees (15%/20%/25%/30%) apply only when the new
independent member adds NEW children after the separation is complete.

- Removed child fee calculation from boardApprove flow
- Children selection is now transfer-only (no fee columns)
- Updated fee preview JS to exclude child fees
- Fee breakdown shows "transferred without fees" for moved children
- Total = percentage_fee + form_fee (570) + annual_subscription only
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent 94e1f426
...@@ -139,22 +139,26 @@ class DivorceController extends Controller ...@@ -139,22 +139,26 @@ class DivorceController extends Controller
$formFee = DivorceFeeCalculator::getFormFee(); $formFee = DivorceFeeCalculator::getFormFee();
$annualSub = DivorceFeeCalculator::getAnnualSubscription(); $annualSub = DivorceFeeCalculator::getAnnualSubscription();
// Children transfer fees (if any selected) // Children to transfer (no fees — fees only apply when adding NEW children after separation)
$childrenSelected = $request->post('children', []); $childrenSelected = $request->post('children', []);
$childFeeTotal = '0.00';
$childrenAssignment = []; $childrenAssignment = [];
if (!empty($childrenSelected) && is_array($childrenSelected)) { if (!empty($childrenSelected) && is_array($childrenSelected)) {
$childCalc = DivorceFeeCalculator::calculateChildFees((int) $case['member_id'], $membershipValue); $children = $db->select(
foreach ($childCalc['children'] as $child) { "SELECT id, full_name_ar, date_of_birth FROM children WHERE member_id = ? AND is_archived = 0 AND status = 'active'",
[(int) $case['member_id']]
);
foreach ($children as $child) {
if (in_array((string) $child['id'], $childrenSelected, true)) { if (in_array((string) $child['id'], $childrenSelected, true)) {
$childFeeTotal = bcadd($childFeeTotal, $child['fee'], 2); $childrenAssignment[] = [
$childrenAssignment[] = $child; 'id' => (int) $child['id'],
'name' => $child['full_name_ar'],
];
} }
} }
} }
$totalFee = bcadd(bcadd(bcadd($percentageFee, $formFee, 2), $annualSub, 2), $childFeeTotal, 2); $totalFee = bcadd(bcadd($percentageFee, $formFee, 2), $annualSub, 2);
$db->update('divorce_cases', [ $db->update('divorce_cases', [
'fee_percentage' => $feePercentage, 'fee_percentage' => $feePercentage,
...@@ -178,8 +182,8 @@ class DivorceController extends Controller ...@@ -178,8 +182,8 @@ class DivorceController extends Controller
'رسوم استمارة (570): ' . money($formFee), 'رسوم استمارة (570): ' . money($formFee),
'اشتراك سنوي: ' . money($annualSub), 'اشتراك سنوي: ' . money($annualSub),
]; ];
if (bccomp($childFeeTotal, '0', 2) > 0) { if (!empty($childrenAssignment)) {
$breakdown[] = 'رسوم ضم أبناء: ' . money($childFeeTotal) . ' (' . count($childrenAssignment) . ' أبناء)'; $breakdown[] = 'نقل أبناء (بدون رسوم): ' . count($childrenAssignment) . ' أبناء';
} }
$breakdown[] = '═══════════════════════════'; $breakdown[] = '═══════════════════════════';
$breakdown[] = 'الإجمالي: ' . money($totalFee); $breakdown[] = 'الإجمالي: ' . money($totalFee);
...@@ -245,7 +249,6 @@ class DivorceController extends Controller ...@@ -245,7 +249,6 @@ class DivorceController extends Controller
$membershipValueSource = $valueInfo['source']; $membershipValueSource = $valueInfo['source'];
$children = []; $children = [];
$childFees = null;
$suggestedPercentage = null; $suggestedPercentage = null;
if ($case['status'] === 'board_review') { if ($case['status'] === 'board_review') {
...@@ -253,14 +256,17 @@ class DivorceController extends Controller ...@@ -253,14 +256,17 @@ class DivorceController extends Controller
if ($feeCalc['success'] ?? false) { if ($feeCalc['success'] ?? false) {
$suggestedPercentage = $feeCalc['suggested_percentage'] ?? null; $suggestedPercentage = $feeCalc['suggested_percentage'] ?? null;
} }
$childFees = DivorceFeeCalculator::calculateChildFees((int) $case['member_id'], $currentMembershipValue); // Load children for transfer selection (no fees — fees only on new additions after separation)
$children = $childFees['children'] ?? []; $db = App::getInstance()->db();
$children = $db->select(
"SELECT id, full_name_ar, date_of_birth FROM children WHERE member_id = ? AND is_archived = 0 AND status = 'active'",
[(int) $case['member_id']]
);
} }
return $this->view('Divorce.Views.show', [ return $this->view('Divorce.Views.show', [
'case' => $case, 'case' => $case,
'children' => $children, 'children' => $children,
'childFees' => $childFees,
'suggestedPercentage' => $suggestedPercentage, 'suggestedPercentage' => $suggestedPercentage,
'currentMembershipValue' => $currentMembershipValue, 'currentMembershipValue' => $currentMembershipValue,
'membershipValueSource' => $membershipValueSource, 'membershipValueSource' => $membershipValueSource,
......
...@@ -121,40 +121,28 @@ $statusLabel = $statusLabels[$case['status']] ?? $case['status']; ...@@ -121,40 +121,28 @@ $statusLabel = $statusLabels[$case['status']] ?? $case['status'];
</div> </div>
</div> </div>
<!-- Children assignment --> <!-- Children transfer selection (no fees — fees only on new additions after separation) -->
<?php if (!empty($children)): ?> <?php if (!empty($children)): ?>
<div style="background:#FEF3C7;border:1px solid #F59E0B;border-radius:8px;padding:15px;margin-bottom:15px;"> <div style="background:#EFF6FF;border:1px solid #2563EB;border-radius:8px;padding:15px;margin-bottom:15px;">
<h4 style="margin:0 0 10px;color:#D97706;font-size:14px;">ضم الأبناء للعضوية المستقلة</h4> <h4 style="margin:0 0 10px;color:#1D4ED8;font-size:14px;">نقل الأبناء للعضوية المستقلة</h4>
<p style="font-size:12px;color:#6B7280;margin-bottom:10px;">حدد الأبناء المراد نقلهم — الرسوم تُحسب حسب العمر وفقاً للائحة</p> <p style="font-size:12px;color:#6B7280;margin-bottom:10px;">حدد الأبناء المراد نقلهم — النقل بدون رسوم إضافية (الرسوم تُطبق فقط عند إضافة أبناء جدد بعد الفصل)</p>
<table style="width:100%;font-size:13px;border-collapse:collapse;"> <table style="width:100%;font-size:13px;border-collapse:collapse;">
<thead> <thead>
<tr style="background:#FDE68A;"> <tr style="background:#DBEAFE;">
<th style="padding:8px;text-align:right;">ضم</th> <th style="padding:8px;text-align:right;">نقل</th>
<th style="padding:8px;text-align:right;">الاسم</th> <th style="padding:8px;text-align:right;">الاسم</th>
<th style="padding:8px;text-align:right;">العمر</th> <th style="padding:8px;text-align:right;">تاريخ الميلاد</th>
<th style="padding:8px;text-align:right;">الفئة</th>
<th style="padding:8px;text-align:right;">النسبة</th>
<th style="padding:8px;text-align:left;">الرسوم</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<?php foreach ($children as $child): ?> <?php foreach ($children as $child): ?>
<tr style="border-bottom:1px solid #E5E7EB;"> <tr style="border-bottom:1px solid #E5E7EB;">
<td style="padding:8px;"><input type="checkbox" name="children[]" value="<?= (int) $child['id'] ?>" checked></td> <td style="padding:8px;"><input type="checkbox" name="children[]" value="<?= (int) $child['id'] ?>" checked></td>
<td style="padding:8px;font-weight:600;"><?= e($child['name']) ?></td> <td style="padding:8px;font-weight:600;"><?= e($child['full_name_ar']) ?></td>
<td style="padding:8px;"><?= (int) $child['age'] ?> سنة</td> <td style="padding:8px;"><?= e($child['date_of_birth']) ?></td>
<td style="padding:8px;font-size:11px;color:#6B7280;"><?= e($child['bracket_label']) ?></td>
<td style="padding:8px;font-weight:600;color:#D97706;"><?= e($child['percentage']) ?>%</td>
<td style="padding:8px;font-weight:700;direction:ltr;text-align:left;"><?= money($child['fee']) ?></td>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
</tbody> </tbody>
<tfoot>
<tr style="background:#FDE68A;">
<td colspan="5" style="padding:8px;font-weight:700;">إجمالي رسوم الأبناء</td>
<td style="padding:8px;font-weight:800;direction:ltr;text-align:left;"><?= money($childFees['total_fee'] ?? '0') ?></td>
</tr>
</tfoot>
</table> </table>
</div> </div>
<?php endif; ?> <?php endif; ?>
...@@ -219,18 +207,11 @@ $statusLabel = $statusLabels[$case['status']] ?? $case['status']; ...@@ -219,18 +207,11 @@ $statusLabel = $statusLabels[$case['status']] ?? $case['status'];
<?php <?php
$assignedChildren = !empty($case['children_assignment_json']) ? json_decode($case['children_assignment_json'], true) : []; $assignedChildren = !empty($case['children_assignment_json']) ? json_decode($case['children_assignment_json'], true) : [];
if (!empty($assignedChildren)): if (!empty($assignedChildren)):
$childTotal = '0.00';
foreach ($assignedChildren as $ac) { $childTotal = bcadd($childTotal, $ac['fee'], 2); }
?> ?>
<tr style="border-top:1px solid #E5E7EB;"> <tr style="border-top:1px solid #E5E7EB;">
<td style="padding:8px 0;color:#6B7280;">رسوم ضم أبناء (<?= count($assignedChildren) ?> أبناء)</td> <td style="padding:8px 0;color:#6B7280;">أبناء تم نقلهم (بدون رسوم)</td>
<td style="padding:8px 0;font-weight:600;direction:ltr;text-align:left;"><?= money($childTotal) ?></td> <td style="padding:8px 0;font-size:12px;color:#6B7280;"><?= e(implode('، ', array_column($assignedChildren, 'name'))) ?></td>
</tr> </tr>
<tr><td colspan="2" style="padding:4px 0;font-size:11px;color:#6B7280;">
<?php foreach ($assignedChildren as $ac): ?>
<?= e($ac['name']) ?> (<?= (int) $ac['age'] ?> سنة — <?= e($ac['percentage']) ?>% = <?= money($ac['fee']) ?>)<br>
<?php endforeach; ?>
</td></tr>
<?php endif; ?> <?php endif; ?>
<tr style="border-top:2px solid #0D7377;"> <tr style="border-top:2px solid #0D7377;">
<td style="padding:12px 0;font-weight:700;font-size:16px;">الإجمالي المطلوب</td> <td style="padding:12px 0;font-weight:700;font-size:16px;">الإجمالي المطلوب</td>
...@@ -312,16 +293,7 @@ document.addEventListener('DOMContentLoaded', function() { ...@@ -312,16 +293,7 @@ document.addEventListener('DOMContentLoaded', function() {
function updatePreview() { function updatePreview() {
var perc = parseFloat(percInput.value) || 0; var perc = parseFloat(percInput.value) || 0;
var percFee = (membershipValue * perc / 100); var percFee = (membershipValue * perc / 100);
var childFee = 0; var total = percFee + formFee + annualSub;
document.querySelectorAll('input[name="children[]"]:checked').forEach(function(cb) {
var row = cb.closest('tr');
var feeCell = row.querySelector('td:last-child');
if (feeCell) {
var txt = feeCell.textContent.replace(/[^\d.]/g, '');
childFee += parseFloat(txt) || 0;
}
});
var total = percFee + formFee + annualSub + childFee;
var preview = document.getElementById('fee-preview'); var preview = document.getElementById('fee-preview');
var content = document.getElementById('fee-preview-content'); var content = document.getElementById('fee-preview-content');
if (perc > 0) { if (perc > 0) {
...@@ -329,8 +301,8 @@ document.addEventListener('DOMContentLoaded', function() { ...@@ -329,8 +301,8 @@ document.addEventListener('DOMContentLoaded', function() {
var html = 'رسوم الطلاق (' + perc + '% × ' + membershipValue.toLocaleString() + '): <strong>' + percFee.toLocaleString() + ' ج.م</strong><br>' + var html = 'رسوم الطلاق (' + perc + '% × ' + membershipValue.toLocaleString() + '): <strong>' + percFee.toLocaleString() + ' ج.م</strong><br>' +
'رسوم استمارة: <strong>' + formFee.toLocaleString() + ' ج.م</strong><br>' + 'رسوم استمارة: <strong>' + formFee.toLocaleString() + ' ج.م</strong><br>' +
'اشتراك سنوي: <strong>' + annualSub.toLocaleString() + ' ج.م</strong><br>'; 'اشتراك سنوي: <strong>' + annualSub.toLocaleString() + ' ج.م</strong><br>';
if (childFee > 0) html += 'رسوم ضم أبناء: <strong>' + childFee.toLocaleString() + ' ج.م</strong><br>';
html += '<hr style="margin:5px 0;border-color:#059669;"><strong style="font-size:16px;color:#DC2626;">الإجمالي: ' + total.toLocaleString() + ' ج.م</strong>'; html += '<hr style="margin:5px 0;border-color:#059669;"><strong style="font-size:16px;color:#DC2626;">الإجمالي: ' + total.toLocaleString() + ' ج.م</strong>';
html += '<br><small style="color:#6B7280;">نقل الأبناء بدون رسوم إضافية</small>';
content.innerHTML = html; content.innerHTML = html;
} else { } else {
preview.style.display = 'none'; preview.style.display = 'none';
...@@ -338,9 +310,6 @@ document.addEventListener('DOMContentLoaded', function() { ...@@ -338,9 +310,6 @@ document.addEventListener('DOMContentLoaded', function() {
} }
percInput.addEventListener('input', updatePreview); percInput.addEventListener('input', updatePreview);
document.querySelectorAll('input[name="children[]"]').forEach(function(cb) {
cb.addEventListener('change', updatePreview);
});
updatePreview(); updatePreview();
}); });
</script> </script>
......
# Divorce Module — Architecture Map # Divorce Module — Architecture Map
> **Last updated:** 2026-06-17 (added both_working case type, restored child <12 to 15%, unified joined_after to 50%) > **Last updated:** 2026-06-17 (child transfer is free; fees only on new additions post-separation; uses current pricing)
> **Status:** Living document — incrementally updated as new information is discovered > **Status:** Living document — incrementally updated as new information is discovered
--- ---
...@@ -126,12 +126,12 @@ board_review → board_approved → fee_paid → completed ...@@ -126,12 +126,12 @@ board_review → board_approved → fee_paid → completed
3. POST /divorce/{id}/board-approve 3. POST /divorce/{id}/board-approve
- Board enters: fee_percentage, board_decision_number, board_decision_date, notes - Board enters: fee_percentage, board_decision_number, board_decision_date, notes
- Board selects children to transfer (checkboxes, fees calculated by age bracket) - Board selects children to transfer (checkboxes, NO FEES — transfer is free)
- Membership value fetched from pricing_configs (current price, not stored value)
- Calculate fees: - Calculate fees:
Fee = (fee_percentage / 100) × membership_value Fee = (fee_percentage / 100) × current_membership_value
ChildFees = sum of (child_percentage × membership_value) for each selected child Total = Fee + form_fee (570) + annual_subscription (257)
Total = Fee + form_fee (570) + annual_subscription (257) + ChildFees - Save children_assignment_json with child details (id, name only)
- Save children_assignment_json with child details (id, name, age, percentage, fee)
- Status → 'board_approved' - Status → 'board_approved'
- Auto-send payment request to Cashier queue - Auto-send payment request to Cashier queue
- Dispatch: divorce.board_approved - Dispatch: divorce.board_approved
...@@ -187,11 +187,10 @@ Fee Components: ...@@ -187,11 +187,10 @@ Fee Components:
- same_form (on original form) → suggested 10%, treated as membership basis - same_form (on original form) → suggested 10%, treated as membership basis
- joined_after (acquired membership) → suggested 50%, treated as acquired member - 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: FREE (no fees during divorce separation)
- Under 12: 15% of membership_value (DIVORCE_CHILD_UNDER_12) Children transferred to the new membership are moved without additional charges.
- 12 to <16: 20% (DIVORCE_CHILD_12_TO_16) Age-based fees (15%/20%/25%/30%) apply ONLY when adding NEW children
- 16 to <18: 25% (DIVORCE_CHILD_16_TO_18) to the independent membership AFTER the separation is complete.
- 18+: 30% (DIVORCE_CHILD_OVER_18)
Total = (percentage × membership_value) + form_fee + annual_subscription + children_fees Total = (percentage × membership_value) + form_fee + annual_subscription + children_fees
......
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