Commit 2e51bbb2 authored by Mahmoud Aglan's avatar Mahmoud Aglan

fix(installments): allow cheque total to exceed installment amount

Generator now allows amt*count >= remaining (not forced equal).
All cheques get the same amount; no last-cheque manipulation.
Preview and guard alert only block when total < remaining.
Server-side storeBatch already accepted grandTotal >= planTotal.
Co-Authored-By: 's avatarClaude Sonnet 4.6 <noreply@anthropic.com>
parent 1ec0c056
...@@ -305,11 +305,9 @@ $coveragePct = $planTotal > 0 ? min(100, round($uploadedTotal / $planTotal * 10 ...@@ -305,11 +305,9 @@ $coveragePct = $planTotal > 0 ? min(100, round($uploadedTotal / $planTotal * 10
var needed = REMAINING_COUNT; var needed = REMAINING_COUNT;
var remaining = Math.round((PLAN_TOTAL - ALREADY_UPLOADED) * 100) / 100; var remaining = Math.round((PLAN_TOTAL - ALREADY_UPLOADED) * 100) / 100;
var endNum = NEXT_NUM_FOR_PLAN + needed - 1; var endNum = NEXT_NUM_FOR_PLAN + needed - 1;
var lastAmt = Math.round((remaining - amt * (needed - 1)) * 100) / 100; var newTotal = Math.round(amt * needed * 100) / 100;
// total of new cheques = amt*(needed-1) + lastAmt = exactly remaining amount
var newTotal = Math.round((amt * (needed - 1) + lastAmt) * 100) / 100;
// grand total = existing + new = must equal PLAN_TOTAL
var grandTotal = Math.round((ALREADY_UPLOADED + newTotal) * 100) / 100; var grandTotal = Math.round((ALREADY_UPLOADED + newTotal) * 100) / 100;
var covered = newTotal >= remaining - 0.009;
document.getElementById('genCount').textContent = needed; document.getElementById('genCount').textContent = needed;
document.getElementById('genAmtDisplay').textContent = fmt(amt); document.getElementById('genAmtDisplay').textContent = fmt(amt);
...@@ -320,13 +318,8 @@ $coveragePct = $planTotal > 0 ? min(100, round($uploadedTotal / $planTotal * 10 ...@@ -320,13 +318,8 @@ $coveragePct = $planTotal > 0 ? min(100, round($uploadedTotal / $planTotal * 10
? 'تكملة من #' + NEXT_NUM_FOR_PLAN + ' ← #' + endNum + ' (الموجود: ' + ALREADY_COUNT + ' شيك بقيمة ' + fmt(ALREADY_UPLOADED) + ')' ? 'تكملة من #' + NEXT_NUM_FOR_PLAN + ' ← #' + endNum + ' (الموجود: ' + ALREADY_COUNT + ' شيك بقيمة ' + fmt(ALREADY_UPLOADED) + ')'
: '#' + NEXT_NUM_FOR_PLAN + ' ← #' + endNum; : '#' + NEXT_NUM_FOR_PLAN + ' ← #' + endNum;
if (lastAmt <= 0) { box.style.background = covered ? '' : '#FEF2F2';
box.style.background = '#FEF2F2'; box.style.border = covered ? '' : '1px solid #FECACA';
box.style.border = '1px solid #FECACA';
} else {
box.style.background = '';
box.style.border = '';
}
box.style.display = ''; box.style.display = '';
}; };
...@@ -343,28 +336,27 @@ $coveragePct = $planTotal > 0 ? min(100, round($uploadedTotal / $planTotal * 10 ...@@ -343,28 +336,27 @@ $coveragePct = $planTotal > 0 ? min(100, round($uploadedTotal / $planTotal * 10
var needed = REMAINING_COUNT; var needed = REMAINING_COUNT;
var remaining = Math.round((PLAN_TOTAL - ALREADY_UPLOADED) * 100) / 100; var remaining = Math.round((PLAN_TOTAL - ALREADY_UPLOADED) * 100) / 100;
var newTotal = Math.round(amt * needed * 100) / 100;
// Guard: per-cheque amount * (needed-1) must leave a positive last cheque // Guard: total of new cheques must cover the remaining amount (can exceed, never less)
var lastAmt = Math.round((remaining - amt * (needed - 1)) * 100) / 100; if (newTotal < remaining - 0.009) {
if (lastAmt <= 0) { var minAmt = Math.ceil((remaining / needed) * 100) / 100;
var maxAmt = Math.round((remaining / needed) * 100) / 100;
alert( alert(
'قيمة الشيك كبيرة جداً — الشيك الأخير سيكون صفراً أو سالباً.\n' + 'إجمالي الشيكات الجديدة (' + newTotal.toFixed(2) + ' ج.م) أقل من المبلغ المتبقي (' + remaining.toFixed(2) + ' ج.م)\n' +
'الحد الأقصى المسموح: ' + maxAmt.toFixed(2) + ' ج.م لكل شيك\n' + 'الحد الأدنى للشيك: ' + minAmt.toFixed(2) + ' ج.م\n' +
'(المبلغ المتبقي ' + remaining.toFixed(2) + ' ج.م ÷ ' + needed + ' شيكات)' 'يمكن أن يزيد الإجمالي عن المبلغ المتبقي ولكن لا يقل عنه'
); );
return; return;
} }
// All cheques have the same amount — total may exceed planTotal, that is acceptable
rows = []; rows = [];
for (var i = 0; i < needed; i++) { for (var i = 0; i < needed; i++) {
var isLast = (i === needed - 1);
rows.push({ rows.push({
cheque_number: String(NEXT_NUM_FOR_PLAN + i), cheque_number: String(NEXT_NUM_FOR_PLAN + i),
bank_name: bank, bank_name: bank,
cheque_date: addMonths(startDate, i), cheque_date: addMonths(startDate, i),
// Last cheque absorbs rounding difference to guarantee total = PLAN_TOTAL cheque_amount: amt,
cheque_amount: isLast ? lastAmt : amt,
notes: '', notes: '',
}); });
} }
......
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