gemcap-be-common 1.5.133 → 1.5.135

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.
@@ -27,8 +27,10 @@ import mongoose from 'mongoose';
27
27
  import { ILedgerDataRow } from './reports.db';
28
28
  import { ILoanProductDoc } from '../models/LoanProducts.model';
29
29
  import { IProductBrokerDocWithLoanBroker, IProductBrokerLean } from '../models/ProductBroker.model';
30
+ import { ILoanChargeDoc, ILoanChargeView } from '../models/LoanCharges.model';
31
+ export declare const handleBrokerInterestFee: (statementAmount: number, charges: ILoanChargeView[], interestShare: number, baseInterestTotal: number, primeRate: number) => number;
30
32
  export declare const getProductBrokers: (productId: string) => Promise<IProductBrokerDocWithLoanBroker[]>;
31
- export declare const enrichWithBrokers: (transactions: ILedgerDataRow[], product: ILoanProductDoc) => Promise<ILedgerDataRow[]>;
33
+ export declare const enrichWithBrokers: (transactions: ILedgerDataRow[], product: ILoanProductDoc, charges: ILoanChargeDoc[], primeRate: number) => Promise<ILedgerDataRow[]>;
32
34
  export declare const getBorrowerBrokers: (borrowerId: string) => Promise<IProductBrokerLean[]>;
33
35
  export declare const getAllProductBrokers: () => Promise<IProductBrokerLean[]>;
