Skip to content

(fix) O3-5432: Validate completion date against enrollment date in program enrollment form#3035

Open
UjjawalPrabhat wants to merge 3 commits intoopenmrs:mainfrom
UjjawalPrabhat:fix/O3-5432-completion-date-validation
Open

(fix) O3-5432: Validate completion date against enrollment date in program enrollment form#3035
UjjawalPrabhat wants to merge 3 commits intoopenmrs:mainfrom
UjjawalPrabhat:fix/O3-5432-completion-date-validation

Conversation

@UjjawalPrabhat
Copy link
Contributor

@UjjawalPrabhat UjjawalPrabhat commented Feb 17, 2026

Requirements

  • This PR has a title that briefly describes the work done including the ticket number. If there is a ticket, make sure your PR title includes a conventional commit label. See existing PR titles for inspiration.
  • My work is based on designs, which are linked or shown either in the Jira ticket or the description below. (See also: Styleguide)
  • My work includes tests or is validated by existing tests.

Summary

  • Added Zod superRefine validation to prevent saving a program enrollment when the completion date is before the enrollment date
  • Shows an inline error on the completion date field: "Completion date cannot be before the enrollment date"
  • Previously, the form submitted to the API which returned a generic 400 error with no actionable guidance

Screenshots

image

Related Issue

O3-5432

Other

@UjjawalPrabhat UjjawalPrabhat force-pushed the fix/O3-5432-completion-date-validation branch from da249e2 to ae5d851 Compare February 17, 2026 19:31
@UjjawalPrabhat
Copy link
Contributor Author

@denniskigen @VeronicaMuthee Could you please review this PR?

Copy link
Member

@denniskigen denniskigen 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 adding the cross-field validation!

selectedProgram: z.string().refine((value) => !!value, t('programRequired', 'Program is required')),
enrollmentDate: z.date(),
completionDate: z.date().optional().nullable(),
enrollmentLocation: z.string(),
Copy link
Member

Choose a reason for hiding this comment

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

nit: The backend (PatientProgramValidator in openmrs-core) uses a strictly-less-than comparison — it allows dateCompleted == dateEnrolled (same-day completion). This check uses <=, which is stricter than the backend. Was that intentional?

If we want to align with the backend, this should be < instead of <=, and the minDate / isDisabled constraints on the completion date picker (lines 237-239) should also be relaxed to allow same-day dates.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@denniskigen Yes. if you check here, the existing UI already enforced that completion date must be at least 1 day after enrollment date. I matched the superRefine validation to be consistent with these existing UI constraints, that's why I used <=.

That being said should we allow same day completions?

await user.tab();

await user.click(saveButton);

Copy link
Member

Choose a reason for hiding this comment

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

Could we also assert that the validation error message is rendered? Right now the test only checks that the submit handlers weren't called, but doesn't verify the user actually sees feedback. Something like:

expect(screen.getByText(/completion date cannot be before the enrollment date/i)).toBeInTheDocument();

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@denniskigen regarding this, if you check here, the OpenmrsDatePicker mock in @openmrs/esm-framework destructures isInvalid to conditionally render invalidText but the real component (and all usages across the codebase) passes invalid, not isInvalid. So the mock never renders the error text, making screen.getByText(...) impossible for date picker validation errors.

Would it maybe make more sense to fix it there first?

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants