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

#1786 - Enable Search Student for Institutions - part 1 #1857

Merged
merged 20 commits into from
Apr 6, 2023

Conversation

andrepestana-aot
Copy link
Collaborator

@andrepestana-aot andrepestana-aot commented Apr 1, 2023

In this PR

  • moved SearchStudents.vue to SearchStudentsCommon.vue to reuse the same UI for institutions and ministry users;
  • added link for BC Public institutions;
  • created API to search students by institutions;

I will create another PR to:

  • create e2e tests
  • fix bug on UI (responsiveness)
  • check an issue with the search when the user application has any pending exception. In that case the location_id is not defined and the user won't be found by the institution.

BC Public Institution

image

Other Institutions

image

@andrepestana-aot andrepestana-aot changed the title Draft #1786 - Enable Search Student for Institutions - part 1 Apr 4, 2023
@andrepestana-aot andrepestana-aot self-assigned this Apr 4, 2023
@andrepestana-aot andrepestana-aot marked this pull request as ready for review April 4, 2023 22:25
@andrepestana-aot andrepestana-aot added User Story Institution Institution Features labels Apr 4, 2023
@AllowAuthorizedParty(AuthorizedParties.institution)
@Controller("student")
@ApiTags(`${ClientTypeBaseRoute.Institution}-student`)
@Injectable()
Copy link
Collaborator

@guru-aot guru-aot Apr 5, 2023

Choose a reason for hiding this comment

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

Do we need an injectable here?

Copy link
Collaborator

Choose a reason for hiding this comment

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

When @Controller is used, @Injectable is not required.

Copy link
Contributor

Choose a reason for hiding this comment

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

looks like its used in quite a few controllers, here are few
image
image
image

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I just moved this code, it already this way. Thanks!

Copy link
Collaborator

Choose a reason for hiding this comment

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

@Controller does not require the @Injectable because they are not injected anywhere. They were probably added by mistake someday and kept being added. Anyone that finds one can have them removed or create a PR to remove them all.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I just moved this code, it already this way. Thanks!

I did not get the part that states that this code was "moved". This is a brand-new file, right?
If the file is new and the code was copied, the statement "it already this way" does not seem accurate, IMO.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It was already that way in the other file, I just moved the code from there to this one. I'm not saying that I should not have changed it and made it right. Sorry!

* @param institutionId institution id.
* @returns whether the institution type is public.
*/
async isBCPublicInstitution(institutionId: number): Promise<boolean> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Just a suggestion, we already have a method to check if the institution is private, which has one reference. Can we just create a single method that return either the institution is INSTITUTION_TYPE_BC_PRIVATE or INSTITUTION_TYPE_BC_PUBLIC?. Thoughts @ann-aot @andrewsignori-aot @sh16011993 @dheepak-aot

Copy link
Collaborator

Choose a reason for hiding this comment

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

I see the point @guru-aot.
Maybe we could create read-only properties a the entity model that will do the check based on the constants INSTITUTION_TYPE_BC_PRIVATE and INSTITUTION_TYPE_BC_PUBLIC.
IMO this is something that can be considered an entity-level concern. Would be like an emulation of a DB computed property.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I agree that it should just be a entity level concern.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@guru-aot I get what you are saying, but to have a single method returning private or public, we need to have a thrid category to pull all these institution types.

image

Copy link
Collaborator

Choose a reason for hiding this comment

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

I get the point team, I was just talking about combining 2 methods and returning a single value either public or private. I guess its going way out of the scope of this PR. Pausing the discussion for now.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@guru-aot I am exactly trying to comprehend your idea. for e.g. if there is a method called checkIfPrivateOrPublic(): Private | Public, what will it return if the institution type is International? let me know if I am missing somehthing.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@guru-aot feel free to pause the discussion, from your end, please leave the comment open.
@andrepestana-aot I believe that this method will no longer be needed because we will build the decorator in the future.
If it is still needed let's move it to the entity model alongside the isBCPrivate.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I removed the method isBCPublicInstitution

