Commit 196d97b0 authored by Mahmoud Aglan's avatar Mahmoud Aglan

feat(transfers): show detailed year calculation breakdown in child separation

Adds a calc_breakdown to the fee response showing acquisition_date,
effective_transfer_date, exact diff (years/months/days), and each year range
so staff can verify the calculation is correct.
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent dcd26dfe
...@@ -161,6 +161,32 @@ final class SeparationFeeCalculator ...@@ -161,6 +161,32 @@ final class SeparationFeeCalculator
return max(1, $diff->y); // floor: only completed years; min 1 for fee-table lookup return max(1, $diff->y); // floor: only completed years; min 1 for fee-table lookup
} }
public static function buildYearsBreakdown(string $acquisitionDate, string $effectiveDate, int $yearsSince, string $feePercentage): array
{
$from = new \DateTime(substr($acquisitionDate, 0, 10));
$to = new \DateTime(substr($effectiveDate, 0, 10));
$diff = $to->diff($from);
$years = [];
$cursor = clone $from;
for ($i = 1; $i <= $diff->y; $i++) {
$yearStart = $cursor->format('Y-m-d');
$cursor->modify('+1 year');
$years[] = ['year' => $i, 'from' => $yearStart, 'to' => $cursor->format('Y-m-d')];
}
return [
'acquisition_date' => substr($acquisitionDate, 0, 10),
'effective_transfer_date' => substr($effectiveDate, 0, 10),
'diff_years' => $diff->y,
'diff_months' => $diff->m,
'diff_days' => $diff->d,
'applied_years' => $yearsSince,
'fee_percentage' => $feePercentage,
'year_ranges' => $years,
];
}
/** /**
* Calculate the effective transfer date for فصل أبناء: * Calculate the effective transfer date for فصل أبناء:
* - If employed: effective = min(max(work_date, graduation_date), date_turned_25) * - If employed: effective = min(max(work_date, graduation_date), date_turned_25)
...@@ -262,6 +288,9 @@ final class SeparationFeeCalculator ...@@ -262,6 +288,9 @@ final class SeparationFeeCalculator
$feePercentage = self::getFeePercentageByYear($yearsSince); $feePercentage = self::getFeePercentageByYear($yearsSince);
// Build calculation breakdown for transparency
$calcBreakdown = self::buildYearsBreakdown($acquisitionDate, $effectiveTransferDate, $yearsSince, $feePercentage);
// Separation fee = percentage × current subscription price // Separation fee = percentage × current subscription price
$separationFee = bcdiv(bcmul($subscriptionPrice, (string) $feePercentage, 4), '100', 2); $separationFee = bcdiv(bcmul($subscriptionPrice, (string) $feePercentage, 4), '100', 2);
...@@ -307,6 +336,7 @@ final class SeparationFeeCalculator ...@@ -307,6 +336,7 @@ final class SeparationFeeCalculator
'dep_spouses' => $depSpouses, 'dep_spouses' => $depSpouses,
'dep_children' => $depChildren, 'dep_children' => $depChildren,
'dep_temps' => $depTemps, 'dep_temps' => $depTemps,
'calc_breakdown' => $calcBreakdown,
]; ];
} }
......
...@@ -114,6 +114,7 @@ ...@@ -114,6 +114,7 @@
<div class="form-group" id="elapsed-years-group" style="display:none;"> <div class="form-group" id="elapsed-years-group" style="display:none;">
<label class="form-label">سنوات الاكتساب المكتملة</label> <label class="form-label">سنوات الاكتساب المكتملة</label>
<div id="elapsed-years-display" style="padding:10px 14px;background:#FEF9C3;border-radius:6px;font-size:14px;font-weight:600;color:#92400E;"></div> <div id="elapsed-years-display" style="padding:10px 14px;background:#FEF9C3;border-radius:6px;font-size:14px;font-weight:600;color:#92400E;"></div>
<div id="elapsed-years-breakdown" style="display:none;margin-top:8px;padding:12px;background:#F8FAFC;border:1px solid #E2E8F0;border-radius:6px;font-size:12px;"></div>
<small style="color:#6B7280;font-size:11px;">محسوب بالتمام فقط — لا يُقرَّب للأعلى</small> <small style="color:#6B7280;font-size:11px;">محسوب بالتمام فقط — لا يُقرَّب للأعلى</small>
</div> </div>
</div> </div>
...@@ -550,8 +551,33 @@ ...@@ -550,8 +551,33 @@
if (type === 'child_separation' && d.years_since_acquisition) { if (type === 'child_separation' && d.years_since_acquisition) {
elapsedGroup.style.display = 'block'; elapsedGroup.style.display = 'block';
elapsedDisplay.textContent = d.years_since_acquisition + ' سنة — نسبة ' + d.fee_percentage + '%'; elapsedDisplay.textContent = d.years_since_acquisition + ' سنة — نسبة ' + d.fee_percentage + '%';
var bkEl = document.getElementById('elapsed-years-breakdown');
if (d.calc_breakdown) {
var bk = d.calc_breakdown;
var html = '<div style="margin-bottom:6px;color:#374151;"><strong>تفاصيل الحسبة:</strong></div>';
html += '<table style="width:100%;font-size:12px;border-collapse:collapse;">';
html += '<tr style="color:#6B7280;"><td>تاريخ إنشاء العضوية (من)</td><td style="font-weight:600;">' + bk.acquisition_date + '</td></tr>';
html += '<tr style="color:#6B7280;"><td>تاريخ الفصل الفعلي (إلى)</td><td style="font-weight:600;">' + bk.effective_transfer_date + '</td></tr>';
html += '<tr style="color:#6B7280;"><td>الفرق</td><td style="font-weight:600;">' + bk.diff_years + ' سنة و ' + bk.diff_months + ' شهر و ' + bk.diff_days + ' يوم</td></tr>';
html += '<tr style="color:#6B7280;"><td>السنوات المحتسبة (تمام فقط)</td><td style="font-weight:600;color:#0D7377;">' + bk.applied_years + '</td></tr>';
html += '<tr style="color:#6B7280;"><td>النسبة المطبقة</td><td style="font-weight:600;color:#0D7377;">' + bk.fee_percentage + '%</td></tr>';
html += '</table>';
if (bk.year_ranges && bk.year_ranges.length > 0) {
html += '<div style="margin-top:8px;padding-top:8px;border-top:1px solid #E2E8F0;color:#374151;"><strong>السنوات:</strong></div>';
html += '<div style="display:flex;flex-wrap:wrap;gap:4px;margin-top:4px;">';
bk.year_ranges.forEach(function(yr) {
html += '<span style="padding:2px 8px;background:#DBEAFE;border-radius:4px;font-size:11px;">سنة ' + yr.year + ': ' + yr.from + ' → ' + yr.to + '</span>';
});
html += '</div>';
}
bkEl.innerHTML = html;
bkEl.style.display = 'block';
} else {
bkEl.style.display = 'none';
}
} else { } else {
elapsedGroup.style.display = 'none'; elapsedGroup.style.display = 'none';
document.getElementById('elapsed-years-breakdown').style.display = 'none';
} }
} }
}) })
......
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