34
36
  export declare const getAllLoanBrokers: () => Promise<{
package/db/brokers.db.js CHANGED
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getBrokerProducts = exports.getAllLoanBrokers = exports.getAllProductBrokers = exports.getBorrowerBrokers = exports.enrichWithBrokers = exports.getProductBrokers = void 0;
6
+ exports.getBrokerProducts = exports.getAllLoanBrokers = exports.getAllProductBrokers = exports.getBorrowerBrokers = exports.enrichWithBrokers = exports.getProductBrokers = exports.handleBrokerInterestFee = void 0;
7
7
  const decimal_js_1 = __importDefault(require("decimal.js"));
8
8
  const mongoose_1 = __importDefault(require("mongoose"));
9
9
  const _models_1 = require("../models/_models");
@@ -11,6 +11,15 @@ const reports_db_1 = require("./reports.db");
11
11
  const ProductBroker_model_1 = require("../models/ProductBroker.model");
12
12
  const LoanBroker_model_1 = require("../models/LoanBroker.model");
13
13
  const main_helper_1 = require("../helpers/main.helper");
14
+ const handleBrokerInterestFee = (statementAmount, charges, interestShare, baseInterestTotal, primeRate) => {
15
+ const interestCharge = charges.find((charge) => reports_db_1.EChargeType[charge.chargeType] === reports_db_1.EChargeType.INTEREST_FEE && charge.active && !charge.deletedAt);
16
+ const interestBase = baseInterestTotal
17
+ ? new decimal_js_1.default(primeRate).add(interestCharge?.percent || 0).div(baseInterestTotal).toDP(2).toNumber()
18
+ : 0;
19
+ const minBase = Math.min(1, interestBase);
20
+ return new decimal_js_1.default(statementAmount).mul(interestShare).mul(minBase).toDP(2).toNumber();
21
+ };
22
+ exports.handleBrokerInterestFee = handleBrokerInterestFee;
14
23
  const getProductBrokers = async (productId) => {
15
24
  return ProductBroker_model_1.ProductBroker.aggregate([
16
25
  {
@@ -37,15 +46,22 @@ const getProductBrokers = async (productId) => {
37
46
  ]);
38
47
  };
39
48
  exports.getProductBrokers = getProductBrokers;
40
- const enrichWithBrokers = async (transactions, product) => {
49
+ const enrichWithBrokers = async (transactions, product, charges, primeRate) => {
41
50
  const productBrokers = await (0, exports.getProductBrokers)(product._id.toString());
42
51
  if (productBrokers.length === 0) {
43
52
  return transactions;
44
53
  }
45
54
  const handleFee = (t, broker, shareName) => {
55
+ let statementAmount;
56
+ if (shareName === 'interestShare') {
57
+ statementAmount = (0, exports.handleBrokerInterestFee)(-t.statementAmount, charges, broker.interestShare, broker.baseInterestTotal, primeRate);
58
+ }
59
+ else {
60
+ statementAmount = new decimal_js_1.default(-t.statementAmount).mul(broker[shareName]).toDP(2).toNumber();
61
+ }
46
62
  return {
47
63
  ...t,
48
- statementAmount: new decimal_js_1.default(-t.statementAmount).mul(broker[shareName]).toDP(2).toNumber(),
64
+ statementAmount,
49
65
  title: `${t.title.replace('ACCRUED', '').trim()}: ${broker.loanBroker.name}`,
50
66
  chargeCode: broker.BSCode,
51
67
  PLCode: broker.PLCode,
package/db/brokers.db.ts CHANGED
@@ -7,6 +7,16 @@ import { ILoanProductDoc } from '../models/LoanProducts.model';
7
7
  import { IProductBrokerDocWithLoanBroker, IProductBrokerLean, ProductBroker } from '../models/ProductBroker.model';
8
8
  import { ILoanBrokerLean, LoanBroker } from '../models/LoanBroker.model';
9
9
  import { fieldsToUnset, sanitizePlainObject } from '../helpers/main.helper';
10
+ import { ILoanChargeDoc, ILoanChargeView } from '../models/LoanCharges.model';
11
+
12
+ export const handleBrokerInterestFee = (statementAmount: number, charges: ILoanChargeView[], interestShare: number, baseInterestTotal: number, primeRate: number) => {
13
+ const interestCharge = charges.find((charge) => EChargeType[charge.chargeType] === EChargeType.INTEREST_FEE && charge.active && !charge.deletedAt);
14
+ const interestBase = baseInterestTotal
15
+ ? new Decimal(primeRate).add(interestCharge?.percent || 0).div(baseInterestTotal).toDP(2).toNumber()
16
+ : 0;
17
+ const minBase = Math.min(1, interestBase);
18
+ return new Decimal(statementAmount).mul(interestShare).mul(minBase).toDP(2).toNumber();
19
+ };
10
20
 
11
21
  export const getProductBrokers = async (productId: string) => {
12
22
  return ProductBroker.aggregate<IProductBrokerDocWithLoanBroker>([
@@ -34,15 +44,23 @@ export const getProductBrokers = async (productId: string) => {
34
44
  ]);
35
45
  };
36
46
 
37
- export const enrichWithBrokers = async (transactions: ILedgerDataRow[], product: ILoanProductDoc): Promise<ILedgerDataRow[]> => {
47
+ export const enrichWithBrokers = async (transactions: ILedgerDataRow[], product: ILoanProductDoc, charges: ILoanChargeDoc[], primeRate: number): Promise<ILedgerDataRow[]> => {
38
48
  const productBrokers = await getProductBrokers(product._id.toString());
39
49
  if (productBrokers.length === 0) {
40
50
  return transactions;
41
51
  }
42
52
  const handleFee = (t: ILedgerDataRow, broker: IProductBrokerDocWithLoanBroker, shareName: 'adminShare' | 'interestShare' | 'otherShare'): ILedgerDataRow => {
53
+ let statementAmount: number;
54
+
55
+
56
+ if (shareName === 'interestShare') {
57
+ statementAmount = handleBrokerInterestFee(-t.statementAmount, charges, broker.interestShare, broker.baseInterestTotal, primeRate);
58
+ } else {
59
+ statementAmount = new Decimal(-t.statementAmount).mul(broker[shareName]).toDP(2).toNumber();
60
+ }
43
61
  return {
44
62
  ...t,
45
- statementAmount: new Decimal(-t.statementAmount).mul(broker[shareName]).toDP(2).toNumber(),
63
+ statementAmount,
46
64
  title: `${t.title.replace('ACCRUED', '').trim()}: ${broker.loanBroker.name}`,
47
65
  chargeCode: broker.BSCode,
48
66
  PLCode: broker.PLCode,
@@ -7,6 +7,7 @@ exports.getPeriods = exports.getBorrowerWithPeriods = exports.getStatementBorrow
7
7
  const lodash_1 = __importDefault(require("lodash"));
8
8
  const mongoose_1 = __importDefault(require("mongoose"));
9
9
  const dayjs_1 = __importDefault(require("dayjs"));
10
+ const decimal_js_1 = __importDefault(require("decimal.js"));
10
11
  const LoanStatementTransaction_model_1 = require("../models/LoanStatementTransaction.model");
11
12
  const LoanTransaction_model_1 = require("../models/LoanTransaction.model");
12
13
  const loan_products_db_1 = require("./loan-products.db");
@@ -14,7 +15,7 @@ const LoanProducts_model_1 = require("../models/LoanProducts.model");
14
15
  const Borrower_model_1 = require("../models/Borrower.model");
15
16
  const loan_transactions_db_1 = require("./loan-transactions.db");
16
17
  const reports_db_1 = require("./reports.db");
17
- const decimal_js_1 = __importDefault(require("decimal.js"));
18
+ const financial_indexes_service_1 = require("../services/financial-indexes.service");
18
19
  var ELedgerReportType;
19
20
  (function (ELedgerReportType) {
20
21
  ELedgerReportType[ELedgerReportType["SHORT"] = 0] = "SHORT";
@@ -50,6 +51,7 @@ exports.ledgerHeadersMap = {
50
51
  paymentDate: 'payment date',
51
52
  },
52
53
  };
54
+ const financialIndexesService = new financial_indexes_service_1.FinancialIndexesService({ apiKey: '' });
53
55
  const getTotalTransactionAmountForCharge = async (chargeId, start, end) => {
54
56
  const results = await LoanStatementTransaction_model_1.LoanStatementTransactionModel.aggregate([
55
57
  {
@@ -132,7 +134,12 @@ const getStatementBorrowersTransactions = async (start, end, selectedPeriod, sel
132
134
  startDate: new Date((0, dayjs_1.default)(periodFull[0].period.start).utc().toDate().toISOString()),
133
135
  endDate: new Date((0, dayjs_1.default)(periodFull[0].period.end).utc().toDate().toISOString()),
134
136
  reportType: ledgerType,
135
- }, { showBalances: showBalances, showFloatedBalance: showBalances });
137
+ }, {
138
+ showBalances: showBalances,
139
+ showFloatedBalance: showBalances,
140
+ }, {
141
+ getFinancialIndexValue: (index, date) => financialIndexesService.getFinancialIndexValue(index, date),
142
+ });
136
143
  const transactions = Object.values(ledgerData).reduce((acc, ledgerTransaction) => [...acc, ...ledgerTransaction], []);
137
144
  const transactionsWithoutBalance = showBalances
138
145
  ? transactions.map((tr) => {
@@ -1,6 +1,7 @@
1
1
  import _ from 'lodash';
2
2
  import mongoose from 'mongoose';
3
3
  import dayjs from 'dayjs';
4
+ import Decimal from 'decimal.js';
4
5
 
5
6
  import { IStatementPeriod, LoanStatementTransactionModel } from '../models/LoanStatementTransaction.model';
6
7
  import { LoanTransaction } from '../models/LoanTransaction.model';
@@ -9,7 +10,7 @@ import { LoanProduct } from '../models/LoanProducts.model';
9
10
  import { BorrowerModel } from '../models/Borrower.model';
10
11
  import { getLastTransactionForDate } from './loan-transactions.db';
11
12
  import { getLedger } from './reports.db';
12
- import Decimal from 'decimal.js';
13
+ import { FinancialIndexesService } from '../services/financial-indexes.service';
13
14
 
14
15
  export enum ELedgerReportType {
15
16
  SHORT,
@@ -47,6 +48,8 @@ export const ledgerHeadersMap = {
47
48
  },
48
49
  };
49
50
 
51
+ const financialIndexesService = new FinancialIndexesService({ apiKey: '' });
52
+
50
53
  export const getTotalTransactionAmountForCharge = async (chargeId: string, start: Date, end: Date) => {
51
54
  const results = await LoanStatementTransactionModel.aggregate([
52
55
  {
@@ -129,12 +132,20 @@ export const getStatementBorrowersTransactions = async (start: string, end: stri
129
132
 
130
133
  const products = await LoanProduct.find({ borrowerId: { $in: selectedBorrowerIds.map((id) => new mongoose.Types.ObjectId(id)) } }).lean();
131
134
  const productIds = products.map((product) => product._id.toString());
132
- const ledgerData = await getLedger({
135
+ const ledgerData = await getLedger(
136
+ {
133
137
  productIds,
134
138
  startDate: new Date(dayjs(periodFull[0].period.start).utc().toDate().toISOString()),
135
139
  endDate: new Date(dayjs(periodFull[0].period.end).utc().toDate().toISOString()),
136
140
  reportType: ledgerType,
137
- }, { showBalances: showBalances, showFloatedBalance: showBalances },
141
+ },
142
+ {
143
+ showBalances: showBalances,
144
+ showFloatedBalance: showBalances,
145
+ },
146
+ {
147
+ getFinancialIndexValue: (index, date) => financialIndexesService.getFinancialIndexValue(index, date),
148
+ },
138
149
  );
139
150
  const transactions = Object.values(ledgerData).reduce((acc, ledgerTransaction) => [...acc, ...ledgerTransaction], []);
140
151
  const transactionsWithoutBalance = showBalances
@@ -143,7 +154,7 @@ export const getStatementBorrowersTransactions = async (start: string, end: stri
143
154
  ...tr,
144
155
  balance: tr.balance ? new Decimal(tr.balance).toDP(2).toNumber() : tr.balance,
145
156
  floatedBalance: tr.floatedBalance ? new Decimal(tr.floatedBalance).toDP(2).toNumber() : tr.floatedBalance,
146
- }
157
+ };
147
158
  })
148
159
  : _.map(transactions, (obj) => _.omit(obj, ['balance', 'floatedBalance']));
149
160
  return [{ transactions: [header, ...transactionsWithoutBalance] }];
@@ -27,6 +27,7 @@ import { ILoanProductDoc } from '../models/LoanProducts.model';
27
27
  import { ELedgerReportType } from './loan-statement.db';
28
28
  import mongoose from 'mongoose';
29
29
  import { ILoanTransactionDoc } from '../models/LoanTransaction.model';
30
+ import { EFinancialIndex } from '../services/financial-indexes.service';
30
31
  export declare enum EChargeType {
31
32
  INTEREST_FEE = "INTEREST",
32
33
  ADMIN_FEE = "ADMIN FEE",
@@ -92,6 +93,10 @@ export type ReportLedgerOptions = {
92
93
  showFloatedBalance: boolean;
93
94
  showBalances: boolean;
94
95
  };
95
- export declare const getLedger: (params: ReportLedgerParams, options?: ReportLedgerOptions) => Promise<{
96
+ type GetFinancialIndexValue = (index: EFinancialIndex, date?: Date) => Promise<number>;
97
+ export declare const getLedger: (params: ReportLedgerParams, options: ReportLedgerOptions, deps: {
98
+ getFinancialIndexValue: GetFinancialIndexValue;
99
+ }) => Promise<{
96
100
  [productId: string]: ILedgerReportRow[];
97
101
  }>;
102
+ export {};
package/db/reports.db.js CHANGED
@@ -22,6 +22,8 @@ const brokers_db_1 = require("./brokers.db");
22
22
  const TermLoan_model_1 = require("../models/TermLoan.model");
23
23
  const TermLoanCalculated_model_1 = require("../models/TermLoanCalculated.model");
24
24
  const _models_1 = require("../models/_models");
25
+ const LoanCharges_model_1 = require("../models/LoanCharges.model");
26
+ const financial_indexes_service_1 = require("../services/financial-indexes.service");
25
27
  var EChargeType;
26
28
  (function (EChargeType) {
27
29
  EChargeType["INTEREST_FEE"] = "INTEREST";
@@ -42,9 +44,9 @@ const defaultReportLedgerOptions = {
42
44
  showBalances: true,
43
45
  showFloatedBalance: true,
44
46
  };
45
- const getLedger = async (params, options = defaultReportLedgerOptions) => {
47
+ const getLedger = async (params, options = defaultReportLedgerOptions, deps) => {
46
48
  const { productIds, reportType } = params;
47
- const fullTransactions = await getLedgerData(params, options);
49
+ const fullTransactions = await getLedgerData(params, options, deps.getFinancialIndexValue);
48
50
  const products = await LoanProducts_model_1.LoanProduct
49
51
  .find({ _id: { $in: productIds.map((id) => new mongoose_1.default.Types.ObjectId(id)) } })
50
52
  .sort({ code: 1 })
@@ -66,10 +68,13 @@ const getLedger = async (params, options = defaultReportLedgerOptions) => {
66
68
  }, {});
67
69
  };
68
70
  exports.getLedger = getLedger;
69
- const getLedgerData = async (params, options = defaultReportLedgerOptions) => {
71
+ const getLedgerData = async (params, options = defaultReportLedgerOptions, getFinancialIndexValue) => {
70
72
  const { productIds, startDate, endDate } = params;
71
73
  const addBrokers = true;
72
- const products = await LoanProducts_model_1.LoanProduct.find({ _id: { $in: productIds.map((id) => new mongoose_1.default.Types.ObjectId(id)) } }).lean();
74
+ const productMongoIds = productIds.map((id) => new mongoose_1.default.Types.ObjectId(id));
75
+ const products = await LoanProducts_model_1.LoanProduct.find({ _id: { $in: productMongoIds } }).lean();
76
+ const charges = await LoanCharges_model_1.LoanCharge.find({ productId: { $in: productMongoIds } }).lean();
77
+ const primeRate = await getFinancialIndexValue(financial_indexes_service_1.EFinancialIndex.PRIME_RATE, params.startDate);
73
78
  const borrowers = await Borrower_model_1.BorrowerModel.find({ _id: { $in: products.map((product) => product.borrowerId) } }).lean();
74
79
  const borrowerMap = borrowers.reduce((acc, borrower) => ({ ...acc, [borrower._id.toString()]: borrower.code }), {});
75
80
  const borrowerCodesMap = products.reduce((acc, product) => ({
@@ -135,6 +140,7 @@ const getLedgerData = async (params, options = defaultReportLedgerOptions) => {
135
140
  product: p,
136
141
  productId: p._id,
137
142
  transactions: productTransactions ? productTransactions.transactions : [],
143
+ charges: charges.filter((charge) => charge.productId.toString() === p._id.toString()),
138
144
  };
139
145
  });
140
146
  const mappedGroups = groupedProductsWithTransactions.reduce((acc, group) => {
@@ -162,6 +168,7 @@ const getLedgerData = async (params, options = defaultReportLedgerOptions) => {
162
168
  paymentDate: null,
163
169
  };
164
170
  }),
171
+ charges: group.charges,
165
172
  },
166
173
  };
167
174
  }, {});
@@ -255,7 +262,7 @@ const getLedgerData = async (params, options = defaultReportLedgerOptions) => {
255
262
  const mappedStatementTransactions = groupedMappedStatementTransactions
256
263
  .reduce((acc, group) => [...acc, ...group], []);
257
264
  const statementTransactionsWithBrokers = addBrokers
258
- ? await (0, brokers_db_1.enrichWithBrokers)(mappedStatementTransactions, group.product)
265
+ ? await (0, brokers_db_1.enrichWithBrokers)(mappedStatementTransactions, group.product, group.charges, primeRate)
259
266
  : mappedStatementTransactions;
260
267
  const sortedTransactions = [...statementTransactionsWithBrokers, ...group.transactions]
261
268
  .sort((a, b) => {
package/db/reports.db.ts CHANGED
@@ -24,6 +24,8 @@ import { enrichWithBrokers } from './brokers.db';
24
24
  import { TermLoanModel } from '../models/TermLoan.model';
25
25
  import { TermLoanCalculatedModel } from '../models/TermLoanCalculated.model';
26
26
  import { MODEL_NAMES } from '../models/_models';
27
+ import { ILoanChargeDoc, LoanCharge } from '../models/LoanCharges.model';
28
+ import { EFinancialIndex } from '../services/financial-indexes.service';
27
29
 
28
30
  export enum EChargeType {
29
31
  INTEREST_FEE = 'INTEREST',
@@ -101,11 +103,19 @@ const defaultReportLedgerOptions: ReportLedgerOptions = {
101
103
  showFloatedBalance: true,
102
104
  };
103
105
 
104
- export const getLedger = async (params: ReportLedgerParams, options = defaultReportLedgerOptions): Promise<{
106
+ type GetFinancialIndexValue = (index: EFinancialIndex, date?: Date) => Promise<number>;
107
+
108
+ export const getLedger = async (
109
+ params: ReportLedgerParams,
110
+ options = defaultReportLedgerOptions,
111
+ deps: {
112
+ getFinancialIndexValue: GetFinancialIndexValue;
113
+ },
114
+ ): Promise<{
105
115
  [productId: string]: ILedgerReportRow []
106
116
  }> => {
107
117
  const { productIds, reportType } = params;
108
- const fullTransactions = await getLedgerData(params, options);
118
+ const fullTransactions = await getLedgerData(params, options, deps.getFinancialIndexValue);
109
119
  const products = await LoanProduct
110
120
  .find({ _id: { $in: productIds.map((id) => new mongoose.Types.ObjectId(id)) } })
111
121
  .sort({ code: 1 })
@@ -130,13 +140,16 @@ export const getLedger = async (params: ReportLedgerParams, options = defaultRep
130
140
  }, {});
131
141
  };
132
142
 
133
- const getLedgerData = async (params: ReportLedgerParams, options = defaultReportLedgerOptions): Promise<{
143
+ const getLedgerData = async (params: ReportLedgerParams, options = defaultReportLedgerOptions, getFinancialIndexValue: GetFinancialIndexValue,): Promise<{
134
144
  [productId: string]: ILedgerReportRow[]
135
145
  }> => {
136
146
  const { productIds, startDate, endDate } = params;
137
147
 
138
148
  const addBrokers = true;
139
- const products = await LoanProduct.find({ _id: { $in: productIds.map((id) => new mongoose.Types.ObjectId(id)) } }).lean();
149
+ const productMongoIds = productIds.map((id) => new mongoose.Types.ObjectId(id));
150
+ const products = await LoanProduct.find({ _id: { $in: productMongoIds } }).lean();
151
+ const charges = await LoanCharge.find({ productId: { $in: productMongoIds } }).lean();
152
+ const primeRate = await getFinancialIndexValue(EFinancialIndex.PRIME_RATE, params.startDate);
140
153
  const borrowers = await BorrowerModel.find({ _id: { $in: products.map((product) => product.borrowerId) } }).lean();
141
154
  const borrowerMap = borrowers.reduce((acc, borrower) => (
142
155
  { ...acc, [borrower._id.toString()]: borrower.code }
@@ -207,11 +220,12 @@ const getLedgerData = async (params: ReportLedgerParams, options = defaultReport
207
220
  product: p,
208
221
  productId: p._id,
209
222
  transactions: productTransactions ? productTransactions.transactions : [],
223
+ charges: charges.filter((charge) => charge.productId.toString() === p._id.toString()),
210
224
  };
211
225
  });
212
226
 
213
227
  const mappedGroups: {
214
- [productId: string]: { transactions: ILedgerDataRow[], product: ILoanProductDoc }
228
+ [productId: string]: { transactions: ILedgerDataRow[], product: ILoanProductDoc, charges: ILoanChargeDoc[] }
215
229
  } = groupedProductsWithTransactions.reduce((acc, group) => {
216
230
  return {
217
231
  ...acc,
@@ -237,6 +251,7 @@ const getLedgerData = async (params: ReportLedgerParams, options = defaultReport
237
251
  paymentDate: null,
238
252
  };
239
253
  }),
254
+ charges: group.charges,
240
255
  },
241
256
  };
242
257
  }, {});
@@ -335,7 +350,7 @@ const getLedgerData = async (params: ReportLedgerParams, options = defaultReport
335
350
  const mappedStatementTransactions: ILedgerDataRow[] = groupedMappedStatementTransactions
336
351
  .reduce((acc, group) => [...acc, ...group], []);
337
352
  const statementTransactionsWithBrokers = addBrokers
338
- ? await enrichWithBrokers(mappedStatementTransactions, group.product)
353
+ ? await enrichWithBrokers(mappedStatementTransactions, group.product, group.charges, primeRate)
339
354
  : mappedStatementTransactions;
340
355
  const sortedTransactions = [...statementTransactionsWithBrokers, ...group.transactions]
341
356
  .sort((a, b) => {
@@ -39,6 +39,7 @@ export interface IProductBroker {
39
39
  BSCode: string;
40
40
  PLCode: string;
41
41
  productId: mongoose.Types.ObjectId;
42
+ baseInterestTotal: number;
42
43
  interestShare: number;
43
44
  adminShare: number;
44
45
  otherShare: number;
@@ -74,6 +75,7 @@ export declare const ProductBrokerSchema: mongoose.Schema<any, mongoose.Model<an
74
75
  BSCode: string;
75
76
  PLCode: string;
76
77
  productId: mongoose.Types.ObjectId;
78
+ baseInterestTotal: number;
77
79
  interestShare: number;
78
80
  adminShare: number;
79
81
  otherShare: number;
@@ -90,6 +92,7 @@ export declare const ProductBrokerSchema: mongoose.Schema<any, mongoose.Model<an
90
92
  BSCode: string;
91
93
  PLCode: string;
92
94
  productId: mongoose.Types.ObjectId;
95
+ baseInterestTotal: number;
93
96
  interestShare: number;
94
97
  adminShare: number;
95
98
  otherShare: number;
@@ -106,6 +109,7 @@ export declare const ProductBrokerSchema: mongoose.Schema<any, mongoose.Model<an
106
109
  BSCode: string;
107
110
  PLCode: string;
108
111
  productId: mongoose.Types.ObjectId;
112
+ baseInterestTotal: number;
109
113
  interestShare: number;
110
114
  adminShare: number;
111
115
  otherShare: number;
@@ -17,6 +17,7 @@ exports.ProductBrokerValidationSchema = joi_1.default.object({
17
17
  BSCode: joi_1.default.string().required(),
18
18
  PLCode: joi_1.default.string().required(),
19
19
  productId: joi_1.default.string().required(),
20
+ baseInterestTotal: joi_1.default.number().required(),
20
21
  interestShare: joi_1.default.number().required(),
21
22
  adminShare: joi_1.default.number().required(),
22
23
  otherShare: joi_1.default.number().required(),
@@ -60,6 +61,10 @@ exports.ProductBrokerSchema = new mongoose_1.default.Schema({
60
61
  ref: _models_1.MODEL_NAMES.loanProducts,
61
62
  required: true,
62
63
  },
64
+ baseInterestTotal: {
65
+ type: Number,
66
+ required: true,
67
+ },
63
68
  interestShare: {
64
69
  type: Number,
65
70
  required: true,
@@ -14,6 +14,7 @@ export const ProductBrokerValidationSchema = Joi.object({
14
14
  BSCode: Joi.string().required(),
15
15
  PLCode: Joi.string().required(),
16
16
  productId: Joi.string().required(),
17
+ baseInterestTotal: Joi.number().required(),
17
18
  interestShare: Joi.number().required(),
18
19
  adminShare: Joi.number().required(),
19
20
  otherShare: Joi.number().required(),
@@ -28,6 +29,7 @@ export interface IProductBroker {
28
29
  BSCode: string;
29
30
  PLCode: string;
30
31
  productId: mongoose.Types.ObjectId;
32
+ baseInterestTotal: number;
31
33
  interestShare: number;
32
34
  adminShare: number;
33
35
  otherShare: number;
@@ -96,6 +98,10 @@ export const ProductBrokerSchema = new mongoose.Schema(
96
98
  ref: MODEL_NAMES.loanProducts,
97
99
  required: true,
98
100
  },
101
+ baseInterestTotal: {
102
+ type: Number,
103
+ required: true,
104
+ },
99
105
  interestShare: {
100
106
  type: Number,
101
107
  required: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gemcap-be-common",
3
- "version": "1.5.133",
3
+ "version": "1.5.135",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -18,6 +18,7 @@ const defaultBrokerList = [
18
18
  PLCode: '',
19
19
  productId: null,
20
20
  loanBrokerId: null,
21
+ baseInterestTotal: 0,
21
22
  adminShare: 0,
22
23
  interestShare: 0,
23
24
  otherShare: 0,
@@ -84,6 +85,7 @@ class BrokersService {
84
85
  BSCode: null,
85
86
  PLCode: null,
86
87
  productId: product,
88
+ baseInterestTotal: null,
87
89
  adminShare: shares.adminShare,
88
90
  interestShare: shares.interestShare,
89
91
  otherShare: shares.otherShare,
@@ -92,7 +94,7 @@ class BrokersService {
92
94
  }
93
95
  async checkTotalShares(borrowerId, brokers) {
94
96
  const productShares = await this.getTotalShares(borrowerId, brokers);
95
- return !Object.values(productShares).some(values => values.adminShare > 1 || values.interestShare > 1 || values.otherShare > 1);
97
+ return !Object.values(productShares).some((values) => values.adminShare > 1 || values.interestShare > 1 || values.otherShare > 1);
96
98
  }
97
99
  async saveProductBrokers(borrowerId, brokers) {
98
100
  const existingBrokers = await (0, brokers_db_2.getBorrowerBrokers)(borrowerId);
@@ -26,6 +26,7 @@ const defaultBrokerList: BrokerView[] = [
26
26
  PLCode: '',
27
27
  productId: null,
28
28
  loanBrokerId: null,
29
+ baseInterestTotal: 0,
29
30
  adminShare: 0,
30
31
  interestShare: 0,
31
32
  otherShare: 0,
@@ -111,6 +112,7 @@ export class BrokersService {
111
112
  BSCode: null,
112
113
  PLCode: null,
113
114
  productId: product,
115
+ baseInterestTotal: null,
114
116
  adminShare: shares.adminShare,
115
117
  interestShare: shares.interestShare,
116
118
  otherShare: shares.otherShare,
@@ -120,7 +122,7 @@ export class BrokersService {
120
122
 
121
123
  async checkTotalShares(borrowerId: string, brokers: IProductBrokerView[]) {
122
124
  const productShares = await this.getTotalShares(borrowerId, brokers);
123
- return !Object.values(productShares).some(values => values.adminShare > 1 || values.interestShare > 1 || values.otherShare > 1);
125
+ return !Object.values(productShares).some((values) => values.adminShare > 1 || values.interestShare > 1 || values.otherShare > 1);
124
126
  }
125
127
 
126
128
  async saveProductBrokers(borrowerId: string, brokers: IProductBrokerView[]) {
@@ -35,6 +35,7 @@ import { CashAllocationService } from './cash-allocation.service';
35
35
  import { CompaniesService } from './companies.service';
36
36
  import { LoanChargesService } from './loan-charges.service';
37
37
  import { LoanPaymentsService } from './loan-payments.service';
38
+ import { FinancialIndexesService } from './financial-indexes.service';
38
39
  export type QuickBookReportType = 'accrual' | 'payment' | 'cash';
39
40
  interface IQBReportTransaction {
40
41
  service: string;
@@ -58,7 +59,8 @@ export declare class QuickbooksService {
58
59
  private readonly companiesService;
59
60
  private readonly loanChargesService;
60
61
  private readonly loanPaymentsService;
61
- constructor(banksService: BanksService, bankUploadedTransactionsService: BankUploadedTransactionsService, borrowersDB: BorrowersDB, brokersService: BrokersService, cashAllocationService: CashAllocationService, companiesService: CompaniesService, loanChargesService: LoanChargesService, loanPaymentsService: LoanPaymentsService);
62
+ private readonly financialIndexesService;
63
+ constructor(banksService: BanksService, bankUploadedTransactionsService: BankUploadedTransactionsService, borrowersDB: BorrowersDB, brokersService: BrokersService, cashAllocationService: CashAllocationService, companiesService: CompaniesService, loanChargesService: LoanChargesService, loanPaymentsService: LoanPaymentsService, financialIndexesService: FinancialIndexesService);
62
64
  uploadAccounts(accounts: IQuickbooksUploadItem[], deleteOld: boolean): Promise<void>;
63
65
  getAllAccounts(): Promise<(mongoose.FlattenMaps<IQuickbooksAccount> & {
64
66
  _id: mongoose.Types.ObjectId;
@@ -16,6 +16,8 @@ const TermLoan_model_1 = require("../models/TermLoan.model");
16
16
  const reports_db_1 = require("../db/reports.db");
17
17
  const QuickbooksAccount_model_1 = require("../models/QuickbooksAccount.model");
18
18
  const date_helper_1 = require("../helpers/date.helper");
19
+ const financial_indexes_service_1 = require("./financial-indexes.service");
20
+ const brokers_db_1 = require("../db/brokers.db");
19
21
  const headersIIF = [
20
22
  {
21
23
  service: '!TRNS',
@@ -88,7 +90,8 @@ class QuickbooksService {
88
90
  companiesService;
89
91
  loanChargesService;
90
92
  loanPaymentsService;
91
- constructor(banksService, bankUploadedTransactionsService, borrowersDB, brokersService, cashAllocationService, companiesService, loanChargesService, loanPaymentsService) {
93
+ financialIndexesService;
94
+ constructor(banksService, bankUploadedTransactionsService, borrowersDB, brokersService, cashAllocationService, companiesService, loanChargesService, loanPaymentsService, financialIndexesService) {
92
95
  this.banksService = banksService;
93
96
  this.bankUploadedTransactionsService = bankUploadedTransactionsService;
94
97
  this.borrowersDB = borrowersDB;
@@ -97,6 +100,7 @@ class QuickbooksService {
97
100
  this.companiesService = companiesService;
98
101
  this.loanChargesService = loanChargesService;
99
102
  this.loanPaymentsService = loanPaymentsService;
103
+ this.financialIndexesService = financialIndexesService;
100
104
  }
101
105
  async uploadAccounts(accounts, deleteOld) {
102
106
  const accountsWithId = accounts.map((account) => ({ _id: 'new_', ...account }));
@@ -325,6 +329,7 @@ class QuickbooksService {
325
329
  document: '',
326
330
  memo: '',
327
331
  };
332
+ const primeRate = await this.financialIndexesService.getFinancialIndexValue(financial_indexes_service_1.EFinancialIndex.PRIME_RATE, reportDate);
328
333
  await Promise.all(productIds.map(async (productId) => {
329
334
  const product = await this.loanChargesService.getLoanProductById(productId);
330
335
  const charges = await this.loanChargesService.getLoanChargeForProduct(productId);
@@ -395,11 +400,18 @@ class QuickbooksService {
395
400
  }
396
401
  return;
397
402
  }
403
+ let brokerAmount;
404
+ if (shareName === 'interestShare') {
405
+ brokerAmount = (0, brokers_db_1.handleBrokerInterestFee)(-totalAmount, charges, broker.interestShare, broker.baseInterestTotal, primeRate);
406
+ }
407
+ else {
408
+ brokerAmount = new decimal_js_1.default(-totalAmount).mul(broker[shareName]).toDP(2).toNumber();
409
+ }
398
410
  const tr = {
399
411
  ...trTemplate,
400
412
  productId,
401
413
  class: borrower.code,
402
- amount: new decimal_js_1.default(-totalAmount).mul(broker[shareName]).toDP(2).toNumber(),
414
+ amount: brokerAmount,
403
415
  memo: `${borrower.code} ${reports_db_1.EChargeType[charge.chargeType].toUpperCase()} BROKER ${broker.order + 1}`,
404
416
  };
405
417
  tr.account = quickbooksAccountBrokerBS.fullName;
@@ -23,6 +23,8 @@ import { CompaniesService } from './companies.service';
23
23
  import { LoanChargesService } from './loan-charges.service';
24
24
  import { LoanPaymentsService } from './loan-payments.service';
25
25
  import { isProductActive } from '../helpers/date.helper';
26
+ import { EFinancialIndex, FinancialIndexesService } from './financial-indexes.service';
27
+ import { handleBrokerInterestFee } from '../db/brokers.db';
26
28
 
27
29
  export type QuickBookReportType = 'accrual' | 'payment' | 'cash';
28
30
 
@@ -130,6 +132,7 @@ export class QuickbooksService {
130
132
  private readonly companiesService: CompaniesService,
131
133
  private readonly loanChargesService: LoanChargesService,
132
134
  private readonly loanPaymentsService: LoanPaymentsService,
135
+ private readonly financialIndexesService: FinancialIndexesService,
133
136
  ) {
134
137
  }
135
138
 
@@ -380,6 +383,8 @@ export class QuickbooksService {
380
383
  memo: '',
381
384
  };
382
385
 
386
+ const primeRate = await this.financialIndexesService.getFinancialIndexValue(EFinancialIndex.PRIME_RATE, reportDate)
387
+
383
388
  await Promise.all(productIds.map(async (productId) => {
384
389
  const product = await this.loanChargesService.getLoanProductById(productId);
385
390
  const charges = await this.loanChargesService.getLoanChargeForProduct(productId);
@@ -460,11 +465,18 @@ export class QuickbooksService {
460
465
  return;
461
466
  }
462
467
 
468
+ let brokerAmount: number;
469
+ if (shareName === 'interestShare') {
470
+ brokerAmount = handleBrokerInterestFee(-totalAmount, charges, broker.interestShare, broker.baseInterestTotal, primeRate);
471
+ } else {
472
+ brokerAmount = new Decimal(-totalAmount).mul(broker[shareName]).toDP(2).toNumber();
473
+ }
474
+
463
475
  const tr: IQBReportTransaction = {
464
476
  ...trTemplate,
465
477
  productId,
466
478
  class: borrower.code,
467
- amount: new Decimal(-totalAmount).mul(broker[shareName]).toDP(2).toNumber(),
479
+ amount: brokerAmount,
468
480
  memo: `${borrower.code} ${EChargeType[charge.chargeType].toUpperCase()} BROKER ${broker.order + 1}`,
469
481
  };
470
482
 
@@ -36,6 +36,7 @@ import { LoanChargesService } from './loan-charges.service';
36
36
  import { LoanTransactionsService } from './loan-transactions.service';
37
37
  import { SignsService } from './signs.service';
38
38
  import { UploadsService } from './uploads.service';
39
+ import { FinancialIndexesService } from './financial-indexes.service';
39
40
  export interface IBankReportData {
40
41
  borrowerId?: string;
41
42
  borrowerName: string;
@@ -97,8 +98,9 @@ export declare class ReportsService {
97
98
  private readonly signsService;
98
99
  private readonly uploadsService;
99
100
  private readonly investorSummaryService;
101
+ private readonly financialIndexesService;
100
102
  margin: number;
101
- constructor(availabilityService: AvailabilityService, borrowerService: BorrowerService, collateralAdjustmentsService: CollateralAdjustmentsService, collateralsService: CollateralsService, equipmentService: EquipmentService, loanChargesService: LoanChargesService, loanTransactionsService: LoanTransactionsService, signsService: SignsService, uploadsService: UploadsService, investorSummaryService: InvestorSummaryService);
103
+ constructor(availabilityService: AvailabilityService, borrowerService: BorrowerService, collateralAdjustmentsService: CollateralAdjustmentsService, collateralsService: CollateralsService, equipmentService: EquipmentService, loanChargesService: LoanChargesService, loanTransactionsService: LoanTransactionsService, signsService: SignsService, uploadsService: UploadsService, investorSummaryService: InvestorSummaryService, financialIndexesService: FinancialIndexesService);
102
104
  getCollateralAdjustmentsForLastSignedBBC(borrowerId: string, date: Date): Promise<number>;
103
105
  private getProductBalances;
104
106
  getBorrowerAndProducts(borrowerId: string, date: Date, useSignedBBC?: boolean, requireBBC?: boolean): Promise<{