.leftJoin("studentAssessment.offering", "offering")
.leftJoin("offering.institutionLocation", "offeringLocation")
.leftJoin("offeringLocation.institution", "offeringInstitution")

Copy link
Collaborator

@guru-aot guru-aot Apr 5, 2023

Choose a reason for hiding this comment

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

please remove empty line here and above.

* lastName, appNumber or sin.
* @returns list of students.
*/
async searchStudentApplicationForInstitution(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Cant we reuse the existing query searchStudentApplication to use the instituion id as an optional parameter and return?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't like the idea of doing that because it would make a simple thing like a query to a more complex method with conditions that will be harder to maintain. Thoughts @ann-aot @dheepak-aot @andrewsignori-aot @sh16011993 ?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe I am wrong and I did not tested it, but would the change be something about moving the inner/left and one where inside an if like below?

    if (institutionId) {
      searchQuery
        .innerJoin("application.location", "pirLocation")
        .innerJoin("pirLocation.institution", "pirInstitution")
        .andWhere(
          "(offeringInstitution.id = :institutionId or pirInstitution.id = :institutionId)",
          { institutionId },
        );
    }

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ok. Changed.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I noticed the if (institutionId) twice in the method. Was it because the proposed code on the comment didn't work or because it looks cleaner?

@@ -93,27 +93,27 @@ export class UpdateStudentAPIInDTO
/**
* Student AEST search parameters.
Copy link
Contributor

Choose a reason for hiding this comment

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

pls update the comment too

StudentSearchAPIInDTO,
SearchStudentAPIOutDTO,
} from "./models/student.dto";

Copy link
Contributor

Choose a reason for hiding this comment

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

pls remove the extra line

userToken.authorizations.institutionId,
searchCriteria,
);
return searchStudentApplications.map((eachStudent: Student) => ({
Copy link
Collaborator

Choose a reason for hiding this comment

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

If AEST and student are sharing the same DTO, the "map" logic can be centralized also on student.controller.service.ts.

"application.student.id = student.id",
)

.innerJoin("application.location", "pirLocation")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe it would be safe to use left join here since we still are not saving the PIR location right on submission.
Even if we start saving, I believe that it would be better to not rely on it using the INNER.


/**
* Search students based on the search criteria.
* TODO add decorator to restrict to BC Public institutions.
Copy link
Collaborator

Choose a reason for hiding this comment

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

👍

color="primary"
class="p-button-raised"
data-cy="viewStudent"
@click="$emit('goToStudentView', slotProps.data.id)"
Copy link
Collaborator

Choose a reason for hiding this comment

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

As an alternate approach because the params are same between both routes, the component can receive a a route prop and do the navigation here.
The benefit it is avoid the emit. <search-students :view-student-route="InstitutionRoutesConst.STUDENT_PROFILE">

Just a suggestion.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, there are many ways of doing that. I'm following #1857 (review)

"application",
"application.student.id = student.id",
)
.leftJoin("application.location", "pirLocation")
Copy link
Collaborator

@dheepak-aot dheepak-aot Apr 6, 2023

Choose a reason for hiding this comment

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

Are we changing the submit logic to save the location in a different PR?

And if that is going to happen, this whole part can be removed right?

        .leftJoin("application.currentAssessment", "studentAssessment")
        .leftJoin("studentAssessment.offering", "offering")
        .leftJoin("offering.institutionLocation", "offeringLocation")
        .leftJoin("offeringLocation.institution", "offeringInstitution");

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, I'm changing the submit logic to save the location in a different PR.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Are we changing the submit logic to save the location in a different PR?

And if that is going to happen, this whole part can be removed right?

        .leftJoin("application.currentAssessment", "studentAssessment")
        .leftJoin("studentAssessment.offering", "offering")
        .leftJoin("offering.institutionLocation", "offeringLocation")
        .leftJoin("offeringLocation.institution", "offeringInstitution");

During previous conversations, we had in mind doing both checks, but since we will save the application.location during the application submission and assuming that the location can only be changed by editing the application, it could be a nice simplification of the query.

@dheepak-aot
Copy link
Collaborator

Thanks for making the changes. Just one outstanding question.

export class StudentInstitutionsController extends BaseController {
constructor(
private readonly studentService: StudentService,
private readonly institutionService: InstitutionService,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please remove the institutionService if it is no longer used.

@UserToken() userToken: IInstitutionUserToken,
@Body() searchCriteria: StudentSearchAPIInDTO,
): Promise<SearchStudentAPIOutDTO[]> {
return await this.studentService.searchStudentApplication(
Copy link
Collaborator

Choose a reason for hiding this comment

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

No need to await.

@UserToken() userToken: IInstitutionUserToken,
@Body() searchCriteria: StudentSearchAPIInDTO,
): Promise<SearchStudentAPIOutDTO[]> {
return await this.studentService.searchStudentApplication(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe I am missing something but is the service result directly returned through the API?
The results must be converted to a DTO.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Now I see that the service is returning the DTO directly. The services, unless they are controller services, do not return DTO directly. API DTOs are supposed to be a controller concern only, that is why we usually deal with them at controller or service controller only.

birthDate: getISODateOnlyString(eachStudent.birthDate),
sin: eachStudent.sinValidation.sin,
}));
return await this.studentService.searchStudentApplication(searchCriteria);
Copy link
Collaborator

Choose a reason for hiding this comment

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

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.

@andrepestana-aot Looks good to me.

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.

Thanks for doing the changes. LGTM 👍

Copy link
Collaborator

@guru-aot guru-aot left a comment

Choose a reason for hiding this comment

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

LGTM, nice work @andrepestana-aot

Copy link
Collaborator

@andrewsignori-aot andrewsignori-aot left a comment

Choose a reason for hiding this comment

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

Thanks for doing the changes, looks good 👍

@sonarqubecloud
Copy link

sonarqubecloud bot commented Apr 6, 2023

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 1 Code Smell

No Coverage information No Coverage information
0.0% 0.0% Duplication

@github-actions
Copy link

github-actions bot commented Apr 6, 2023

Backend Unit Tests Coverage Report

Totals Coverage
Statements: 17.99% ( 1960 / 10892 )
Methods: 8.12% ( 115 / 1417 )
Lines: 20.71% ( 1716 / 8286 )
Branches: 10.85% ( 129 / 1189 )

@github-actions
Copy link

github-actions bot commented Apr 6, 2023

E2E Workflow Workers Coverage Report

Totals Coverage
Statements: 32.41% ( 176 / 543 )
Methods: 21.25% ( 17 / 80 )
Lines: 39.25% ( 157 / 400 )
Branches: 3.17% ( 2 / 63 )

@github-actions
Copy link

github-actions bot commented Apr 6, 2023

E2E Queue Consumers Coverage Report

Totals Coverage
Statements: 56.72% ( 308 / 543 )
Methods: 46.38% ( 32 / 69 )
Lines: 59.48% ( 276 / 464 )
Branches: 0% ( 0 / 10 )

@github-actions
Copy link

github-actions bot commented Apr 6, 2023

E2E SIMS API Coverage Report

Totals Coverage
Statements: 38.08% ( 2580 / 6775 )
Methods: 29.82% ( 263 / 882 )
Lines: 43.7% ( 2208 / 5053 )
Branches: 12.98% ( 109 / 840 )

@andrepestana-aot andrepestana-aot merged commit 007adef into main Apr 6, 2023
@andrepestana-aot andrepestana-aot temporarily deployed to DEV April 6, 2023 21:31 — with GitHub Actions Inactive
@andrepestana-aot andrepestana-aot deleted the 1786_enable_search_student_for_institutions branch April 6, 2023 21:31
@andrepestana-aot andrepestana-aot temporarily deployed to DEV April 6, 2023 21:32 — with GitHub Actions Inactive
@andrepestana-aot andrepestana-aot temporarily deployed to DEV April 6, 2023 21:42 — with GitHub Actions Inactive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Institution Institution Features User Story
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants