-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathassert-life-time-maximum-full-time-step.ts
146 lines (143 loc) · 5.92 KB
/
assert-life-time-maximum-full-time-step.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import { Injectable } from "@nestjs/common";
import { round } from "@sims/utilities";
import { EntityManager } from "typeorm";
import {
DisbursementScheduleSharedService,
RestrictionCode,
SFASApplicationService,
StudentRestrictionSharedService,
SystemUsersService,
} from "@sims/services";
import {
DisbursementValue,
DisbursementValueType,
StudentRestriction,
} from "@sims/sims-db";
import { ECertProcessStep } from "./e-cert-steps-models";
import { ProcessSummary } from "@sims/utilities/logger";
import { EligibleECertDisbursement } from "../disbursement-schedule.models";
import { ECertGenerationService } from "../e-cert-generation.service";
import { getRestrictionByCode } from "./e-cert-steps-utils";
/**
* Check if the student is reaching the full-time BCSL maximum.
*/
@Injectable()
export class AssertLifeTimeMaximumFullTimeStep implements ECertProcessStep {
constructor(
private readonly studentRestrictionSharedService: StudentRestrictionSharedService,
private readonly systemUsersService: SystemUsersService,
private readonly sfasApplicationService: SFASApplicationService,
private readonly disbursementScheduleSharedService: DisbursementScheduleSharedService,
private readonly eCertGenerationService: ECertGenerationService,
) {}
/**
* Check if BCSL is part of the disbursement and ensure that, if BCSL maximum is reached,
* the award will be adjusted and a restriction will be created.
* @param eCertDisbursement eligible disbursement to be potentially added to an e-Cert.
* @param entityManager used to execute the commands in the same transaction.
* @param log cumulative log summary.
*/
async executeStep(
eCertDisbursement: EligibleECertDisbursement,
entityManager: EntityManager,
log: ProcessSummary,
): Promise<boolean> {
log.info("Checking life time maximums for BC loans.");
if (getRestrictionByCode(eCertDisbursement, RestrictionCode.BCLM)) {
log.info(
`Student already has a ${RestrictionCode.BCLM} restriction, hence skipping the check.`,
);
return true;
}
// Check if the BC Loan is present in the awards to be disbursed.
const bcLoan = eCertDisbursement.disbursement.disbursementValues.find(
(award) => award.valueType === DisbursementValueType.BCLoan,
);
if (!bcLoan?.valueAmount) {
log.info(
`${DisbursementValueType.BCLoan} award not found or there is no amount to be disbursed, hence skipping the check.`,
);
return true;
}
// Check if a new restriction should be created and award adjusted.
const newRestrictionCreated =
await this.checkLifeTimeMaximumAndAddStudentRestriction(
eCertDisbursement,
bcLoan,
entityManager,
);
if (newRestrictionCreated) {
// If a new restriction was created refresh the active restrictions list.
const activeRestrictions =
await this.eCertGenerationService.getStudentActiveRestrictions(
eCertDisbursement.studentId,
entityManager,
);
eCertDisbursement.refreshActiveStudentRestrictions(activeRestrictions);
log.info(
`New ${RestrictionCode.BCLM} restriction was added to the student account.`,
);
} else {
log.info(
`No ${RestrictionCode.BCLM} restriction was created at this time.`,
);
}
return true;
}
/**
* Check if the student hits/exceeds the life time maximum for the BCSL Award.
* If they hits/exceeds the life time maximum, then the award is reduced so the
* student hits the exact maximum value and the student restriction
* {@link RestrictionCode.BCLM} is placed for the student.
* @param eCertDisbursement student disbursement that is part of one e-Cert.
* @param disbursementValue award value to be verified.
* @param entityManager used to execute the commands in the same transaction.
* @returns true if a new restriction was created, otherwise false.
*/
private async checkLifeTimeMaximumAndAddStudentRestriction(
eCertDisbursement: EligibleECertDisbursement,
disbursementValue: DisbursementValue,
entityManager: EntityManager,
): Promise<boolean> {
// Get totals including legacy system.
const [totalLegacyBCSLAmount, totalDisbursedBCSLAmount] = await Promise.all(
[
this.sfasApplicationService.totalLegacyBCSLAmount(
eCertDisbursement.studentId,
),
this.disbursementScheduleSharedService.totalDisbursedBCSLAmount(
eCertDisbursement.studentId,
),
],
);
const totalLifeTimeAmount =
totalLegacyBCSLAmount +
totalDisbursedBCSLAmount +
disbursementValue.effectiveAmount;
if (totalLifeTimeAmount < eCertDisbursement.maxLifetimeBCLoanAmount) {
// The limit was not reached.
return false;
}
// Amount subtracted when lifetime maximum is reached.
const amountSubtracted =
totalLifeTimeAmount - eCertDisbursement.maxLifetimeBCLoanAmount;
// Ideally disbursementValue.effectiveAmount should be greater or equal to amountSubtracted.
// The flow will not reach here if the ministry ignore the restriction for the previous
// disbursement/application and money went out to the student, even though they reach the maximum.
const newEffectiveAmount =
disbursementValue.effectiveAmount - amountSubtracted;
// Create RestrictionCode.BCLM restriction when lifetime maximum is reached/exceeded.
const bclmRestriction =
await this.studentRestrictionSharedService.createRestrictionToSave(
eCertDisbursement.studentId,
RestrictionCode.BCLM,
this.systemUsersService.systemUser.id,
eCertDisbursement.applicationId,
);
await entityManager.getRepository(StudentRestriction).save(bclmRestriction);
disbursementValue.effectiveAmount = round(newEffectiveAmount);
disbursementValue.restrictionAmountSubtracted = amountSubtracted;
disbursementValue.restrictionSubtracted = bclmRestriction.restriction;
return true;
}
}