Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#3260 - CAS Integration 3A - Create new Supplier and Site - CAS API Call #3804

Merged
merged 18 commits into from
Oct 21, 2024

Conversation

andrewsignori-aot
Copy link
Collaborator

@andrewsignori-aot andrewsignori-aot commented Oct 17, 2024

Main Changes

  • The current process is now segregated into different classes (called processors) that are responsible for taking care of the below scenarios.
    • CASActiveSupplierNotFoundProcessor: 🆕
      • Supplier does not exist on CAS;
      • CAS API should be called to create supplier and site;
      • Student CAS supplier should be updated.
    • CASPreValidationsProcessor: 🆕
      • Given name or not a Canadian address.
      • Update the student supplier for manual intervention.
    • CASActiveSupplierFoundProcessor: (🆕 refactored)
      • Supplier found on CAS
      • Student CAS supplier should be updated.

Address match

Error handling

API call properly reports errors using HTTP Status 400 and adding meaningful error messages. Please see below samples.
These error messages were used to define the max length validation for the submitted data.

  • [0069] Length of field SupplierName exceeded. Maximum length is 80.
  • [0034] SIN is already in use.
  • [0069] Length of field AddressLine1 exceeded. Maximum length is 35.

GetSupplier 404

The GetSupplier method from CAS API does not return a 404 error when no supplier is found as stated in the documentation.
The method seems to be implemented as a search and it will just return an empty array if no items were found.

{
    "items": [],
    "hasMore": false,
    "limit": 0,
    "offset": 0,
    "count": 0,
}

Secondary PR changes

  • Created a small helper to identify if the student's address is from Canada. The idea is to avoid confusion about which property to use and how the value is set on DB. This is the reason the method receives the AddressInfo itself which contains country and selectedCountry properties.
  • New CAS mocks added to allow the CAS responses mocks.

New E2E Tests

  • Should update CAS supplier table to manual intervention when student does not have a first name.
  • Should update CAS supplier table to manual intervention when student address is not from Canada.
  • Should create a new supplier and site on CAS and update CAS suppliers table when the student was not found on CAS and the request to create the supplier and site was successful.

Log samples

[2024-10-17 22:53:31]--INFO: Log details
[2024-10-17 22:53:31]----INFO: Log details
[2024-10-17 22:53:31]----INFO: Logging on CAS.
[2024-10-17 22:53:31]----INFO: Logon successful.
[2024-10-17 22:53:31]------INFO: Log details
[2024-10-17 22:53:31]------INFO: Processing student CAS supplier ID: 69.
[2024-10-17 22:53:31]------INFO: CAS evaluation result status: NotFound.
[2024-10-17 22:53:31]------INFO: No active CAS supplier found. Reason: Supplier not found.
[2024-10-17 22:53:31]------INFO: Created supplier and site on CAS.
[2024-10-17 22:53:31]------INFO: Updated CAS supplier and site for the student.
[2024-10-17 22:53:31]INFO: CAS supplier integration executed.
[2024-10-17 23:04:38]INFO: Log details
[2024-10-17 23:04:38]INFO: Executing CAS supplier integration...
[2024-10-17 23:04:38]INFO: Found 1 records to be updated.
[2024-10-17 23:04:38]--INFO: Log details
[2024-10-17 23:04:38]----INFO: Log details
[2024-10-17 23:04:38]----INFO: Logging on CAS.
[2024-10-17 23:04:38]----INFO: Logon successful.
[2024-10-17 23:04:38]------INFO: Log details
[2024-10-17 23:04:38]------INFO: Processing student CAS supplier ID: 86.
[2024-10-17 23:04:38]------INFO: CAS evaluation result status: PreValidationsFailed.
[2024-10-17 23:04:38]------WARN: Not possible to retrieve CAS supplier information because some pre-validations were not fulfilled. Reason(s): Non-Canadian address.
[2024-10-17 23:04:38]------INFO: Updated CAS supplier for manual intervention.
[2024-10-17 23:04:38]INFO: CAS supplier integration executed.
[2024-10-17 22:55:57]INFO: Log details
[2024-10-17 22:55:57]INFO: Executing CAS supplier integration...
[2024-10-17 22:55:57]INFO: Found 1 records to be updated.
[2024-10-17 22:55:57]--INFO: Log details
[2024-10-17 22:55:57]----INFO: Log details
[2024-10-17 22:55:57]----INFO: Logging on CAS.
[2024-10-17 22:55:57]----INFO: Logon successful.
[2024-10-17 22:55:57]------INFO: Log details
[2024-10-17 22:55:57]------INFO: Processing student CAS supplier ID: 74.
[2024-10-17 22:55:57]------INFO: CAS evaluation result status: ActiveSupplierFound.
[2024-10-17 22:55:57]------INFO: Active CAS supplier found.
[2024-10-17 22:55:57]------INFO: Updated CAS supplier for the student.
[2024-10-17 22:55:57]INFO: CAS supplier integration executed.

TODO

  • Adjust the scheduler cron expression.
  • Add more E2E tests.
  • Run in parallel.
  • If some error is present throw in the scheduler to allow it to be retried.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes related to this PR start at line 50.
