feat: add Zakat calculator (per-member, Nisab + 2.5% rate)
Closes the Zakat gap identified in the competitive benchmark against Rafiq. Per-member module (nf_zakat_records, same author-owns/family-reads RLS pattern as Insurance/Wassiyah/Waqf) computing 2.5% due on zakatable wealth (cash, gold, silver, business assets, investments) once above a user-entered Nisab threshold, minus deductible short-term liabilities. Manual entry only, matching the app's existing philosophy — no live gold price feed. Covered by e2e-zakat.cjs (7/7).
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
// Shared Zakat calculation core — Nisab check + 2.5% (1/40) on qualifying
|
||||
// wealth held above threshold. Nisab is entered as a value, not a live gold
|
||||
// price feed — matches the app's "manual entry only" philosophy already
|
||||
// established for Asset Registry / Faraid.
|
||||
const ZAKAT_RATE = 0.025;
|
||||
|
||||
export function zakatableWealth(fields) {
|
||||
const gross = (Number(fields.cash) || 0) + (Number(fields.gold) || 0) + (Number(fields.silver) || 0)
|
||||
+ (Number(fields.businessAssets) || 0) + (Number(fields.investments) || 0) + (Number(fields.otherZakatable) || 0);
|
||||
const deductible = Number(fields.deductibleLiabilities) || 0;
|
||||
return Math.max(0, gross - deductible);
|
||||
}
|
||||
|
||||
export function zakatDue(fields) {
|
||||
const wealth = zakatableWealth(fields);
|
||||
const nisab = Number(fields.nisabThreshold) || 0;
|
||||
if (nisab <= 0 || wealth < nisab) return 0;
|
||||
return wealth * ZAKAT_RATE;
|
||||
}
|
||||
|
||||
export function meetsNisab(fields) {
|
||||
const nisab = Number(fields.nisabThreshold) || 0;
|
||||
return nisab > 0 && zakatableWealth(fields) >= nisab;
|
||||
}
|
||||
Reference in New Issue
Block a user