gemcap-be-common 1.3.100 → 1.3.102
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/package.json +1 -1
- package/repositories/calendar.repository.d.ts +3 -0
- package/repositories/calendar.repository.js +24 -0
- package/repositories/calendar.repository.ts +19 -0
- package/repositories/postponed-transactions.repository.d.ts +5 -0
- package/repositories/postponed-transactions.repository.js +13 -0
- package/repositories/postponed-transactions.repository.ts +11 -0
- package/services/calendar.service.d.ts +3 -0
- package/services/calendar.service.js +5 -11
- package/services/calendar.service.ts +8 -11
- package/services/loan-transactions.service.d.ts +3 -3
- package/services/loan-transactions.service.js +127 -155
- package/services/loan-transactions.service.ts +128 -155
- package/services/postponed-transactions.service.d.ts +10 -0
- package/services/postponed-transactions.service.js +30 -0
- package/services/postponed-transactions.service.ts +30 -0
- package/tsconfig.tsbuildinfo +1 -1
package/package.json
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.CalendarRepository = void 0;
|
|
7
|
+
const dayjs_1 = __importDefault(require("dayjs"));
|
|
8
|
+
const CalandarDay_model_1 = __importDefault(require("../models/CalandarDay.model"));
|
|
9
|
+
class CalendarRepository {
|
|
10
|
+
async getNextWorkingDay(date) {
|
|
11
|
+
let nextDay = (0, dayjs_1.default)(new Date(date));
|
|
12
|
+
let isWorking = false;
|
|
13
|
+
do {
|
|
14
|
+
nextDay = nextDay.add(1, 'day');
|
|
15
|
+
const calendarDay = await CalandarDay_model_1.default.findOne({ date: nextDay.format('YYYY-MM-DD') }).lean();
|
|
16
|
+
if (!calendarDay) {
|
|
17
|
+
console.error(`no data in calendar for ${nextDay.format('YYYY-MM-DD')}`);
|
|
18
|
+
}
|
|
19
|
+
isWorking = calendarDay ? calendarDay.workingDay : true;
|
|
20
|
+
} while (isWorking === false);
|
|
21
|
+
return nextDay.format('YYYY-MM-DD');
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.CalendarRepository = CalendarRepository;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import dayjs from 'dayjs';
|
|
2
|
+
|
|
3
|
+
import CalendarDay from '../models/CalandarDay.model';
|
|
4
|
+
|
|
5
|
+
export class CalendarRepository {
|
|
6
|
+
async getNextWorkingDay(date: string) {
|
|
7
|
+
let nextDay = dayjs(new Date(date));
|
|
8
|
+
let isWorking = false;
|
|
9
|
+
do {
|
|
10
|
+
nextDay = nextDay.add(1, 'day');
|
|
11
|
+
const calendarDay = await CalendarDay.findOne({ date: nextDay.format('YYYY-MM-DD') }).lean();
|
|
12
|
+
if (!calendarDay) {
|
|
13
|
+
console.error(`no data in calendar for ${nextDay.format('YYYY-MM-DD')}`);
|
|
14
|
+
}
|
|
15
|
+
isWorking = calendarDay ? calendarDay.workingDay : true;
|
|
16
|
+
} while (isWorking === false);
|
|
17
|
+
return nextDay.format('YYYY-MM-DD');
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { IPostponedTransaction } from '../models/PostponedTransactions.model';
|
|
2
|
+
export declare class PostponedTransactionsRepository {
|
|
3
|
+
cleanRecalculated(transactionId: string): Promise<void>;
|
|
4
|
+
createPostponedTransaction(postponedTransaction: IPostponedTransaction): Promise<void>;
|
|
5
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PostponedTransactionsRepository = void 0;
|
|
4
|
+
const PostponedTransactions_model_1 = require("../models/PostponedTransactions.model");
|
|
5
|
+
class PostponedTransactionsRepository {
|
|
6
|
+
async cleanRecalculated(transactionId) {
|
|
7
|
+
await PostponedTransactions_model_1.PostponedTransaction.deleteMany({ transactionId });
|
|
8
|
+
}
|
|
9
|
+
async createPostponedTransaction(postponedTransaction) {
|
|
10
|
+
await PostponedTransactions_model_1.PostponedTransaction.create(postponedTransaction);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
exports.PostponedTransactionsRepository = PostponedTransactionsRepository;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { IPostponedTransaction, PostponedTransaction } from '../models/PostponedTransactions.model';
|
|
2
|
+
|
|
3
|
+
export class PostponedTransactionsRepository {
|
|
4
|
+
async cleanRecalculated(transactionId: string) {
|
|
5
|
+
await PostponedTransaction.deleteMany({ transactionId });
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
async createPostponedTransaction(postponedTransaction: IPostponedTransaction) {
|
|
9
|
+
await PostponedTransaction.create(postponedTransaction);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
/// <reference types="mongoose/types/virtuals" />
|
|
24
24
|
/// <reference types="mongoose" />
|
|
25
25
|
/// <reference types="mongoose/types/inferschematype" />
|
|
26
|
+
import { CalendarRepository } from '../repositories/calendar.repository';
|
|
26
27
|
interface IWorkingDaysApi {
|
|
27
28
|
working_day: number;
|
|
28
29
|
work_hours: number;
|
|
@@ -40,6 +41,8 @@ interface IWorkingDaysApi {
|
|
|
40
41
|
type: number;
|
|
41
42
|
}
|
|
42
43
|
export declare class CalendarService {
|
|
44
|
+
private readonly calendarRepository;
|
|
45
|
+
constructor(calendarRepository: CalendarRepository);
|
|
43
46
|
fulfillCalendar(): Promise<void>;
|
|
44
47
|
createDate(date: string, dateProp: IWorkingDaysApi): Promise<void>;
|
|
45
48
|
isWorkingDay(date: string): Promise<boolean>;
|
|
@@ -8,6 +8,10 @@ const axios_1 = __importDefault(require("axios"));
|
|
|
8
8
|
const dayjs_1 = __importDefault(require("dayjs"));
|
|
9
9
|
const CalandarDay_model_1 = __importDefault(require("../models/CalandarDay.model"));
|
|
10
10
|
class CalendarService {
|
|
11
|
+
calendarRepository;
|
|
12
|
+
constructor(calendarRepository) {
|
|
13
|
+
this.calendarRepository = calendarRepository;
|
|
14
|
+
}
|
|
11
15
|
async fulfillCalendar() {
|
|
12
16
|
const getDays = () => {
|
|
13
17
|
const days = [];
|
|
@@ -76,17 +80,7 @@ class CalendarService {
|
|
|
76
80
|
return !isNextDayWorking;
|
|
77
81
|
}
|
|
78
82
|
async getNextWorkingDay(date) {
|
|
79
|
-
|
|
80
|
-
let isWorking = false;
|
|
81
|
-
do {
|
|
82
|
-
nextDay = nextDay.add(1, 'day');
|
|
83
|
-
const calendarDay = await CalandarDay_model_1.default.findOne({ date: nextDay.format('YYYY-MM-DD') }).lean();
|
|
84
|
-
if (!calendarDay) {
|
|
85
|
-
console.error(`no data in calendar for ${nextDay.format('YYYY-MM-DD')}`);
|
|
86
|
-
}
|
|
87
|
-
isWorking = calendarDay ? calendarDay.workingDay : true;
|
|
88
|
-
} while (isWorking === false);
|
|
89
|
-
return nextDay.format('YYYY-MM-DD');
|
|
83
|
+
return this.calendarRepository.getNextWorkingDay(date);
|
|
90
84
|
}
|
|
91
85
|
async getLastWorkingDay(date) {
|
|
92
86
|
let previous = (0, dayjs_1.default)(new Date(date));
|
|
@@ -2,6 +2,7 @@ import axios from 'axios';
|
|
|
2
2
|
import dayjs from 'dayjs';
|
|
3
3
|
|
|
4
4
|
import CalendarDay, { ICalendarDay } from '../models/CalandarDay.model';
|
|
5
|
+
import { CalendarRepository } from '../repositories/calendar.repository';
|
|
5
6
|
|
|
6
7
|
interface IWorkingDaysApi {
|
|
7
8
|
working_day: number;
|
|
@@ -21,6 +22,12 @@ interface IWorkingDaysApi {
|
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
export class CalendarService {
|
|
25
|
+
|
|
26
|
+
constructor(
|
|
27
|
+
private readonly calendarRepository: CalendarRepository,
|
|
28
|
+
) {
|
|
29
|
+
}
|
|
30
|
+
|
|
24
31
|
async fulfillCalendar() {
|
|
25
32
|
|
|
26
33
|
const getDays = () => {
|
|
@@ -95,17 +102,7 @@ export class CalendarService {
|
|
|
95
102
|
}
|
|
96
103
|
|
|
97
104
|
async getNextWorkingDay(date: string) {
|
|
98
|
-
|
|
99
|
-
let isWorking = false;
|
|
100
|
-
do {
|
|
101
|
-
nextDay = nextDay.add(1, 'day');
|
|
102
|
-
const calendarDay = await CalendarDay.findOne({ date: nextDay.format('YYYY-MM-DD') }).lean();
|
|
103
|
-
if (!calendarDay) {
|
|
104
|
-
console.error(`no data in calendar for ${nextDay.format('YYYY-MM-DD')}`);
|
|
105
|
-
}
|
|
106
|
-
isWorking = calendarDay ? calendarDay.workingDay : true;
|
|
107
|
-
} while (isWorking === false);
|
|
108
|
-
return nextDay.format('YYYY-MM-DD');
|
|
105
|
+
return this.calendarRepository.getNextWorkingDay(date);
|
|
109
106
|
}
|
|
110
107
|
|
|
111
108
|
async getLastWorkingDay(date: string) {
|
|
@@ -39,6 +39,7 @@ import { LoanStatementStatusService } from './loan-statement-status.service';
|
|
|
39
39
|
import { NodemailerService } from './nodemailer.service';
|
|
40
40
|
import { TermLoanService } from './term-loan.service';
|
|
41
41
|
import { LockService } from './lock.service';
|
|
42
|
+
import { PostponedTransactionsService } from './postponed-transactions.service';
|
|
42
43
|
interface ILoanTransactionsServiceConfig {
|
|
43
44
|
portfolioEmail: string;
|
|
44
45
|
}
|
|
@@ -63,8 +64,9 @@ export declare class LoanTransactionsService {
|
|
|
63
64
|
private readonly lockService;
|
|
64
65
|
private readonly termLoanService;
|
|
65
66
|
private readonly uploadsService;
|
|
67
|
+
private readonly postponedTransactionsService;
|
|
66
68
|
private readonly config;
|
|
67
|
-
constructor(config: ILoanTransactionsServiceConfig, attachedFilesService: AttachedFilesService, banksService: BanksService, borrowersDB: BorrowersDB, calendarService: CalendarService, loanChargesService: LoanChargesService, getLoanPaymentsService: () => LoanPaymentsService, getLoanStatementService: () => LoanStatementService, loanStatementStatusService: LoanStatementStatusService, getNodemailerService: () => NodemailerService, lockService: LockService, termLoanService: TermLoanService, uploadsService: UploadsService);
|
|
69
|
+
constructor(config: ILoanTransactionsServiceConfig, attachedFilesService: AttachedFilesService, banksService: BanksService, borrowersDB: BorrowersDB, calendarService: CalendarService, loanChargesService: LoanChargesService, getLoanPaymentsService: () => LoanPaymentsService, getLoanStatementService: () => LoanStatementService, loanStatementStatusService: LoanStatementStatusService, getNodemailerService: () => NodemailerService, lockService: LockService, termLoanService: TermLoanService, uploadsService: UploadsService, postponedTransactionsService: PostponedTransactionsService);
|
|
68
70
|
getTransactionsById(transactionId: string): Promise<mongoose.FlattenMaps<ILoanTransaction> & {
|
|
69
71
|
_id: mongoose.Types.ObjectId;
|
|
70
72
|
}>;
|
|
@@ -113,8 +115,6 @@ export declare class LoanTransactionsService {
|
|
|
113
115
|
recalculateBalanceLegacy(transactionId: string): Promise<void>;
|
|
114
116
|
recalculateBalance(transactionId: string): Promise<void>;
|
|
115
117
|
deleteLoanTransaction(transactionId: string, updateLoanPayment: boolean, userId?: any): Promise<void>;
|
|
116
|
-
createPostponedTransaction(transaction: ILoanTransactionDoc): Promise<void>;
|
|
117
|
-
cleanRecalculated(transactionId: string): Promise<void>;
|
|
118
118
|
deleteLoanTransactionFile(transactionFileId: string, userId: string): Promise<any>;
|
|
119
119
|
getFirstTransaction(productId: string, excludeAdjustments?: boolean): Promise<ILoanTransactionDoc>;
|
|
120
120
|
getLastTransactionForDate(productId: string, date?: Date, excludeAdjustments?: boolean): Promise<ILoanTransactionDoc>;
|
|
@@ -36,8 +36,9 @@ class LoanTransactionsService {
|
|
|
36
36
|
lockService;
|
|
37
37
|
termLoanService;
|
|
38
38
|
uploadsService;
|
|
39
|
+
postponedTransactionsService;
|
|
39
40
|
config;
|
|
40
|
-
constructor(config, attachedFilesService, banksService, borrowersDB, calendarService, loanChargesService, getLoanPaymentsService, getLoanStatementService, loanStatementStatusService, getNodemailerService, lockService, termLoanService, uploadsService) {
|
|
41
|
+
constructor(config, attachedFilesService, banksService, borrowersDB, calendarService, loanChargesService, getLoanPaymentsService, getLoanStatementService, loanStatementStatusService, getNodemailerService, lockService, termLoanService, uploadsService, postponedTransactionsService) {
|
|
41
42
|
this.attachedFilesService = attachedFilesService;
|
|
42
43
|
this.banksService = banksService;
|
|
43
44
|
this.borrowersDB = borrowersDB;
|
|
@@ -50,6 +51,7 @@ class LoanTransactionsService {
|
|
|
50
51
|
this.lockService = lockService;
|
|
51
52
|
this.termLoanService = termLoanService;
|
|
52
53
|
this.uploadsService = uploadsService;
|
|
54
|
+
this.postponedTransactionsService = postponedTransactionsService;
|
|
53
55
|
this.config = config;
|
|
54
56
|
}
|
|
55
57
|
async getTransactionsById(transactionId) {
|
|
@@ -313,11 +315,11 @@ class LoanTransactionsService {
|
|
|
313
315
|
updatedTransaction = await LoanTransaction_model_1.LoanTransaction.findByIdAndUpdate(transaction._id, transaction, { new: true });
|
|
314
316
|
}
|
|
315
317
|
if (startId) {
|
|
316
|
-
|
|
318
|
+
this.recalculateBalance(startId).catch(console.error);
|
|
317
319
|
}
|
|
318
320
|
const statementDate = this.loanStatementStatusService.getStatementDateForDate(new Date(transaction.date));
|
|
319
|
-
|
|
320
|
-
|
|
321
|
+
this.loanStatementStatusService.updateStatementStatus(transaction.productId.toString(), statementDate, false).catch(console.error);
|
|
322
|
+
this.termLoanService.setTermLoanExpected(transaction.productId.toString()).catch(console.error);
|
|
321
323
|
return updatedTransaction;
|
|
322
324
|
}
|
|
323
325
|
async recalculateProduct(productId) {
|
|
@@ -345,136 +347,120 @@ class LoanTransactionsService {
|
|
|
345
347
|
return;
|
|
346
348
|
}
|
|
347
349
|
const recalcBalance = async () => {
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
{
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
{
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
for (const transaction of recalculatedTransactions) {
|
|
386
|
-
currentBalance = new decimal_js_1.default(currentBalance).add(transaction.amount).toNumber();
|
|
387
|
-
await LoanTransaction_model_1.LoanTransaction.findByIdAndUpdate(transaction._id, { balance: currentBalance });
|
|
388
|
-
}
|
|
389
|
-
await LoanProducts_model_1.LoanProduct.findByIdAndUpdate(changedTransaction.productId, { isBalanceActual: true });
|
|
390
|
-
});
|
|
391
|
-
}
|
|
392
|
-
finally {
|
|
393
|
-
await session.endSession();
|
|
350
|
+
await LoanProducts_model_1.LoanProduct.findByIdAndUpdate(changedTransaction.productId, { isBalanceActual: false });
|
|
351
|
+
const previousTransaction = await LoanTransaction_model_1.LoanTransaction.aggregate([
|
|
352
|
+
{
|
|
353
|
+
$match: {
|
|
354
|
+
'productId': new mongoose_1.default.Types.ObjectId(changedTransaction.productId.toString()),
|
|
355
|
+
'date': { $lt: new Date(changedTransaction.date) },
|
|
356
|
+
},
|
|
357
|
+
}, {
|
|
358
|
+
$sort: {
|
|
359
|
+
'date': -1,
|
|
360
|
+
'order': -1,
|
|
361
|
+
'createdAt': -1,
|
|
362
|
+
},
|
|
363
|
+
}, {
|
|
364
|
+
$limit: 1,
|
|
365
|
+
},
|
|
366
|
+
]);
|
|
367
|
+
let currentBalance = previousTransaction.length
|
|
368
|
+
? previousTransaction[0].balance ?? 0
|
|
369
|
+
: 0;
|
|
370
|
+
const recalculatedTransactions = await LoanTransaction_model_1.LoanTransaction.aggregate([
|
|
371
|
+
{
|
|
372
|
+
$match: {
|
|
373
|
+
'productId': new mongoose_1.default.Types.ObjectId(changedTransaction.productId.toString()),
|
|
374
|
+
'date': { $gte: new Date(changedTransaction.date) },
|
|
375
|
+
},
|
|
376
|
+
}, {
|
|
377
|
+
$sort: {
|
|
378
|
+
'date': 1,
|
|
379
|
+
'order': 1,
|
|
380
|
+
'createdAt': 1,
|
|
381
|
+
},
|
|
382
|
+
},
|
|
383
|
+
]);
|
|
384
|
+
for (const transaction of recalculatedTransactions) {
|
|
385
|
+
currentBalance = new decimal_js_1.default(currentBalance).add(transaction.amount).toNumber();
|
|
386
|
+
await LoanTransaction_model_1.LoanTransaction.findByIdAndUpdate(transaction._id, { balance: currentBalance });
|
|
394
387
|
}
|
|
388
|
+
await LoanProducts_model_1.LoanProduct.findByIdAndUpdate(changedTransaction.productId, { isBalanceActual: true });
|
|
395
389
|
};
|
|
396
390
|
const recalcFloatedBalance = async () => {
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
{
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
391
|
+
await LoanProducts_model_1.LoanProduct.findByIdAndUpdate(changedTransaction.productId, { isFloatedBalanceActual: false });
|
|
392
|
+
const previousEqualBalancesTransaction = await LoanTransaction_model_1.LoanTransaction.aggregate([
|
|
393
|
+
{
|
|
394
|
+
$match: {
|
|
395
|
+
'productId': new mongoose_1.default.Types.ObjectId(changedTransaction.productId.toString()),
|
|
396
|
+
'date': { $lt: new Date(changedTransaction.date) },
|
|
397
|
+
$expr: { $eq: ['$balance', '$floatedBalance'] },
|
|
398
|
+
},
|
|
399
|
+
}, {
|
|
400
|
+
$sort: {
|
|
401
|
+
'date': -1,
|
|
402
|
+
'order': -1,
|
|
403
|
+
'createdAt': -1,
|
|
404
|
+
},
|
|
405
|
+
}, {
|
|
406
|
+
$limit: 1,
|
|
407
|
+
},
|
|
408
|
+
]);
|
|
409
|
+
let currentFloatedBalance = 0;
|
|
410
|
+
if (previousEqualBalancesTransaction.length) {
|
|
411
|
+
const previousTransaction = await LoanTransaction_model_1.LoanTransaction.aggregate([
|
|
412
|
+
{
|
|
413
|
+
$match: {
|
|
414
|
+
'productId': new mongoose_1.default.Types.ObjectId(previousEqualBalancesTransaction[0].productId.toString()),
|
|
415
|
+
'date': { $lt: new Date(previousEqualBalancesTransaction[0].date) },
|
|
416
416
|
},
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
$match: {
|
|
423
|
-
'productId': new mongoose_1.default.Types.ObjectId(previousEqualBalancesTransaction[0].productId.toString()),
|
|
424
|
-
'date': { $lt: new Date(previousEqualBalancesTransaction[0].date) },
|
|
425
|
-
},
|
|
426
|
-
}, {
|
|
427
|
-
$sort: {
|
|
428
|
-
'date': -1,
|
|
429
|
-
'order': -1,
|
|
430
|
-
'createdAt': -1,
|
|
431
|
-
},
|
|
432
|
-
}, {
|
|
433
|
-
$limit: 1,
|
|
434
|
-
},
|
|
435
|
-
]);
|
|
436
|
-
if (previousTransaction.length) {
|
|
437
|
-
currentFloatedBalance = previousTransaction[0].floatedBalance;
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
const initTransaction = previousEqualBalancesTransaction.length ? previousEqualBalancesTransaction[0] : changedTransaction;
|
|
441
|
-
const recalculatedTransactions = await LoanTransaction_model_1.LoanTransaction.aggregate([
|
|
442
|
-
{
|
|
443
|
-
$match: {
|
|
444
|
-
'productId': new mongoose_1.default.Types.ObjectId(initTransaction.productId.toString()),
|
|
445
|
-
'date': { $gte: new Date(initTransaction.date) },
|
|
446
|
-
},
|
|
447
|
-
}, {
|
|
448
|
-
$sort: {
|
|
449
|
-
'date': 1,
|
|
450
|
-
'order': 1,
|
|
451
|
-
'createdAt': 1,
|
|
452
|
-
},
|
|
417
|
+
}, {
|
|
418
|
+
$sort: {
|
|
419
|
+
'date': -1,
|
|
420
|
+
'order': -1,
|
|
421
|
+
'createdAt': -1,
|
|
453
422
|
},
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
currentFloatedBalance = new decimal_js_1.default(currentFloatedBalance).add(totalPostponed).toNumber();
|
|
462
|
-
break;
|
|
463
|
-
case LoanTransaction_model_1.ELoanTransactionTypes.DISBURSEMENT:
|
|
464
|
-
currentFloatedBalance = new decimal_js_1.default(currentFloatedBalance).add(transaction.amount).add(totalPostponed).toNumber();
|
|
465
|
-
break;
|
|
466
|
-
case LoanTransaction_model_1.ELoanTransactionTypes.ADJUSTMENT:
|
|
467
|
-
currentFloatedBalance = new decimal_js_1.default(currentFloatedBalance).add(transaction.amount).add(totalPostponed).toNumber();
|
|
468
|
-
break;
|
|
469
|
-
}
|
|
470
|
-
await LoanTransaction_model_1.LoanTransaction.findByIdAndUpdate(transaction._id, { floatedBalance: currentFloatedBalance });
|
|
471
|
-
}
|
|
472
|
-
await LoanProducts_model_1.LoanProduct.findByIdAndUpdate(changedTransaction.productId, { isFloatedBalanceActual: true });
|
|
473
|
-
});
|
|
423
|
+
}, {
|
|
424
|
+
$limit: 1,
|
|
425
|
+
},
|
|
426
|
+
]);
|
|
427
|
+
if (previousTransaction.length) {
|
|
428
|
+
currentFloatedBalance = previousTransaction[0].floatedBalance;
|
|
429
|
+
}
|
|
474
430
|
}
|
|
475
|
-
|
|
476
|
-
|
|
431
|
+
const initTransaction = previousEqualBalancesTransaction.length ? previousEqualBalancesTransaction[0] : changedTransaction;
|
|
432
|
+
const recalculatedTransactions = await LoanTransaction_model_1.LoanTransaction.aggregate([
|
|
433
|
+
{
|
|
434
|
+
$match: {
|
|
435
|
+
'productId': new mongoose_1.default.Types.ObjectId(initTransaction.productId.toString()),
|
|
436
|
+
'date': { $gte: new Date(initTransaction.date) },
|
|
437
|
+
},
|
|
438
|
+
}, {
|
|
439
|
+
$sort: {
|
|
440
|
+
'date': 1,
|
|
441
|
+
'order': 1,
|
|
442
|
+
'createdAt': 1,
|
|
443
|
+
},
|
|
444
|
+
},
|
|
445
|
+
]);
|
|
446
|
+
for (const transaction of recalculatedTransactions) {
|
|
447
|
+
const totalPostponed = await (0, loan_products_db_1.getPostponedTransactions)(transaction.date, transaction.productId.toString(), true);
|
|
448
|
+
switch (transaction.transactionType) {
|
|
449
|
+
case LoanTransaction_model_1.ELoanTransactionTypes.COLLECTION:
|
|
450
|
+
await this.postponedTransactionsService.cleanRecalculated(transaction._id.toString());
|
|
451
|
+
await this.postponedTransactionsService.createPostponedTransaction(transaction);
|
|
452
|
+
currentFloatedBalance = new decimal_js_1.default(currentFloatedBalance).add(totalPostponed).toNumber();
|
|
453
|
+
break;
|
|
454
|
+
case LoanTransaction_model_1.ELoanTransactionTypes.DISBURSEMENT:
|
|
455
|
+
currentFloatedBalance = new decimal_js_1.default(currentFloatedBalance).add(transaction.amount).add(totalPostponed).toNumber();
|
|
456
|
+
break;
|
|
457
|
+
case LoanTransaction_model_1.ELoanTransactionTypes.ADJUSTMENT:
|
|
458
|
+
currentFloatedBalance = new decimal_js_1.default(currentFloatedBalance).add(transaction.amount).add(totalPostponed).toNumber();
|
|
459
|
+
break;
|
|
460
|
+
}
|
|
461
|
+
await LoanTransaction_model_1.LoanTransaction.findByIdAndUpdate(transaction._id, { floatedBalance: currentFloatedBalance });
|
|
477
462
|
}
|
|
463
|
+
await LoanProducts_model_1.LoanProduct.findByIdAndUpdate(changedTransaction.productId, { isFloatedBalanceActual: true });
|
|
478
464
|
};
|
|
479
465
|
await recalcBalance();
|
|
480
466
|
await recalcFloatedBalance();
|
|
@@ -485,16 +471,15 @@ class LoanTransactionsService {
|
|
|
485
471
|
console.error(`Transaction not found: ${transactionId}`);
|
|
486
472
|
return;
|
|
487
473
|
}
|
|
488
|
-
// Получаем все транзакции, начиная с самой ранней, которую нужно пересчитать
|
|
489
474
|
const earliestTransaction = await LoanTransaction_model_1.LoanTransaction.aggregate([
|
|
490
475
|
{
|
|
491
476
|
$match: {
|
|
492
477
|
productId: startTransaction.productId,
|
|
493
|
-
date: { $lte: new Date(startTransaction.date) }
|
|
494
|
-
}
|
|
478
|
+
date: { $lte: new Date(startTransaction.date) },
|
|
479
|
+
},
|
|
495
480
|
},
|
|
496
481
|
{ $sort: { date: 1, order: 1, createdAt: 1 } },
|
|
497
|
-
{ $limit: 1 }
|
|
482
|
+
{ $limit: 1 },
|
|
498
483
|
]);
|
|
499
484
|
const fromDate = earliestTransaction.length
|
|
500
485
|
? earliestTransaction[0].date
|
|
@@ -503,10 +488,10 @@ class LoanTransactionsService {
|
|
|
503
488
|
{
|
|
504
489
|
$match: {
|
|
505
490
|
productId: startTransaction.productId,
|
|
506
|
-
date: { $gte: fromDate }
|
|
507
|
-
}
|
|
491
|
+
date: { $gte: fromDate },
|
|
492
|
+
},
|
|
508
493
|
},
|
|
509
|
-
{ $sort: { date: 1, order: 1, createdAt: 1 } }
|
|
494
|
+
{ $sort: { date: 1, order: 1, createdAt: 1 } },
|
|
510
495
|
]);
|
|
511
496
|
let balance = 0;
|
|
512
497
|
let floatedBalance = 0;
|
|
@@ -514,11 +499,11 @@ class LoanTransactionsService {
|
|
|
514
499
|
{
|
|
515
500
|
$match: {
|
|
516
501
|
productId: startTransaction.productId,
|
|
517
|
-
date: { $lt: fromDate }
|
|
518
|
-
}
|
|
502
|
+
date: { $lt: fromDate },
|
|
503
|
+
},
|
|
519
504
|
},
|
|
520
505
|
{ $sort: { date: -1, order: -1, createdAt: -1 } },
|
|
521
|
-
{ $limit: 1 }
|
|
506
|
+
{ $limit: 1 },
|
|
522
507
|
]);
|
|
523
508
|
if (prevBeforeStart.length) {
|
|
524
509
|
balance = prevBeforeStart[0].balance || 0;
|
|
@@ -531,8 +516,8 @@ class LoanTransactionsService {
|
|
|
531
516
|
const totalPostponed = await (0, loan_products_db_1.getPostponedTransactions)(tr.date, tr.productId.toString(), true);
|
|
532
517
|
switch (tr.transactionType) {
|
|
533
518
|
case LoanTransaction_model_1.ELoanTransactionTypes.COLLECTION:
|
|
534
|
-
await this.cleanRecalculated(tr._id.toString());
|
|
535
|
-
await this.createPostponedTransaction(tr);
|
|
519
|
+
await this.postponedTransactionsService.cleanRecalculated(tr._id.toString());
|
|
520
|
+
await this.postponedTransactionsService.createPostponedTransaction(tr);
|
|
536
521
|
floatedBalance = new decimal_js_1.default(floatedBalance).add(totalPostponed).toNumber();
|
|
537
522
|
break;
|
|
538
523
|
case LoanTransaction_model_1.ELoanTransactionTypes.DISBURSEMENT:
|
|
@@ -577,24 +562,11 @@ class LoanTransactionsService {
|
|
|
577
562
|
}
|
|
578
563
|
}
|
|
579
564
|
if (nextTransaction.length) {
|
|
580
|
-
|
|
565
|
+
this.recalculateBalance(nextTransaction[0]._id.toString()).catch(console.error);
|
|
581
566
|
}
|
|
582
567
|
const statementDate = this.loanStatementStatusService.getStatementDateForDate(new Date(currentTransaction.date));
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
}
|
|
586
|
-
async createPostponedTransaction(transaction) {
|
|
587
|
-
const currentDay = (0, dayjs_1.default)(new Date(transaction.date)).format('YYYY-MM-DD');
|
|
588
|
-
const workingDate = await this.calendarService.getNextWorkingDay(currentDay);
|
|
589
|
-
const postponedTransaction = {
|
|
590
|
-
postponedToDate: workingDate,
|
|
591
|
-
transactionId: new mongoose_1.default.Types.ObjectId(String(transaction._id)),
|
|
592
|
-
productId: new mongoose_1.default.Types.ObjectId(String(transaction.productId)),
|
|
593
|
-
};
|
|
594
|
-
await PostponedTransactions_model_1.PostponedTransaction.create(postponedTransaction);
|
|
595
|
-
}
|
|
596
|
-
async cleanRecalculated(transactionId) {
|
|
597
|
-
await PostponedTransactions_model_1.PostponedTransaction.deleteMany({ transactionId });
|
|
568
|
+
this.loanStatementStatusService.updateStatementStatus(currentTransaction.productId.toString(), statementDate, false).catch(console.error);
|
|
569
|
+
this.termLoanService.setTermLoanExpected(currentTransaction.productId.toString()).catch(console.error);
|
|
598
570
|
}
|
|
599
571
|
async deleteLoanTransactionFile(transactionFileId, userId) {
|
|
600
572
|
const foundFile = await LoanTransactionFile_model_1.LoanTransactionFileModel.findById(transactionFileId).lean();
|