-
Notifications
You must be signed in to change notification settings - Fork 13
#4539 - Add Duplicate SIN Validation #5697
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
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR implements a duplicate SIN validation check when Ministry users manually add a SIN to a student profile. If a duplicate is detected, the user is warned and must explicitly confirm before proceeding.
Changes:
- Adds optional
confirmDuplicateSINfield to the CreateSINValidation DTO (frontend and backend) - Implements duplicate SIN check in the SINValidationService and controller
- Updates the AddNewSIN modal to display a warning banner and confirmation checkbox when duplicates are detected, and moves the save logic into the modal component to allow resubmission
- Adds comprehensive e2e tests covering duplicate rejection, duplicate confirmation, and unique SIN scenarios
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| sources/packages/web/src/views/aest/student/SINManagement.vue | Moves SIN creation logic to modal component; simplifies parent component's responsibilities |
| sources/packages/web/src/services/http/dto/Student.dto.ts | Adds optional confirmDuplicateSIN field to CreateSINValidationAPIInDTO |
| sources/packages/web/src/constants/error-code.constants.ts | Defines SIN_DUPLICATE_NOT_CONFIRMED error constant |
| sources/packages/web/src/components/common/sin/AddNewSIN.vue | Adds duplicate warning UI, confirmation checkbox, and inline SIN creation logic with error handling |
| sources/packages/backend/apps/api/src/services/sin-validation/sin-validation.service.ts | Implements checkDuplicateSIN method to detect existing SINs across student profiles |
| sources/packages/backend/apps/api/src/route-controllers/student/student.aest.controller.ts | Adds duplicate SIN validation and throws UnprocessableEntityException when not confirmed |
| sources/packages/backend/apps/api/src/route-controllers/student/models/student.dto.ts | Adds optional confirmDuplicateSIN boolean field with validation decorators |
| sources/packages/backend/apps/api/src/route-controllers/student/tests/e2e/student.aest.controller.createStudentSINValidation.e2e-spec.ts | Adds e2e tests for duplicate rejection, duplicate confirmation, and unique SIN scenarios |
| sources/packages/backend/apps/api/src/constants/error-code.constants.ts | Defines SIN_DUPLICATE_NOT_CONFIRMED constant for backend error handling |
sources/packages/backend/apps/api/src/services/sin-validation/sin-validation.service.ts
Outdated
Show resolved
Hide resolved
sources/packages/backend/apps/api/src/route-controllers/student/student.aest.controller.ts
Outdated
Show resolved
Hide resolved
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
...ntrollers/student/_tests_/e2e/student.aest.controller.createStudentSINValidation.e2e-spec.ts
Show resolved
Hide resolved
...ntrollers/student/_tests_/e2e/student.aest.controller.createStudentSINValidation.e2e-spec.ts
Show resolved
Hide resolved
...ntrollers/student/_tests_/e2e/student.aest.controller.createStudentSINValidation.e2e-spec.ts
Show resolved
Hide resolved
...ntrollers/student/_tests_/e2e/student.aest.controller.createStudentSINValidation.e2e-spec.ts
Show resolved
Hide resolved
weskubo-cgi
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes look great. Just some minor questions/comments to resolve.
sources/packages/backend/apps/api/src/route-controllers/student/student.aest.controller.ts
Outdated
Show resolved
Hide resolved
sources/packages/backend/apps/api/src/services/sin-validation/sin-validation.service.ts
Outdated
Show resolved
Hide resolved
...ntrollers/student/_tests_/e2e/student.aest.controller.createStudentSINValidation.e2e-spec.ts
Show resolved
Hide resolved
...ntrollers/student/_tests_/e2e/student.aest.controller.createStudentSINValidation.e2e-spec.ts
Outdated
Show resolved
Hide resolved
| @@ -1,6 +1,6 @@ | |||
| <template> | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, i believe it even makes the modal screen scroll a bit when all the banners are displayed
| const addNewSINModal = ref( | ||
| {} as ModalDialog<CreateSINValidationAPIInDTO | boolean>, | ||
| ); | ||
| const addNewSINModal = ref<InstanceType<typeof AddNewSIN>>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: Is there any reason to use this instead of const addNewSINModal = ref({} as ModalDialog<boolean>);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a particular reason, it only changed because the modal wont return the Model anymore, and i like the InstaceType better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As all the modals follow a common design system with type ModalDialog. I would stick to common interface. The modified approach is better if a component has it's own unique properties which requires to be typed.
sources/packages/backend/apps/api/src/route-controllers/student/student.aest.controller.ts
Outdated
Show resolved
Hide resolved
| .getRepository(Student) | ||
| .createQueryBuilder("student") | ||
| .innerJoin("student.sinValidation", "sinValidation") | ||
| .select("student.id") | ||
| .where("sinValidation.sin = :sin", { sin: normalizedSIN }) | ||
| .andWhere("student.id != :studentId", { studentId }) | ||
| .getOne(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
using exists would simplify this.
const exists = await this.dataSource.getRepository(Student).exists({
where: {
id: Not(studentId),
sinValidation: {
sin: normalizedSIN,
},
},
});There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for not being clear. returning the exists would be good.
return this.dataSource.getRepository(Student).exists({
where: {
id: Not(studentId),
sinValidation: {
sin: normalizedSIN,
},
},
});| class="mt-4" | ||
| v-if="showDuplicateWarning" | ||
| :type="BannerTypes.Warning" | ||
| header="Duplicate SIN Warning" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please share the title with business as it wasn't in the AC.
| v-if="showDuplicateWarning" | ||
| :type="BannerTypes.Warning" | ||
| header="Duplicate SIN Warning" | ||
| summary="This SIN is currently associated with another student profile. Please investigate and correct any profiles with the incorrect SIN. If this is correct for the current student, please confirm and click 'Add SIN now'." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor. The AC has Add SIN now enclosed in double quotes.
|
| const showDuplicateWarning = ref(false); | ||
|
|
||
| const requiredCheckboxRule = (value: boolean) => | ||
| value || "You must confirm to proceed"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a period to the message.
|
|
||
| const cancel = () => { | ||
| addNewSINForm.value.reset(); | ||
| showDuplicateWarning.value = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the value required to be reset??
| // Check for duplicate SIN if confirmation is not provided. | ||
| isDuplicate = await this.sinValidationService.checkDuplicateSIN( | ||
| studentId, | ||
| payload.sin, | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error can be thrown inside the if block as it does not have reason to live outside.
if (!payload.confirmDuplicateSIN) {
// Check for duplicate SIN if confirmation is not provided.
const isDuplicate = await this.sinValidationService.checkDuplicateSIN(
studentId,
payload.sin,
);
if (isDuplicate) {
throw new UnprocessableEntityException(
new ApiProcessError(
"This SIN is currently associated with another student profile and confirmation to allow duplication SIN is missing.",
SIN_DUPLICATE_NOT_CONFIRMED,
),
);
}
}



Summary
Adds a duplicate validation when manually adding a SIN number to a student in the Ministry Portal.
Frontend
Updates the AddNewSIN modal component to include new banner and confirmation checkbox.
Updates the SINManagement view to move the save SIN method to the AddNewSIN component (to allow resubmission without closing the modal)
Backend
Updates the create SIN model to include optional confirmDuplicate property.
Updates the SIN validation service to include new duplicate validation.
Updates the student controller to handle the custom error (duplicate not confirmed).
E2E
Adds new tests for the different validation scenarios.