The file was renamed.

@andrewsignori-aot andrewsignori-aot marked this pull request as ready for review October 18, 2024 20:06
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

const auth = await this.casService.logon();
summary.info("Logon successful.");
suppliersUpdated = await this.requestCASAndUpdateSuppliers(
suppliersUpdated = await this.processSuppliers(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The silent failing is also happening inside this.processSuppliers.

Does this method need to fail silently w/o throwing error?

Copy link
Collaborator Author

@andrewsignori-aot andrewsignori-aot Oct 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The below AC is not implemented yet.
"If some error is present throw in the scheduler to allow it to be retried."
The idea is to inspect the summary (as it is already done in getSuccessMessageWithAttentionCheck) and throw an error if any error log message is present. Throwing an exception from here or from there would result in the same.
I added it now to the "TODOs" in the PR description.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the idea is that the failure will be caught and then logged for info purpose as summary.error and then in the next run of the scheduler, the failed cas suppliers will be attempted again.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If some error is logged to the summary we will throw to allow the scheduler to retry immediately.
When we have the permanent errors implemented, those should be probably logged as warnings because they will be part of the "business valid scenarios".

@@ -38,10 +50,10 @@ export class CASSupplierIntegrationService {
const summary = new ProcessSummary();
parentProcessSummary.children(summary);
try {
summary.info("Logging on CAS...");
summary.info("Logging on CAS.");
const auth = await this.casService.logon();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not related to PR and asking for my understanding, How long is a logon valid?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per the docs, 1 hour (3600 seconds).

Comment on lines +81 to +95
{
supplierNumber: result.response.supplierNumber,
supplierName: result.submittedData.SupplierName,
status: "ACTIVE",
lastUpdated: now,
supplierAddress: {
supplierSiteCode: result.response.supplierSiteCode,
addressLine1: submittedAddress.AddressLine1,
city: submittedAddress.City,
provinceState: submittedAddress.Province,
country: submittedAddress.Country,
postalCode: submittedAddress.PostalCode,
status: "ACTIVE",
lastUpdated: now,
},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about supplierProtected and siteProtected in the update?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean setting them explicitly to null?
Since the supplier was not found, it will be a new supplier and site. These properties should never exist or be created for a new supplier and site.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These properties should never exist or be created for a new supplier and site. - Ah, is it? I was under the impression that it is set during new supplier and site creation.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are legacy properties. As far as I know, they only exist due to some SFAS requirement.
Either way, we do not have any direction about setting them.

{
id: casSupplier.id,
},
{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The update happening for found and not found is identical. Can we have a common method to be re-used for the update?

Copy link
Collaborator Author

@andrewsignori-aot andrewsignori-aot Oct 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean the below part is identical? I would prefer to leave as it is.

image

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My point was conversion of CAS Supplier and CAS Site to SIMS Supplier and SIMS supplier address(and then update). May be something in one of the upcoming CAS tickets.

Comment on lines +47 to +52
if (evaluationResult.status !== CASEvaluationStatus.NotFound) {
throw new Error("Incorrect CAS evaluation result processor selected.");
}
summary.info(
`No active CAS supplier found. Reason: ${evaluationResult.reason}.`,
);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 for this info in all the processors.

@dheepak-aot
Copy link
Collaborator

Great Job @andrewsignori-aot. Thanks for trying it make it streamlined for any upcoming CAS updates.
Please have a look at the comments.

modifier: { id: systemUsersService.systemUser.id },
});
// Ensure updatedAt was updated.
expect(updateCASSupplier.updatedAt.getTime()).toBeGreaterThan(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

// Arrange
const referenceDate = new Date();
const savedCASSupplier = await saveFakeCASSupplier(db);
// Configure CAS mock to return em empty result for the GetSupplier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: an

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

Copy link
Collaborator

@sh16011993 sh16011993 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work @andrewsignori-aot 👍 Thank You for the walkthrough of your PR.

Copy link

Copy link

Backend Unit Tests Coverage Report

Totals Coverage
Statements: 22.42% ( 3632 / 16201 )
Methods: 9.99% ( 201 / 2013 )
Lines: 25.8% ( 3158 / 12238 )
Branches: 14% ( 273 / 1950 )

Copy link

E2E Workflow Workers Coverage Report

Totals Coverage
Statements: 58.64% ( 509 / 868 )
Methods: 52.88% ( 55 / 104 )
Lines: 62.27% ( 411 / 660 )
Branches: 41.35% ( 43 / 104 )

Copy link

E2E Queue Consumers Coverage Report

Totals Coverage
Statements: 83.21% ( 1160 / 1394 )
Methods: 83.94% ( 115 / 137 )
Lines: 84.26% ( 990 / 1175 )
Branches: 67.07% ( 55 / 82 )

Copy link

E2E SIMS API Coverage Report

Totals Coverage
Statements: 66.01% ( 5571 / 8439 )
Methods: 63.3% ( 683 / 1079 )
Lines: 70.12% ( 4401 / 6276 )
Branches: 44.93% ( 487 / 1084 )

Copy link
Collaborator

@dheepak-aot dheepak-aot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work. Thanks for doing the changes. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants