From 98d7571184abc051dff89757caeb6c06ef45ec0e Mon Sep 17 00:00:00 2001 From: kndone Date: Sun, 26 Nov 2023 16:57:05 +0800 Subject: [PATCH] feat: automatic deposit interest calculation --- src/models/depositTransactionSchema.js | 3 +- src/schedules/agenda.js | 4 +- src/schedules/jobs/deposit-interests.js | 77 ++++++++++++++++++++++++- src/schedules/jobs/loan-interests.js | 4 +- 4 files changed, 79 insertions(+), 9 deletions(-) diff --git a/src/models/depositTransactionSchema.js b/src/models/depositTransactionSchema.js index 6db8da5..bf18368 100644 --- a/src/models/depositTransactionSchema.js +++ b/src/models/depositTransactionSchema.js @@ -11,8 +11,7 @@ const DepositTransactionSchema = new Schema({ immutable: true }, ORNumber: { - type: String, - required: true + type: String }, transactionDate: { type: Date, diff --git a/src/schedules/agenda.js b/src/schedules/agenda.js index 8aa4ea9..448bac6 100644 --- a/src/schedules/agenda.js +++ b/src/schedules/agenda.js @@ -7,8 +7,8 @@ import { DEFAULT_MONGODB_URI } from '../db/default_uri.js' // Configure Agenda const agenda = new Agenda({ ensureIndex: true, - // processEvery: '10 minutes', - processEvery: '5 seconds', + processEvery: '10 minutes', + // processEvery: '5 seconds', db: { address: process.env.MONGODB_URI || DEFAULT_MONGODB_URI } // TODO: Use existing mongoose connection }) diff --git a/src/schedules/jobs/deposit-interests.js b/src/schedules/jobs/deposit-interests.js index 6942c03..b813373 100644 --- a/src/schedules/jobs/deposit-interests.js +++ b/src/schedules/jobs/deposit-interests.js @@ -10,7 +10,78 @@ const name = 'process-deposit-interests' const handler = async (job, done) => { console.log('Updating deposit interests...') - const deposits = await Deposit.find({}) + const deposits = await Deposit.find({ + nextInterestDate: { + $lte: Date.now() + } + }).lean() + parseDecimal(deposits) + + const allSettings = await DepositSettings.findOne().lean() + parseDecimal(allSettings) + + for (const deposit of deposits) { + const depositSettings = allSettings[deposit.category] + let interest = Decimal('0') + + if (depositSettings.interest_rate.unit === 'Fixed') { + interest = interest.add(depositSettings.interest_rate.value) + } else { + interest = interest.add( + Decimal(depositSettings.interest_rate.value).mul('0.01').mul(deposit.runningAmount) + ) + } + + const newBalance = round2(interest.add(deposit.runningAmount)) + interest = round2(interest) + const submissionDate = Date.now() + + const transaction = { + transactionID: Date.now().toString(36).toUpperCase(), + transactionDate: Date.now(), + submissionDate: submissionDate, + transactionType: 'Deposit', + amount: 0, + interest: parseFloat(interest), + balance: parseFloat(newBalance), + officerInCharge: { + given: 'Admin', + middle: '', + last: ' ' + } + } + + const timeSetting = depositSettings.time + + const timeConversions = { + days: 1, + months: 30, + years: 365 + } + const nextInterestDate = moment(deposit.nextInterestDate) + .add(timeSetting.value * timeConversions[timeSetting.type], 'days') + .set({ + hour: 0, + minute: 0, + second: 0, + millisecond: 0 + }) + .toDate() + + const query = { + $push: { ledger: transaction }, + $set: { + runningAmount: parseFloat(newBalance), + nextInterestDate: nextInterestDate + } + } + + const ret = await Deposit.updateOne({ depositID: deposit.depositID }, query, { + runValidators: true + }) + } + + console.log(`Successfully updated ${deposits.length} deposit interests.`) done() } @@ -30,6 +101,6 @@ const round2 = function (decimal) { return decimal.mul('100').round().mul('0.01') } -// const every = '0 1 * * *' // Every 1:00 AM (to avoid desync problems with date checks) -const every = '5 seconds' +const every = '0 1 * * *' // Every 1:00 AM (to avoid desync problems with date checks) +// const every = '5 seconds' export default { name, handler, every } diff --git a/src/schedules/jobs/loan-interests.js b/src/schedules/jobs/loan-interests.js index 2b2ce95..42d4acf 100644 --- a/src/schedules/jobs/loan-interests.js +++ b/src/schedules/jobs/loan-interests.js @@ -8,6 +8,8 @@ moment().format() const name = 'process-loan-interests' const handler = async (job, done) => { + console.log('Updating loan interests...') + const loans = await Loan.find({ nextInterestDate: { $lte: Date.now() @@ -18,8 +20,6 @@ const handler = async (job, done) => { const allSettings = await LoanSettings.findOne().lean() parseDecimal(allSettings) - console.log('Updating loan interests...') - for (const loan of loans) { const loanSettings = allSettings[loan.loanType] let interest = Decimal('0')