Updated Amount validation conditions to not allow indefinite zeroes at the start.#7104
Conversation
|
CLA Assistant Lite bot All contributors have signed the CLA ✍️ ✅ |
|
I have read the CLA Document and I hereby sign the CLA |
|
@sig5 Please add videos for the rest of the platforms. |
|
@parasharrajat I don't have access to a Macbook at the moment. But since this is just a regex change, this should work just fine. Can we do without the Mac/iOS videos? |
|
That's fine. |
|
@parasharrajat Thanks :D ! Added for Android. |
|
Ah, I missed that! As a user, he/she might want to change 5001 to 1001, So we should allow trailing zeroes at the beginning. App/src/pages/iou/steps/IOUAmountPage.js Lines 141 to 144 in 6803d00 We can instead parse the string directly after removing the Commas. And this should take care of all the values. cc: @parasharrajat |
|
Sound like a plan... |
|
I have modified the conditions to work with all strings. I have also modified the value of Constant |
| const lengthBeforeDecimal = this.stripCommaFromAmount(amount.split('.')[0]).length; | ||
| return amount === '' || (decimalNumberRegex.test(amount) && decimalNumberRegex.test(amount) && lengthBeforeDecimal <= (CONST.IOU.AMOUNT_MAX_LENGTH); |
There was a problem hiding this comment.
Why do need to check the decimal part only? It seems to be that we just need to strip , and . from the number and check the length.
There was a problem hiding this comment.
Because the regex enforces the number of values after the decimal to <= 2. If the condition is imposed on the whole string instead, the user can have 500000 and 50000.0 in his valid range but not 50000.24 if IOU.AMOUNT_MAX_LENGTH =6. Applying check on the only part before decimal will ensure a uniform range for the user.
In essence: The sufficient condition to ensure the range of values stays under the max limit is to ensure the length of the decimal part.
Also commas were handled because they were expected to be handled in the existing code. The appropriate use case must be : We might be inserting commas if we are copy-pasting the amount!
There was a problem hiding this comment.
Yeah, commas are added. Missed that upper line. On Backend, we check the whole number via converting the floats to integer (amount * 100) is used.
If we try the logic from the previous code.
- 5000.24 => 500024
- 5000.0 => 500000
I will try to stick to the old code. and we can just prevent zeros.
Let me know if I am missing something.
There was a problem hiding this comment.
The logic that was previously provided works well for a processed string (as we get in backend ) since we can be happy without caring about zeroes in the beginning. In this case, we will need to add an additional condition that essentially checks if (length of stripped portion as a parsedFloat + length of trailing zeroes ) doesn't exceed the limit.
Previous Code:
00500.23 => disregards the initial two zeroes, applies the older condition, and checks from the amount string if the number of zeroes in the beginning, invalidates the amount string.
Newer Logic
00500.23 => takes care of the length of the string directly. The two conditions: (1) fractional part upto 2 decimal places[ Regex takes care] (2) Length of string before decimal should be bounded by Amount_Length, are handled appropriately this way.
In my humble opinion, this condition will ensure a lesser overhead, cleaner, and more generally applicable too! Do let me know your thoughts on it :D .
There was a problem hiding this comment.
disregards the initial two zeroes, applies the older condition, and checks from the amount string if the number of zeroes in the beginning, invalidates the amount string.
Hmm. Still, I am not sure of what you explained above but I got the idea.
There was a problem hiding this comment.
Since we essentially cast strings as integers, we lose the zeroes in the beginning of the number that causes the referenced issue ( Since parseFloat("00000005")=5 ).
I am suggesting that if we directly use the string for validation, we won't be losing the zeroes in the beginning.
| REQUEST: 'request', | ||
| }, | ||
| AMOUNT_MAX_LENGTH: 10, | ||
| AMOUNT_MAX_LENGTH: 7, |
There was a problem hiding this comment.
| AMOUNT_MAX_LENGTH: 7, | |
| AMOUNT_WHOLE_MAX_LENGTH: 7, |
Can you think of a better name to denote the part correctly? I can't think any..
There was a problem hiding this comment.
We can probably do something like AMOUNT_INTEGER_PART_MAX_LEN
There was a problem hiding this comment.
Hmm, did I miss the reasoning behind this change? We want to support large IOU amounts.
There was a problem hiding this comment.
Can you revert the value to 10 please
Co-authored-by: Rajat Parashar <parasharrajat@users.noreply.github.com>
|
Hi @sig5. please merge main to resolve the failing test. |
|
Done. Thanks! |
Julesssss
left a comment
There was a problem hiding this comment.
Yep, that has fixed the lag on my size. Thanks.
It looks like there's a trailing space lint failure to fix, but other than that the PR looks good.
|
Seems, PR is changed completely. I will do the review shortly... |
parasharrajat
left a comment
There was a problem hiding this comment.
Good work. Loved the math.
| * @returns {Number} | ||
| */ | ||
| amountLength(amount) { | ||
| const trailingZeroes = amount.match(/^0+/); |
There was a problem hiding this comment.
Should this be leadingZeroes ? if so, please replace all the trailing to leading.
| We return sum of trailing zeroes length and absAmount length( which has value of the all digits after the decimal). | ||
| In case of zeroes, we add the trailing zeroes length to 2, which | ||
| represent places reserved for digits after decimal. | ||
| */ | ||
| return trailingZeroesLength + (absAmount === '0' ? 2 : absAmount.length); |
There was a problem hiding this comment.
| We return sum of trailing zeroes length and absAmount length( which has value of the all digits after the decimal). | |
| In case of zeroes, we add the trailing zeroes length to 2, which | |
| represent places reserved for digits after decimal. | |
| */ | |
| return trailingZeroesLength + (absAmount === '0' ? 2 : absAmount.length); | |
| Return the sum of leading zeroes length and absolute amount length(including fraction digits). | |
| When the absolute amount is 0, add 2 to the leading zeroes length to represent fraction digits. | |
| */ | |
| return trailingZeroesLength + absAmount === '0' ? 2 : absAmount.length; |
There was a problem hiding this comment.
I addressed the comments, but am doing away with parentheses change since === and ?: has lower precedence than +, it will break the code to put w/o it both at beginning and end.
|
Thanks, @parasharrajat :D! I addressed the suggestions. |
parasharrajat
left a comment
There was a problem hiding this comment.
@sig5 Could you please do a final checkout on performance? just to make sure lodashGet is not slow... 😄
|
Hey @parasharrajat , the runtimes of both the methods seem pretty much equal on my system! |
|
https://measurethat.net/Benchmarks/Show/16725/0/lodashget-vs-property-df Native code is 1.5 times faster than lodashGet. But I am fine as far as it does not affect the UX. I leave this to @Julesssss to check. For me, both are the same and I don't see a recognizable delay. |
|
Hi @sig5, with the latest changes I'm once again able to add multiple zeros prior to the decimal place. |
Julesssss
left a comment
There was a problem hiding this comment.
Requesting further changes.
|
Hi @Julesssss this is expected since we decided to only limit the number of zeroes rather than limiting the zeroes to one since it will pose issues while editing the number. (Eg: 50001->00001-> 10001).
|
|
Ah, that makes sense. Thanks for pointing out the comment. |
|
@sig5, Great job getting your first Expensify/App pull request over the finish line! 🎉 I know there's a lot of information in our contributing guidelines, so here are some points to take note of 📝:
So it might take a while before you're paid for your work, but we typically post multiple new jobs every day, so there's plenty of opportunity. I hope you've had a positive experience contributing to this repo! 😊 |
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🚀 Deployed to staging by @Julesssss in version: 1.1.30-4 🚀
|
|
@marcaaron @chiragsalian @mallenexpensify When we have a single zero upfront, it is not being stripped. Can you please confirm its expected? |
|
Hi @mvtglobally I feel like I should mention here that this was discussed here:#7104 (review), Example:
|
|
Hi @mvtglobally, yes i believe this is fine. From my understanding the code here does not allow indefinite 0's. i.e., you can't enter more than 8 0's to destroy the UI. You can enter |
|
🚀 Deployed to production by @chiragsalian in version: 1.1.31-1 🚀
|



Details
The IOU Amount page didn't impose limits on the length of the string if zeroes are appended to the string. Hence the string can be indefinitely long if zeroes are used at the start.
Fixed Issues
$ #7068
Tests
QA Steps
Tested On
Screenshots
Web
Screencast.from.10-01-22.11-39-07.PM.IST.mov
Mobile Web
WhatsApp.Video.2022-01-10.at.11.41.38.PM.mp4
Desktop
iOS
Android
WhatsApp.Video.2022-01-11.at.12.52.15.AM.mp4