-
Notifications
You must be signed in to change notification settings - Fork 0
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
Feature: Line manager can deny an annual leave request #25
Conversation
1977961
to
73ea660
Compare
Adds a test for the feature, following the full user journey.
Creates an endpoint for line managers to deny annual leave requests.
327d388
to
8f5e6bb
Compare
8f5e6bb
to
7b97567
Compare
This is the endpoint users hit when they have successfully denied an annual leave request.
Creates a column in the annual_leave_requests table for denial_reason and permits this parameter in the AnnualLeaveRequestsController
Updates the page to be rendered based on the attempted status update (i.e. if a denial failed, render the deny page)
Implements code to send an email to a user when their annual leave request has been denied
This refactors the emails_helper module so that it uses the same method for sending emails about status updates, whether it is denied or approved. This is with the aim of making the workflow more open to extension, because at the moment it is not.
7b97567
to
6a94aa5
Compare
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 are several instances here of conditional behaviour based on the leave request status, which is a good sign it might be worth refactoring. In general you want to check a condition once and then propagate that decision across the application where necessary
confirm_annual_leave_request_approval_path | ||
when "denied" | ||
confirm_annual_leave_request_denial_path | ||
end |
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.
I think the fact that you're checking the status both here and on lines 43-44 is a sign there's a refactoring available here. There's a couple of things you could do. Either you could separate the approval and denial routes, removing the conditionals altogether (this would be my choice - in my experience more routes with less conditionals are much more maintainable than less routes with more conditionals) or you could set up some kind of status configuration that knows what paths/views to render based on the status parameter.
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.
I agree 100%, I created a refactor here but thought it would be better as a separate PR as this one is already quite big. Let me know what you think of the refactor.
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 that refactor looks like it's definitely heading in a good direction, nice one
when "approved" | ||
client.send_email(approval_email_hash(annual_leave_request)) | ||
when "denied" | ||
client.send_email(denial_email_hash(annual_leave_request)) |
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.
Ah, another duplicated conditional 🤔
date_to: annual_leave_request.date_to.to_fs(:rfc822), | ||
denial_reason: annual_leave_request.denial_reason, | ||
}, | ||
} |
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.
This is sort of why I was suggesting those serializer objects in a previous PR review - once you've got a number of different email hashes to think about you probably won't want them all in one helper... but for now it's probably fine.
@@ -6,6 +6,7 @@ class AnnualLeaveRequest < ApplicationRecord | |||
validates :date_from, :date_to, comparison: { greater_than: Time.zone.today, message: "must be in the future" } | |||
validate :user_has_enough_annual_leave_remaining | |||
validates :confirm_approval, acceptance: { accept: "confirmed" } | |||
validates :denial_reason, presence: true, allow_nil: true |
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.
Curious about the allow_nil here, I'm guessing there's a good reason why it's there but I don't know what it is
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.
This allows me to create AnnualLeaveRequest
s with no denial reason (default is nil
on creation), whilst simultaneously checking a Line Manager gives a reason on denial. Is there a better way to do this?
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.
Ah that makes sense. That suggests you've got a problem with your database table design to me, because having to have a denial reason for requests that aren't denied is a sign the modelling isn't perfect. I've done things like move the state updates into a different table or even have a separate table for records for each state in other systems before, but it's hard to say exactly what the best choice would be here.
Modelling state machines in databases is tricky though and you might want to leave it as is for now until it starts to cause more problems.
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.
Yea that makes sense! I'm going to merge this request and make a trello ticket to revisit this topic
denial_reason: "some valid reason", | ||
}, | ||
} | ||
leave_request.reload |
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.
I feel a bit wary about sharing the leave_request
object between these four tests, but I think in case its safe. Always a little bit prone to confusing mishaps though
What
Adds the ability for line managers to deny annual leave requests, including:
Why
This is a key feature in the application. Users need to have their annual leave requests responded to by their line managers.
Screenshots
Deny page
Design specification
Deny page with errors
Denial confirmation page
Design specification