Add admin transaction cancellation without deleting history.

Cancelled transactions are excluded from paid totals and due-date
calculations while remaining visible for audit purposes.
This commit is contained in:
2026-08-16 22:38:00 +03:30
parent a436cfeb47
commit 5328f36f06
6 changed files with 53 additions and 2 deletions
+7
View File
@@ -24,13 +24,18 @@ const sanitizeNotes = (notes) => {
const rialsToToman = (value) => Math.floor(toNonNegativeNumber(value) / 10);
const isCancelledTransaction = (trx = {}) => String(trx.status || '').toLowerCase() === 'cancelled';
const isPaidTransaction = (trx = {}) => {
if (isCancelledTransaction(trx)) return false;
const status = String(trx.status || '').toLowerCase();
if (status === 'pending') return false;
if (status === 'paid') return true;
return Boolean(trx.date);
};
const isActiveTransaction = (trx = {}) => !isCancelledTransaction(trx);
const sumPaidTransactions = (transactions = []) => {
if (!Array.isArray(transactions)) return 0;
return transactions.reduce((sum, trx) => {
@@ -50,6 +55,8 @@ module.exports = {
sanitizeNotes,
rialsToToman,
isPaidTransaction,
isCancelledTransaction,
isActiveTransaction,
sumPaidTransactions,
remainingPayable
};
+10
View File
@@ -73,6 +73,16 @@ describe('paid vs pending transactions', () => {
assert.equal(isPaidTransaction({ status: 'pending', amount: 2_000_000 }), false);
assert.equal(isPaidTransaction({ status: 'paid', amount: 8_000_000 }), true);
});
it('ignores cancelled transactions in paid totals', () => {
const transactions = [
{ amount: 5_000_000, status: 'paid', date: '2026-08-03' },
{ amount: 5_000_000, status: 'cancelled' },
{ amount: 2_000_000, status: 'pending', dueDate: '2026-08-23' }
];
assert.equal(sumPaidTransactions(transactions), 5_000_000);
assert.equal(isPaidTransaction({ status: 'cancelled', amount: 5_000_000, date: '2026-08-03' }), false);
});
});
describe('sanitizeNotes', () => {