Commit 447dfbce authored by Fares's avatar Fares

fix(death): trustee fee percentage now reliably uses current plan price

The board approval percentage calculation had fragile fallbacks that could
miss the pricing_configs data and fall back to the old membership_value.
Added cascading fallbacks: PricingEngine → branch+qual → branch-only →
any active pricing → membership_value (last resort).

Also fixed the JS preview in show.php which was using the stored
membership_value (114,000) instead of the current plan price (150,000)
for the real-time calculation hint.
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent 93215a48
......@@ -329,6 +329,34 @@ class DeathController extends Controller
$boardApprover = $db->selectOne("SELECT full_name_ar FROM employees WHERE id = ?", [(int) $case['board_approved_by']]);
}
// Get current plan price for JS preview (not the old membership_value)
$currentPlanPrice = '0.00';
$memberRow = $db->selectOne("SELECT branch_id, qualification_id, membership_type FROM members WHERE id = ?", [(int) $case['member_id']]);
if ($memberRow) {
$brId = (int) ($memberRow['branch_id'] ?? 1);
$qId = !empty($memberRow['qualification_id']) ? (int) $memberRow['qualification_id'] : null;
if ($qId) {
$qual = $db->selectOne("SELECT code FROM qualifications WHERE id = ?", [$qId]);
if ($qual && $qual['code']) {
$priceInfo = \App\Modules\Pricing\Services\PricingEngine::getMembershipPrice($brId, $qual['code']);
if (!empty($priceInfo['price']) && bccomp($priceInfo['price'], '0.01', 2) >= 0) {
$currentPlanPrice = $priceInfo['price'];
}
}
}
if (bccomp($currentPlanPrice, '0.01', 2) < 0) {
$pr = $db->selectOne(
"SELECT price FROM pricing_configs WHERE branch_id = ? AND is_active = 1 AND effective_from <= CURDATE() AND (effective_to IS NULL OR effective_to >= CURDATE()) ORDER BY price DESC LIMIT 1",
[$brId]
);
if ($pr) $currentPlanPrice = $pr['price'];
}
if (bccomp($currentPlanPrice, '0.01', 2) < 0) {
$pr = $db->selectOne("SELECT price FROM pricing_configs WHERE is_active = 1 ORDER BY price DESC LIMIT 1");
if ($pr) $currentPlanPrice = $pr['price'];
}
}
return $this->view('Death.Views.show', [
'case' => $case,
'fees' => $fees,
......@@ -338,6 +366,7 @@ class DeathController extends Controller
'newMember' => $newMember,
'paymentRequest' => $paymentRequest,
'boardApprover' => $boardApprover,
'currentPlanPrice' => $currentPlanPrice,
]);
}
......@@ -373,20 +402,55 @@ class DeathController extends Controller
if ($feeMethod === 'percentage') {
$branchId = (int) ($memberRow['branch_id'] ?? 1);
$qualId = !empty($memberRow['qualification_id']) ? (int) $memberRow['qualification_id'] : null;
// Try via PricingEngine with qualification
if ($qualId) {
$qual = $db->selectOne("SELECT code FROM qualifications WHERE id = ?", [$qualId]);
if ($qual && $qual['code']) {
$priceInfo = \App\Modules\Pricing\Services\PricingEngine::getMembershipPrice($branchId, $qual['code']);
$currentPlanPrice = $priceInfo['price'] ?? '0.00';
if (!empty($priceInfo['price']) && bccomp($priceInfo['price'], '0.01', 2) >= 0) {
$currentPlanPrice = $priceInfo['price'];
}
}
}
// Fallback 1: query pricing_configs by branch + qualification_id directly
if (bccomp($currentPlanPrice, '0.01', 2) < 0 && $qualId) {
$pricing = $db->selectOne(
"SELECT price FROM pricing_configs WHERE branch_id = ? AND qualification_id = ? AND is_active = 1 AND effective_from <= CURDATE() AND (effective_to IS NULL OR effective_to >= CURDATE()) ORDER BY effective_from DESC LIMIT 1",
[$branchId, $qualId]
);
if ($pricing && bccomp($pricing['price'], '0.01', 2) >= 0) {
$currentPlanPrice = $pricing['price'];
}
}
// Fallback 2: any active pricing for this branch (highest price = working member)
if (bccomp($currentPlanPrice, '0.01', 2) < 0) {
$pricing = $db->selectOne(
"SELECT price FROM pricing_configs WHERE branch_id = ? AND membership_type = 'working' AND is_active = 1 AND effective_from <= CURDATE() AND (effective_to IS NULL OR effective_to >= CURDATE()) ORDER BY price DESC LIMIT 1",
"SELECT price FROM pricing_configs WHERE branch_id = ? AND is_active = 1 AND effective_from <= CURDATE() AND (effective_to IS NULL OR effective_to >= CURDATE()) ORDER BY price DESC LIMIT 1",
[$branchId]
);
$currentPlanPrice = $pricing['price'] ?? ($memberRow['membership_value'] ?? '0.00');
if ($pricing && bccomp($pricing['price'], '0.01', 2) >= 0) {
$currentPlanPrice = $pricing['price'];
}
}
// Fallback 3: any active pricing across all branches (last resort before membership_value)
if (bccomp($currentPlanPrice, '0.01', 2) < 0) {
$pricing = $db->selectOne(
"SELECT price FROM pricing_configs WHERE is_active = 1 AND effective_from <= CURDATE() AND (effective_to IS NULL OR effective_to >= CURDATE()) ORDER BY price DESC LIMIT 1"
);
if ($pricing && bccomp($pricing['price'], '0.01', 2) >= 0) {
$currentPlanPrice = $pricing['price'];
}
}
// Last fallback: stored membership_value (should never reach here if pricing_configs has data)
if (bccomp($currentPlanPrice, '0.01', 2) < 0) {
$currentPlanPrice = $memberRow['membership_value'] ?? '0.00';
}
$boardFeeAmount = bcdiv(bcmul($currentPlanPrice, $feeValue, 6), '100', 2);
} else {
$boardFeeAmount = bcadd($feeValue, '0', 2);
......
......@@ -299,7 +299,7 @@ document.addEventListener('DOMContentLoaded', function() {
var feeValue = document.getElementById('board_fee_value');
var feeLabel = document.getElementById('fee_value_label');
var feeHint = document.getElementById('fee_calc_hint');
var membershipValue = <?= (float) ($case['member_membership_value'] ?? 0) ?>;
var currentPlanPrice = <?= (float) ($currentPlanPrice ?? 0) ?>;
if (feeMethod) {
feeMethod.addEventListener('change', function() {
......@@ -307,8 +307,8 @@ document.addEventListener('DOMContentLoaded', function() {
feeLabel.innerHTML = 'النسبة المئوية (%) <span style="color:#DC2626;">*</span>';
feeValue.placeholder = 'مثال: 8';
feeValue.step = '0.01';
feeHint.textContent = membershipValue > 0
? 'مثال: 8% من ' + membershipValue.toLocaleString('ar-EG') + ' = ' + (membershipValue * 0.08).toFixed(2)
feeHint.textContent = currentPlanPrice > 0
? 'النسبة تُحسب من قيمة الخطة الحالية: ' + currentPlanPrice.toLocaleString('ar-EG') + ' ج.م — مثال: 8% = ' + (currentPlanPrice * 0.08).toFixed(2)
: 'أدخل النسبة المئوية';
} else if (this.value === 'fixed') {
feeLabel.innerHTML = 'المبلغ الثابت (ج.م) <span style="color:#DC2626;">*</span>';
......@@ -319,10 +319,10 @@ document.addEventListener('DOMContentLoaded', function() {
});
feeValue.addEventListener('input', function() {
if (feeMethod.value === 'percentage' && membershipValue > 0) {
if (feeMethod.value === 'percentage' && currentPlanPrice > 0) {
var pct = parseFloat(this.value) || 0;
var calc = (membershipValue * pct / 100).toFixed(2);
feeHint.textContent = 'المبلغ المحسوب: ' + parseFloat(calc).toLocaleString('ar-EG') + ' ج.م';
var calc = (currentPlanPrice * pct / 100).toFixed(2);
feeHint.textContent = pct + '% من ' + currentPlanPrice.toLocaleString('ar-EG') + ' = ' + parseFloat(calc).toLocaleString('ar-EG') + ' ج.م';
}
});
}
......
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