gemcap-be-common 1.3.98 → 1.3.99

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gemcap-be-common",
3
- "version": "1.3.98",
3
+ "version": "1.3.99",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -45,7 +45,7 @@ export declare class ComplianceBorrowersService {
45
45
  };
46
46
  };
47
47
  getFullComplianceBorrowerById(complianceBorrowerId: any): Promise<any>;
48
- getAllBorrowersShortened(userAccess: any): Promise<(Pick<IComplianceBorrowerDocument, "items" | "borrower" | "fundingStatus"> | {
48
+ getAllBorrowersShortened(userAccess: any): Promise<(Pick<IComplianceBorrowerDocument, "borrower" | "fundingStatus" | "items"> | {
49
49
  items: {
50
50
  instances: any[];
51
51
  item: import("../models/ComplianceItem.model").IComplianceItemDocument;
@@ -110,6 +110,7 @@ export declare class LoanTransactionsService {
110
110
  updateLoanTransaction(transaction: ILoanTransactionDoc): Promise<void>;
111
111
  saveLoanTransaction(transaction: Partial<ILoanTransactionWithId>): Promise<ILoanTransactionDoc>;
112
112
  recalculateProduct(productId: string): Promise<void>;
113
+ recalculateBalanceLegacy(transactionId: string): Promise<void>;
113
114
  recalculateBalance(transactionId: string): Promise<void>;
114
115
  deleteLoanTransaction(transactionId: string, updateLoanPayment: boolean, userId?: any): Promise<void>;
115
116
  createPostponedTransaction(transaction: ILoanTransactionDoc): Promise<void>;
@@ -9,7 +9,6 @@ const mongoose_1 = __importDefault(require("mongoose"));
9
9
  const dayjs_1 = __importDefault(require("dayjs"));
10
10
  const decimal_js_1 = __importDefault(require("decimal.js"));
11
11
  const date_helper_1 = require("../helpers/date.helper");
12
- const numbers_helper_1 = require("../helpers/numbers.helper");
13
12
  const common_helper_1 = require("../helpers/common.helper");
14
13
  const BBCDate_model_1 = require("../models/BBCDate.model");
15
14
  const loan_types_enum_1 = require("../enums/loan-types.enum");
@@ -339,132 +338,226 @@ class LoanTransactionsService {
339
338
  await this.recalculateBalance(firstTransactions[0]._id.toString());
340
339
  }
341
340
  }
342
- async recalculateBalance(transactionId) {
341
+ async recalculateBalanceLegacy(transactionId) {
343
342
  const changedTransaction = await LoanTransaction_model_1.LoanTransaction.findById(transactionId);
344
343
  if (!changedTransaction) {
345
344
  console.error(`no transactions with id ${transactionId}`);
346
345
  return;
347
346
  }
348
- setTimeout(async () => {
349
- await LoanProducts_model_1.LoanProduct.findByIdAndUpdate(changedTransaction.productId, { isBalanceActual: false });
350
- const previousTransaction = await LoanTransaction_model_1.LoanTransaction.aggregate([
351
- {
352
- $match: {
353
- 'productId': new mongoose_1.default.Types.ObjectId(changedTransaction.productId.toString()),
354
- 'date': { $lt: new Date(changedTransaction.date) },
355
- },
356
- }, {
357
- $sort: {
358
- 'date': -1,
359
- 'order': -1,
360
- 'createdAt': -1,
361
- },
362
- }, {
363
- $limit: 1,
364
- },
365
- ]);
366
- let currentBalance = previousTransaction.length
367
- ? previousTransaction[0].balance ?? 0
368
- : 0;
369
- const recalculatedTransactions = await LoanTransaction_model_1.LoanTransaction.aggregate([
370
- {
371
- $match: {
372
- 'productId': new mongoose_1.default.Types.ObjectId(changedTransaction.productId.toString()),
373
- 'date': { $gte: new Date(changedTransaction.date) },
374
- },
375
- }, {
376
- $sort: {
377
- 'date': 1,
378
- 'order': 1,
379
- 'createdAt': 1,
380
- },
381
- },
382
- ]);
383
- for (const transaction of recalculatedTransactions) {
384
- currentBalance = new decimal_js_1.default(currentBalance).add(transaction.amount).toNumber();
385
- await LoanTransaction_model_1.LoanTransaction.findByIdAndUpdate(transaction._id, { balance: currentBalance });
347
+ const recalcBalance = async () => {
348
+ const session = await mongoose_1.default.startSession();
349
+ try {
350
+ await session.withTransaction(async () => {
351
+ await LoanProducts_model_1.LoanProduct.findByIdAndUpdate(changedTransaction.productId, { isBalanceActual: false });
352
+ const previousTransaction = await LoanTransaction_model_1.LoanTransaction.aggregate([
353
+ {
354
+ $match: {
355
+ 'productId': new mongoose_1.default.Types.ObjectId(changedTransaction.productId.toString()),
356
+ 'date': { $lt: new Date(changedTransaction.date) },
357
+ },
358
+ }, {
359
+ $sort: {
360
+ 'date': -1,
361
+ 'order': -1,
362
+ 'createdAt': -1,
363
+ },
364
+ }, {
365
+ $limit: 1,
366
+ },
367
+ ]);
368
+ let currentBalance = previousTransaction.length
369
+ ? previousTransaction[0].balance ?? 0
370
+ : 0;
371
+ const recalculatedTransactions = await LoanTransaction_model_1.LoanTransaction.aggregate([
372
+ {
373
+ $match: {
374
+ 'productId': new mongoose_1.default.Types.ObjectId(changedTransaction.productId.toString()),
375
+ 'date': { $gte: new Date(changedTransaction.date) },
376
+ },
377
+ }, {
378
+ $sort: {
379
+ 'date': 1,
380
+ 'order': 1,
381
+ 'createdAt': 1,
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
+ });
386
391
  }
387
- await LoanProducts_model_1.LoanProduct.findByIdAndUpdate(changedTransaction.productId, { isBalanceActual: true });
388
- });
389
- setTimeout(async () => {
390
- await LoanProducts_model_1.LoanProduct.findByIdAndUpdate(changedTransaction.productId, { isFloatedBalanceActual: false });
391
- const previousEqualBalancesTransaction = await LoanTransaction_model_1.LoanTransaction.aggregate([
392
- {
393
- $match: {
394
- 'productId': new mongoose_1.default.Types.ObjectId(changedTransaction.productId.toString()),
395
- 'date': { $lt: new Date(changedTransaction.date) },
396
- $expr: { $eq: ['$balance', '$floatedBalance'] },
392
+ finally {
393
+ await session.endSession();
394
+ }
395
+ };
396
+ const recalcFloatedBalance = async () => {
397
+ const session = await mongoose_1.default.startSession();
398
+ try {
399
+ await session.withTransaction(async () => {
400
+ await LoanProducts_model_1.LoanProduct.findByIdAndUpdate(changedTransaction.productId, { isFloatedBalanceActual: false });
401
+ const previousEqualBalancesTransaction = await LoanTransaction_model_1.LoanTransaction.aggregate([
402
+ {
403
+ $match: {
404
+ 'productId': new mongoose_1.default.Types.ObjectId(changedTransaction.productId.toString()),
405
+ 'date': { $lt: new Date(changedTransaction.date) },
406
+ $expr: { $eq: ['$balance', '$floatedBalance'] },
407
+ },
408
+ }, {
409
+ $sort: {
410
+ 'date': -1,
411
+ 'order': -1,
412
+ 'createdAt': -1,
413
+ },
414
+ }, {
415
+ $limit: 1,
416
+ },
417
+ ]);
418
+ let currentFloatedBalance = 0;
419
+ if (previousEqualBalancesTransaction.length) {
420
+ const previousTransaction = await LoanTransaction_model_1.LoanTransaction.aggregate([
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
+ },
453
+ },
454
+ ]);
455
+ for (const transaction of recalculatedTransactions) {
456
+ const totalPostponed = await (0, loan_products_db_1.getPostponedTransactions)(transaction.date, transaction.productId.toString(), true);
457
+ switch (transaction.transactionType) {
458
+ case LoanTransaction_model_1.ELoanTransactionTypes.COLLECTION:
459
+ await this.cleanRecalculated(transaction._id.toString());
460
+ await this.createPostponedTransaction(transaction);
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
+ });
474
+ }
475
+ finally {
476
+ await session.endSession();
477
+ }
478
+ };
479
+ await recalcBalance();
480
+ await recalcFloatedBalance();
481
+ }
482
+ async recalculateBalance(transactionId) {
483
+ const startTransaction = await LoanTransaction_model_1.LoanTransaction.findById(transactionId).lean();
484
+ if (!startTransaction) {
485
+ console.error(`Transaction not found: ${transactionId}`);
486
+ return;
487
+ }
488
+ const session = await mongoose_1.default.startSession();
489
+ try {
490
+ await session.withTransaction(async () => {
491
+ // Получаем все транзакции, начиная с самой ранней, которую нужно пересчитать
492
+ const earliestTransaction = await LoanTransaction_model_1.LoanTransaction.aggregate([
493
+ {
494
+ $match: {
495
+ productId: startTransaction.productId,
496
+ date: { $lte: new Date(startTransaction.date) }
497
+ }
397
498
  },
398
- }, {
399
- $sort: {
400
- 'date': 1,
401
- 'order': 1,
402
- 'createdAt': 1,
499
+ { $sort: { date: 1, order: 1, createdAt: 1 } },
500
+ { $limit: 1 }
501
+ ]);
502
+ const fromDate = earliestTransaction.length
503
+ ? earliestTransaction[0].date
504
+ : startTransaction.date;
505
+ const allTransactions = await LoanTransaction_model_1.LoanTransaction.aggregate([
506
+ {
507
+ $match: {
508
+ productId: startTransaction.productId,
509
+ date: { $gte: fromDate }
510
+ }
403
511
  },
404
- }, {
405
- $limit: 1,
406
- },
407
- ]);
408
- let currentFloatedBalance = 0;
409
- if (previousEqualBalancesTransaction.length) {
410
- const previousTransaction = await LoanTransaction_model_1.LoanTransaction.aggregate([
512
+ { $sort: { date: 1, order: 1, createdAt: 1 } }
513
+ ]);
514
+ let balance = 0;
515
+ let floatedBalance = 0;
516
+ // Найдём стартовые значения
517
+ const prevBeforeStart = await LoanTransaction_model_1.LoanTransaction.aggregate([
411
518
  {
412
519
  $match: {
413
- 'productId': new mongoose_1.default.Types.ObjectId(previousEqualBalancesTransaction[0].productId.toString()),
414
- 'date': { $lt: new Date(previousEqualBalancesTransaction[0].date) },
415
- },
416
- }, {
417
- $sort: {
418
- 'date': -1,
419
- 'order': -1,
420
- 'createdAt': -1,
421
- },
422
- }, {
423
- $limit: 1,
520
+ productId: startTransaction.productId,
521
+ date: { $lt: fromDate }
522
+ }
424
523
  },
524
+ { $sort: { date: -1, order: -1, createdAt: -1 } },
525
+ { $limit: 1 }
425
526
  ]);
426
- if (previousTransaction.length) {
427
- currentFloatedBalance = previousTransaction[0].floatedBalance;
527
+ if (prevBeforeStart.length) {
528
+ balance = prevBeforeStart[0].balance || 0;
529
+ floatedBalance = prevBeforeStart[0].floatedBalance || 0;
428
530
  }
429
- }
430
- const initTransaction = previousEqualBalancesTransaction.length ? previousEqualBalancesTransaction[0] : changedTransaction;
431
- const recalculatedTransactions = await LoanTransaction_model_1.LoanTransaction.aggregate([
432
- {
433
- $match: {
434
- 'productId': new mongoose_1.default.Types.ObjectId(initTransaction.productId.toString()),
435
- 'date': { $gte: new Date(initTransaction.date) },
436
- },
437
- }, {
438
- $sort: {
439
- 'date': 1,
440
- 'order': 1,
441
- 'createdAt': 1,
442
- },
443
- },
444
- ]);
445
- for (const transaction of recalculatedTransactions) {
446
- const totalPostponed = await (0, loan_products_db_1.getPostponedTransactions)(transaction.date, transaction.productId.toString(), true);
447
- switch (transaction.transactionType) {
448
- case LoanTransaction_model_1.ELoanTransactionTypes.COLLECTION:
449
- await this.cleanRecalculated(transaction._id.toString());
450
- await this.createPostponedTransaction(transaction);
451
- currentFloatedBalance = (0, numbers_helper_1.roundToXDigits)(currentFloatedBalance + totalPostponed);
452
- break;
453
- case LoanTransaction_model_1.ELoanTransactionTypes.DISBURSEMENT:
454
- currentFloatedBalance = (0, numbers_helper_1.roundToXDigits)(currentFloatedBalance + transaction.amount + totalPostponed);
455
- break;
456
- case LoanTransaction_model_1.ELoanTransactionTypes.ADJUSTMENT:
457
- currentFloatedBalance = (0, numbers_helper_1.roundToXDigits)(currentFloatedBalance + transaction.amount + totalPostponed);
458
- break;
531
+ // Один проход для расчёта balance и floatedBalance
532
+ for (const tr of allTransactions) {
533
+ // Пересчёт обычного баланса
534
+ balance = new decimal_js_1.default(balance).add(tr.amount).toNumber();
535
+ // Пересчёт floatedBalance
536
+ const totalPostponed = await (0, loan_products_db_1.getPostponedTransactions)(tr.date, tr.productId.toString(), true);
537
+ switch (tr.transactionType) {
538
+ case LoanTransaction_model_1.ELoanTransactionTypes.COLLECTION:
539
+ await this.cleanRecalculated(tr._id.toString());
540
+ await this.createPostponedTransaction(tr);
541
+ floatedBalance = new decimal_js_1.default(floatedBalance).add(totalPostponed).toNumber();
542
+ break;
543
+ case LoanTransaction_model_1.ELoanTransactionTypes.DISBURSEMENT:
544
+ case LoanTransaction_model_1.ELoanTransactionTypes.ADJUSTMENT:
545
+ floatedBalance = new decimal_js_1.default(floatedBalance).add(tr.amount).add(totalPostponed).toNumber();
546
+ break;
547
+ }
548
+ await LoanTransaction_model_1.LoanTransaction.updateOne({ _id: tr._id }, { balance, floatedBalance }, { session });
459
549
  }
460
- await LoanTransaction_model_1.LoanTransaction.findByIdAndUpdate(transaction._id, { floatedBalance: currentFloatedBalance });
461
- }
462
- await LoanProducts_model_1.LoanProduct.findByIdAndUpdate(changedTransaction.productId, { isFloatedBalanceActual: true });
463
- }, 1000);
550
+ await LoanProducts_model_1.LoanProduct.updateOne({ _id: startTransaction.productId }, { isBalanceActual: true, isFloatedBalanceActual: true }, { session });
551
+ });
552
+ }
553
+ finally {
554
+ await session.endSession();
555
+ }
464
556
  }
465
557
  async deleteLoanTransaction(transactionId, updateLoanPayment, userId = null) {
466
558
  const currentTransaction = await LoanTransaction_model_1.LoanTransaction.findById(transactionId).lean();
467
559
  if (!currentTransaction) {
560
+ console.error(`no transactions with id ${transactionId}`);
468
561
  return;
469
562
  }
470
563
  const nextTransaction = await LoanTransaction_model_1.LoanTransaction.aggregate([