Move embedded payment rows into Transaction documents with due dates so remaining tuition can be tracked separately from paid amounts.
56 lines
1.4 KiB
JavaScript
56 lines
1.4 KiB
JavaScript
'use strict';
|
|
|
|
const NOTES_MAX_LENGTH = 5000;
|
|
|
|
const toNonNegativeNumber = (value) => {
|
|
const n = Number(value);
|
|
if (!Number.isFinite(n) || n < 0) return 0;
|
|
return n;
|
|
};
|
|
|
|
const normalizeDiscount = (discount, amount) => {
|
|
return Math.min(toNonNegativeNumber(discount), toNonNegativeNumber(amount));
|
|
};
|
|
|
|
const getPayableAmount = (payment = {}) => {
|
|
const amount = toNonNegativeNumber(payment.amount);
|
|
return amount - normalizeDiscount(payment.discount, amount);
|
|
};
|
|
|
|
const sanitizeNotes = (notes) => {
|
|
if (notes == null) return '';
|
|
return String(notes).trim().slice(0, NOTES_MAX_LENGTH);
|
|
};
|
|
|
|
const rialsToToman = (value) => Math.floor(toNonNegativeNumber(value) / 10);
|
|
|
|
const isPaidTransaction = (trx = {}) => {
|
|
const status = String(trx.status || '').toLowerCase();
|
|
if (status === 'pending') return false;
|
|
if (status === 'paid') return true;
|
|
return Boolean(trx.date);
|
|
};
|
|
|
|
const sumPaidTransactions = (transactions = []) => {
|
|
if (!Array.isArray(transactions)) return 0;
|
|
return transactions.reduce((sum, trx) => {
|
|
if (!isPaidTransaction(trx)) return sum;
|
|
return sum + toNonNegativeNumber(trx.amount);
|
|
}, 0);
|
|
};
|
|
|
|
const remainingPayable = (payment = {}, transactions = []) => {
|
|
return Math.max(0, getPayableAmount(payment) - sumPaidTransactions(transactions));
|
|
};
|
|
|
|
module.exports = {
|
|
NOTES_MAX_LENGTH,
|
|
getPayableAmount,
|
|
normalizeDiscount,
|
|
sanitizeNotes,
|
|
rialsToToman,
|
|
isPaidTransaction,
|
|
sumPaidTransactions,
|
|
remainingPayable
|
|
};
|