gemcap-be-common 1.2.63 → 1.2.65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/db/loan-statement.db.d.ts +13 -1
- package/db/loan-statement.db.js +24 -28
- package/db/loan-statement.db.ts +28 -34
- package/db/reports.db.d.ts +44 -4
- package/db/reports.db.js +234 -186
- package/db/reports.db.ts +279 -201
- package/enums/microservice-task.enum.d.ts +2 -1
- package/enums/microservice-task.enum.js +1 -0
- package/enums/microservice-task.enum.ts +1 -0
- package/package.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
package/db/reports.db.ts
CHANGED
|
@@ -7,7 +7,7 @@ import mongoose from 'mongoose';
|
|
|
7
7
|
import { BorrowerModel } from '../models/Borrower.model';
|
|
8
8
|
import {
|
|
9
9
|
ELoanTransactionTypes,
|
|
10
|
-
|
|
10
|
+
ILoanTransactionDoc,
|
|
11
11
|
LoanTransaction,
|
|
12
12
|
} from '../models/LoanTransaction.model';
|
|
13
13
|
import { ELoanTypes } from '../enums/loan-types.enum';
|
|
@@ -77,42 +77,87 @@ export interface ILedgerDataRow {
|
|
|
77
77
|
isBrokerFee?: boolean;
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
export
|
|
81
|
-
|
|
80
|
+
export type LedgerTransactions = {
|
|
81
|
+
transactions: ILoanTransactionDoc[];
|
|
82
|
+
product: ILoanProductDoc;
|
|
83
|
+
productId: mongoose.Types.ObjectId;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export type ReportLedgerParams = {
|
|
87
|
+
productIds: string[],
|
|
88
|
+
startDate: Date,
|
|
89
|
+
endDate: Date,
|
|
90
|
+
reportType: ELedgerReportType,
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export type ReportLedgerOptions = {
|
|
94
|
+
showFloatedBalance: boolean,
|
|
95
|
+
showBalances: boolean,
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const defaultReportLedgerOptions: ReportLedgerOptions = {
|
|
99
|
+
showBalances: true,
|
|
100
|
+
showFloatedBalance: true,
|
|
101
|
+
};
|
|
82
102
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
const fullTransactions = await getLedgerData(
|
|
103
|
+
export const getLedger = async (params: ReportLedgerParams, options = defaultReportLedgerOptions): Promise<{
|
|
104
|
+
[productId: string]: ILedgerReportRow []
|
|
105
|
+
}> => {
|
|
106
|
+
const { productIds, reportType } = params;
|
|
107
|
+
const fullTransactions = await getLedgerData(params, options);
|
|
108
|
+
const products = await LoanProduct
|
|
109
|
+
.find({ _id: { $in: productIds.map((id) => new mongoose.Types.ObjectId(id)) } })
|
|
110
|
+
.sort({ code: 1 })
|
|
111
|
+
.lean();
|
|
88
112
|
|
|
89
113
|
const header = ledgerHeadersMap[reportType];
|
|
90
|
-
const headerKeys = showFloatedBalance
|
|
114
|
+
const headerKeys = options.showFloatedBalance
|
|
91
115
|
? Object.keys(header).filter((key) => key !== 'floatedBalance')
|
|
92
116
|
: Object.keys(header);
|
|
93
117
|
|
|
94
118
|
const sumKeys = ['amount', 'statementAmount'];
|
|
95
119
|
const groupKeys = headerKeys.filter((key) => !sumKeys.includes(key));
|
|
96
|
-
const finalTransactions = reportType === ELedgerReportType.SHORT
|
|
97
|
-
? mergeLedgerData(fullTransactions, groupKeys, sumKeys)
|
|
98
|
-
: fullTransactions;
|
|
99
120
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
121
|
+
return products.reduce((acc, product) => {
|
|
122
|
+
const transactions = fullTransactions[product._id.toString()];
|
|
123
|
+
const finalTransactions = reportType === ELedgerReportType.SHORT
|
|
124
|
+
? mergeLedgerData(transactions, groupKeys, sumKeys)
|
|
125
|
+
: transactions;
|
|
126
|
+
const sheetName = `${product.code} - ${product.name}`;
|
|
127
|
+
return {
|
|
128
|
+
...acc,
|
|
129
|
+
[sheetName]: _.map(finalTransactions, (obj) => _.pick(obj, headerKeys)) as ILedgerReportRow[],
|
|
130
|
+
};
|
|
131
|
+
}, {});
|
|
103
132
|
};
|
|
104
133
|
|
|
105
|
-
const getLedgerData = async (
|
|
134
|
+
const getLedgerData = async (params: ReportLedgerParams, options = defaultReportLedgerOptions): Promise<{
|
|
135
|
+
[productId: string]: ILedgerReportRow[]
|
|
136
|
+
}> => {
|
|
137
|
+
const { productIds, startDate, endDate } = params;
|
|
138
|
+
|
|
106
139
|
const addBrokers = true;
|
|
107
|
-
const
|
|
108
|
-
const
|
|
109
|
-
const
|
|
140
|
+
const products = await LoanProduct.find({ _id: { $in: productIds.map((id) => new mongoose.Types.ObjectId(id)) } }).lean();
|
|
141
|
+
const borrowers = await BorrowerModel.find({ _id: { $in: products.map((product) => product.borrowerId) } }).lean();
|
|
142
|
+
const borrowerMap = borrowers.reduce((acc, borrower) => (
|
|
143
|
+
{ ...acc, [borrower._id.toString()]: borrower.code }
|
|
144
|
+
), {});
|
|
145
|
+
const borrowerCodesMap = products.reduce((acc, product): { [productId: string]: string } => ({
|
|
146
|
+
...acc,
|
|
147
|
+
[product._id.toString()]: borrowerMap[product.borrowerId.toString()],
|
|
148
|
+
}), {});
|
|
149
|
+
|
|
150
|
+
const groupedTransactions = await LoanTransaction.aggregate<LedgerTransactions>([
|
|
110
151
|
{
|
|
111
152
|
$match: {
|
|
112
153
|
$and: [
|
|
113
154
|
{ 'date': { $gte: startDate } },
|
|
114
155
|
{ 'date': { $lte: dayjs(endDate).endOf('day').toDate() } },
|
|
115
|
-
{
|
|
156
|
+
{
|
|
157
|
+
productId: {
|
|
158
|
+
$in: products.map((product) => product._id),
|
|
159
|
+
},
|
|
160
|
+
},
|
|
116
161
|
],
|
|
117
162
|
},
|
|
118
163
|
}, {
|
|
@@ -132,207 +177,240 @@ const getLedgerData = async (productId: string, startDate: Date, endDate: Date):
|
|
|
132
177
|
'order': 1,
|
|
133
178
|
},
|
|
134
179
|
},
|
|
135
|
-
]);
|
|
136
|
-
const convertTypes = (transactionType: ELoanTransactionTypes) => {
|
|
137
|
-
if (product.type === ELoanTypes.TERM && transactionType === ELoanTransactionTypes.COLLECTION) {
|
|
138
|
-
return 'PRINCIPAL';
|
|
139
|
-
}
|
|
140
|
-
return transactionType;
|
|
141
|
-
};
|
|
142
|
-
const mappedTransactions = transactions.map((transaction) => {
|
|
143
|
-
return <ILedgerDataRow>{
|
|
144
|
-
typeOrder: 0,
|
|
145
|
-
order: transaction.order,
|
|
146
|
-
date: transaction.date,
|
|
147
|
-
type: convertTypes(transaction.transactionType),
|
|
148
|
-
amount: transaction.amount,
|
|
149
|
-
statementAmount: null,
|
|
150
|
-
title: convertTypes(transaction.transactionType),
|
|
151
|
-
balance: transaction.balance,
|
|
152
|
-
floatedBalance: transaction.floatedBalance,
|
|
153
|
-
chargeCode: transaction.product.code,
|
|
154
|
-
PLCode: null,
|
|
155
|
-
productCode: transaction.product.code,
|
|
156
|
-
productName: transaction.product.name,
|
|
157
|
-
createdAt: transaction['createdAt'],
|
|
158
|
-
info: transaction.reference,
|
|
159
|
-
paymentDate: null,
|
|
160
|
-
};
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
const loanCharges = await getLoanChargeForProduct(productId);
|
|
164
|
-
const chargesIds = loanCharges.map((charge) => charge._id);
|
|
165
|
-
const statementTransactions = await LoanStatementTransactionModel.aggregate<ILoanStatementTransactionDocWithCharge>([
|
|
166
180
|
{
|
|
167
|
-
$
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
{ 'chargeId': { '$in': chargesIds } },
|
|
172
|
-
],
|
|
173
|
-
},
|
|
174
|
-
}, {
|
|
175
|
-
$lookup: {
|
|
176
|
-
from: 'loan_charges',
|
|
177
|
-
localField: 'chargeId',
|
|
178
|
-
foreignField: '_id',
|
|
179
|
-
as: 'charge',
|
|
180
|
-
},
|
|
181
|
-
}, {
|
|
182
|
-
$unwind: {
|
|
183
|
-
path: '$charge',
|
|
181
|
+
$group: {
|
|
182
|
+
_id: '$productId',
|
|
183
|
+
transactions: { $push: '$$ROOT' },
|
|
184
|
+
product: { $first: '$product' },
|
|
184
185
|
},
|
|
185
|
-
},
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
'
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
$project: {
|
|
189
|
+
_id: 0,
|
|
190
|
+
productId: '$_id',
|
|
191
|
+
product: 1,
|
|
192
|
+
transactions: 1,
|
|
190
193
|
},
|
|
191
194
|
},
|
|
192
195
|
]);
|
|
193
196
|
|
|
194
|
-
const
|
|
195
|
-
|
|
197
|
+
const convertTypes = (transactionType: ELoanTransactionTypes, product: ILoanProductDoc): EChargeType => {
|
|
198
|
+
if (product.type === ELoanTypes.TERM && transactionType === ELoanTransactionTypes.COLLECTION) {
|
|
199
|
+
return EChargeType.PRINCIPAL;
|
|
200
|
+
}
|
|
201
|
+
return EChargeType[transactionType];
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
const mappedGroups: {
|
|
205
|
+
[productId: string]: { transactions: ILedgerDataRow[], product: ILoanProductDoc }
|
|
206
|
+
} = groupedTransactions.reduce((acc, group) => {
|
|
196
207
|
return {
|
|
197
|
-
...
|
|
198
|
-
|
|
199
|
-
|
|
208
|
+
...acc,
|
|
209
|
+
[group.productId.toString()]: {
|
|
210
|
+
product: group.product,
|
|
211
|
+
transactions: group.transactions.map((transaction): ILedgerDataRow => {
|
|
212
|
+
return {
|
|
213
|
+
typeOrder: 0,
|
|
214
|
+
order: transaction.order,
|
|
215
|
+
date: transaction.date,
|
|
216
|
+
type: convertTypes(transaction.transactionType, group.product),
|
|
217
|
+
amount: transaction.amount,
|
|
218
|
+
statementAmount: null,
|
|
219
|
+
title: convertTypes(transaction.transactionType, group.product),
|
|
220
|
+
balance: transaction.balance,
|
|
221
|
+
floatedBalance: transaction.floatedBalance,
|
|
222
|
+
chargeCode: group.product.code,
|
|
223
|
+
PLCode: null,
|
|
224
|
+
productCode: group.product.code,
|
|
225
|
+
productName: group.product.name,
|
|
226
|
+
createdAt: transaction['createdAt'],
|
|
227
|
+
info: transaction.reference,
|
|
228
|
+
paymentDate: null,
|
|
229
|
+
};
|
|
230
|
+
}),
|
|
231
|
+
},
|
|
200
232
|
};
|
|
201
|
-
})
|
|
233
|
+
}, {});
|
|
202
234
|
|
|
203
|
-
const
|
|
204
|
-
|
|
235
|
+
const allData = {};
|
|
236
|
+
await Promise.all(Object.entries(mappedGroups).map(async ([productId, group]) => {
|
|
237
|
+
const loanCharges = await getLoanChargeForProduct(productId);
|
|
238
|
+
const chargesIds = loanCharges.map((charge) => charge._id);
|
|
239
|
+
const statementTransactions = await LoanStatementTransactionModel.aggregate<ILoanStatementTransactionDocWithCharge>([
|
|
240
|
+
{
|
|
241
|
+
$match: {
|
|
242
|
+
$and: [
|
|
243
|
+
{ 'date': { $gte: startDate } },
|
|
244
|
+
{ 'date': { $lte: dayjs(endDate).endOf('day').toDate() } },
|
|
245
|
+
{ 'chargeId': { '$in': chargesIds } },
|
|
246
|
+
],
|
|
247
|
+
},
|
|
248
|
+
}, {
|
|
249
|
+
$lookup: {
|
|
250
|
+
from: 'loan_charges',
|
|
251
|
+
localField: 'chargeId',
|
|
252
|
+
foreignField: '_id',
|
|
253
|
+
as: 'charge',
|
|
254
|
+
},
|
|
255
|
+
}, {
|
|
256
|
+
$unwind: {
|
|
257
|
+
path: '$charge',
|
|
258
|
+
},
|
|
259
|
+
}, {
|
|
260
|
+
$sort: {
|
|
261
|
+
'date': 1,
|
|
262
|
+
'createdAt': 1,
|
|
263
|
+
'order': 1,
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
]);
|
|
205
267
|
|
|
206
|
-
const
|
|
268
|
+
const statementTransactionsWithBalance = options.showBalances
|
|
269
|
+
? await Promise.all(statementTransactions.map(async (statement) => {
|
|
270
|
+
const balances = await getLoanProductBalance(productId, statement.date);
|
|
271
|
+
return {
|
|
272
|
+
...statement,
|
|
273
|
+
balance: balances.balance,
|
|
274
|
+
floatedBalance: balances.floatedBalance,
|
|
275
|
+
};
|
|
276
|
+
}))
|
|
277
|
+
: statementTransactions.slice();
|
|
207
278
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
for (const payment of payments) {
|
|
211
|
-
transactions.push({
|
|
212
|
-
typeOrder: 1,
|
|
213
|
-
order: statement.order,
|
|
214
|
-
date: statement.date,
|
|
215
|
-
type: statement.charge.chargeType,
|
|
216
|
-
amount: null,
|
|
217
|
-
statementAmount: isParticipant ? statement.amountPaid : -statement.amountPaid,
|
|
218
|
-
title: `${statement.charge.name} PAID`,
|
|
219
|
-
chargeCode: statement.charge.code,
|
|
220
|
-
PLCode: statement.charge.PLCode,
|
|
221
|
-
productCode: product.code,
|
|
222
|
-
productName: product.name,
|
|
223
|
-
balance: statement.balance,
|
|
224
|
-
floatedBalance: statement.floatedBalance,
|
|
225
|
-
createdAt: statement['createdAt'],
|
|
226
|
-
info: statement.memo,
|
|
227
|
-
paymentDate: dayjs(payment.date).format(defaultDateFormat),
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
return [...transactions, {
|
|
232
|
-
typeOrder: 1,
|
|
233
|
-
order: statement.order,
|
|
234
|
-
date: statement.date,
|
|
235
|
-
type: statement.charge.chargeType,
|
|
236
|
-
amount: null,
|
|
237
|
-
statementAmount: isParticipant ? -statement.amount : statement.amount,
|
|
238
|
-
title: `${statement.charge.name} ACCRUED`,
|
|
239
|
-
chargeCode: statement.charge.code,
|
|
240
|
-
PLCode: statement.charge.PLCode,
|
|
241
|
-
productCode: product.code,
|
|
242
|
-
productName: product.name,
|
|
243
|
-
balance: statement.balance,
|
|
244
|
-
floatedBalance: statement.floatedBalance,
|
|
245
|
-
createdAt: statement['createdAt'],
|
|
246
|
-
info: statement.memo,
|
|
247
|
-
paymentDate: null,
|
|
248
|
-
}];
|
|
249
|
-
}));
|
|
250
|
-
const mappedStatementTransactions: ILedgerDataRow[] = groupedMappedStatementTransactions
|
|
251
|
-
.reduce((acc, group) => [...acc, ...group], []);
|
|
252
|
-
const statementTransactionsWithBrokers = addBrokers
|
|
253
|
-
? await enrichWithBrokers(mappedStatementTransactions, product)
|
|
254
|
-
: mappedStatementTransactions;
|
|
255
|
-
const sortedTransactions = [...statementTransactionsWithBrokers, ...mappedTransactions]
|
|
256
|
-
.sort((a, b) => {
|
|
257
|
-
if (a.date.valueOf() !== b.date.valueOf()) {
|
|
258
|
-
return b.date.valueOf() - a.date.valueOf();
|
|
259
|
-
}
|
|
260
|
-
if (a.typeOrder !== b.typeOrder) {
|
|
261
|
-
return b.typeOrder - a.typeOrder;
|
|
262
|
-
}
|
|
263
|
-
return b.createdAt.valueOf() - a.createdAt.valueOf();
|
|
264
|
-
});
|
|
279
|
+
const isParticipant = group.product.isParticipant;
|
|
280
|
+
const groupedMappedStatementTransactions = await Promise.all(statementTransactionsWithBalance.map(async (statement) => {
|
|
265
281
|
|
|
266
|
-
|
|
267
|
-
.map((row): ILedgerReportRow => ({
|
|
268
|
-
borrowerCode: borrower.code,
|
|
269
|
-
date: formatDate(row.date),
|
|
270
|
-
type: !!row.isBrokerFee ? `${EChargeType[row.type]} BROKER` : EChargeType[row.type],
|
|
271
|
-
chargeCode: row.chargeCode,
|
|
272
|
-
PLCode: row.PLCode,
|
|
273
|
-
productCode: row.productCode,
|
|
274
|
-
productName: row.productName,
|
|
275
|
-
amount: row.amount,
|
|
276
|
-
statementAmount: row.statementAmount,
|
|
277
|
-
title: row.title,
|
|
278
|
-
balance: row.balance,
|
|
279
|
-
floatedBalance: row.floatedBalance,
|
|
280
|
-
info: row.info,
|
|
281
|
-
paymentDate: row.paymentDate ? formatDate(row.paymentDate) : '',
|
|
282
|
-
}));
|
|
282
|
+
const transactions = [];
|
|
283
283
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
284
|
+
if (statement.amountPaid > 0) {
|
|
285
|
+
const payments = await getPaymentForTransaction(productId, statement._id.toString());
|
|
286
|
+
for (const payment of payments) {
|
|
287
|
+
transactions.push({
|
|
288
|
+
typeOrder: 1,
|
|
289
|
+
order: statement.order,
|
|
290
|
+
date: statement.date,
|
|
291
|
+
type: statement.charge.chargeType,
|
|
292
|
+
amount: null,
|
|
293
|
+
statementAmount: isParticipant ? statement.amountPaid : -statement.amountPaid,
|
|
294
|
+
title: `${statement.charge.name} PAID`,
|
|
295
|
+
chargeCode: statement.charge.code,
|
|
296
|
+
PLCode: statement.charge.PLCode,
|
|
297
|
+
productCode: group.product.code,
|
|
298
|
+
productName: group.product.name,
|
|
299
|
+
balance: statement.balance,
|
|
300
|
+
floatedBalance: statement.floatedBalance,
|
|
301
|
+
createdAt: statement['createdAt'],
|
|
302
|
+
info: statement.memo,
|
|
303
|
+
paymentDate: dayjs(payment.date).format(defaultDateFormat),
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
return [...transactions, {
|
|
308
|
+
typeOrder: 1,
|
|
309
|
+
order: statement.order,
|
|
310
|
+
date: statement.date,
|
|
311
|
+
type: statement.charge.chargeType,
|
|
312
|
+
amount: null,
|
|
313
|
+
statementAmount: isParticipant ? -statement.amount : statement.amount,
|
|
314
|
+
title: `${statement.charge.name} ACCRUED`,
|
|
315
|
+
chargeCode: statement.charge.code,
|
|
316
|
+
PLCode: statement.charge.PLCode,
|
|
317
|
+
productCode: group.product.code,
|
|
318
|
+
productName: group.product.name,
|
|
319
|
+
balance: statement.balance,
|
|
320
|
+
floatedBalance: statement.floatedBalance,
|
|
321
|
+
createdAt: statement['createdAt'],
|
|
322
|
+
info: statement.memo,
|
|
304
323
|
paymentDate: null,
|
|
305
|
-
};
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
324
|
+
}];
|
|
325
|
+
}));
|
|
326
|
+
const mappedStatementTransactions: ILedgerDataRow[] = groupedMappedStatementTransactions
|
|
327
|
+
.reduce((acc, group) => [...acc, ...group], []);
|
|
328
|
+
const statementTransactionsWithBrokers = addBrokers
|
|
329
|
+
? await enrichWithBrokers(mappedStatementTransactions, group.product)
|
|
330
|
+
: mappedStatementTransactions;
|
|
331
|
+
const sortedTransactions = [...statementTransactionsWithBrokers, ...group.transactions]
|
|
332
|
+
.sort((a, b) => {
|
|
333
|
+
if (a.date.valueOf() !== b.date.valueOf()) {
|
|
334
|
+
return b.date.valueOf() - a.date.valueOf();
|
|
335
|
+
}
|
|
336
|
+
if (a.typeOrder !== b.typeOrder) {
|
|
337
|
+
return b.typeOrder - a.typeOrder;
|
|
338
|
+
}
|
|
339
|
+
return b.createdAt.valueOf() - a.createdAt.valueOf();
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
const fullTransactions = sortedTransactions
|
|
343
|
+
.map((row): ILedgerReportRow => ({
|
|
344
|
+
borrowerCode: borrowerCodesMap[productId],
|
|
345
|
+
date: formatDate(row.date),
|
|
346
|
+
type: row.isBrokerFee ? `${EChargeType[row.type]} BROKER` : EChargeType[row.type],
|
|
347
|
+
chargeCode: row.chargeCode,
|
|
348
|
+
PLCode: row.PLCode,
|
|
349
|
+
productCode: row.productCode,
|
|
350
|
+
productName: row.productName,
|
|
351
|
+
amount: row.amount,
|
|
352
|
+
statementAmount: row.statementAmount,
|
|
353
|
+
title: row.title,
|
|
354
|
+
balance: row.balance,
|
|
355
|
+
floatedBalance: row.floatedBalance,
|
|
356
|
+
info: row.info,
|
|
357
|
+
paymentDate: row.paymentDate ? formatDate(row.paymentDate) : '',
|
|
358
|
+
}));
|
|
359
|
+
|
|
360
|
+
const termLoan = await TermLoanModel.findOne({ productId, actual: true });
|
|
361
|
+
if (termLoan) {
|
|
362
|
+
const calculatedTermLoan = await TermLoanCalculatedModel.findOne({
|
|
363
|
+
termLoanId: termLoan._id.toString(),
|
|
364
|
+
relevantStatement: dayjs(endDate).format('YYYY-MM-DD'),
|
|
365
|
+
});
|
|
366
|
+
if (calculatedTermLoan) {
|
|
367
|
+
const expectedPayment = <ILedgerReportRow>{
|
|
368
|
+
borrowerCode: borrowerCodesMap[productId],
|
|
369
|
+
date: formatDate(endDate),
|
|
370
|
+
type: EChargeType.EXPECTED_PRINCIPAL,
|
|
371
|
+
chargeCode: null,
|
|
372
|
+
PLCode: null,
|
|
373
|
+
productCode: group.product.code,
|
|
374
|
+
amount: isParticipant ? -calculatedTermLoan.monthlyPrincipal : calculatedTermLoan.monthlyPrincipal,
|
|
375
|
+
statementAmount: null,
|
|
376
|
+
title: EChargeType.EXPECTED_PRINCIPAL,
|
|
377
|
+
balance: null,
|
|
378
|
+
floatedBalance: null,
|
|
379
|
+
info: EChargeType.EXPECTED_PRINCIPAL,
|
|
380
|
+
paymentDate: null,
|
|
381
|
+
};
|
|
382
|
+
fullTransactions.unshift(expectedPayment);
|
|
383
|
+
if (calculatedTermLoan.payments && calculatedTermLoan.payments.length > 0) {
|
|
384
|
+
for (const payment of calculatedTermLoan.payments) {
|
|
385
|
+
const paymentDoc = await LoanTransaction.findById(payment.paymentId).lean();
|
|
386
|
+
if (paymentDoc) {
|
|
387
|
+
const expectedPayment = <ILedgerReportRow>{
|
|
388
|
+
borrowerCode: borrowerCodesMap[productId],
|
|
389
|
+
date: formatDate(endDate),
|
|
390
|
+
type: EChargeType.EXPECTED_PRINCIPAL_PAID,
|
|
391
|
+
chargeCode: null,
|
|
392
|
+
PLCode: null,
|
|
393
|
+
productCode: group.product.code,
|
|
394
|
+
amount: isParticipant ? -payment.amount : payment.amount,
|
|
395
|
+
statementAmount: null,
|
|
396
|
+
title: EChargeType.EXPECTED_PRINCIPAL_PAID,
|
|
397
|
+
balance: null,
|
|
398
|
+
floatedBalance: null,
|
|
399
|
+
info: EChargeType.EXPECTED_PRINCIPAL_PAID,
|
|
400
|
+
paymentDate: formatDate(paymentDoc.date),
|
|
401
|
+
};
|
|
402
|
+
fullTransactions.unshift(expectedPayment);
|
|
403
|
+
}
|
|
327
404
|
}
|
|
328
405
|
}
|
|
329
406
|
}
|
|
330
407
|
}
|
|
331
|
-
|
|
332
|
-
|
|
408
|
+
allData[productId] = fullTransactions;
|
|
409
|
+
}));
|
|
410
|
+
return allData;
|
|
333
411
|
};
|
|
334
412
|
|
|
335
|
-
const mergeLedgerData = (transactions: ILedgerReportRow[], groupKeys: string[], sumKeys: string[]) => {
|
|
413
|
+
const mergeLedgerData = (transactions: ILedgerReportRow[], groupKeys: string[], sumKeys: string[]): ILedgerReportRow[] => {
|
|
336
414
|
const groupedObjects = _.groupBy(
|
|
337
415
|
transactions,
|
|
338
416
|
(obj) => groupKeys.reduce((acc, key) => `${acc}${obj[key]}`, ''),
|
|
@@ -8,4 +8,5 @@ var EMicroserviceTask;
|
|
|
8
8
|
EMicroserviceTask["QUERY"] = "query";
|
|
9
9
|
EMicroserviceTask["YIELD"] = "yield";
|
|
10
10
|
EMicroserviceTask["REPORT"] = "report";
|
|
11
|
+
EMicroserviceTask["POST_UPLOAD"] = "post_upload";
|
|
11
12
|
})(EMicroserviceTask || (exports.EMicroserviceTask = EMicroserviceTask = {}));
|