I prefer scaling in the IO when possible (if the point isn’t reverse scaled). I then check the range using the engineering units, since as you mention, the module range (4 to 20mA, -20 to 20mA, -10 to 10v, etc.) may be valid, but can be well outside what you want in your process. I don’t think there is a one size fits all on this, and I think your approach is valid. Customers changing the IO input ranges is not something I have ran into…
Checking your inputs, and alarming on out of range values is such a common procedure that I have a subroutine for this. I set it up to allow for time delays and reset hysteresis, and it made the alarming in my control charts concise and easy to configure. I could then alarm in PAC display by checking the discrete alarm status variable I setup for each point, and I also could optionally log a message to the controllers message queue.
Here is a screenshot of the parameters to get an idea/inspiration:
And here is an example of it being called:
Notice that the limits are variables (persistent) that the operators can reconfigure if needed. In others I have hard coded values. I also have a similar subroutine for digital/discrete values.