-
Notifications
You must be signed in to change notification settings - Fork 40
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
Parsing amounts incorrectly from string to decimal #40
Comments
One option may be to use I did a quick test using a query string instead which seemed promising. I appended the Update the startup something like this:
|
Quite the interesting finding here. Are you saying that QuickBooks is sending to your server 20,00 ? If that's the case, I think we should be able to replicate that by setting our desktop computer to a different region? |
@jsgoupil Yes, to replicate the scenario you can modify the Windows regional settings on the computer that is running the WebConnector, actually just changing the decimal symbol for the currencies from point to comma should be enough. @tofer Unfortunately the solution you propose will work only if you know in advance what is the culture of the client you are going to integrate in order to build the URL and include it in the QWC file. However it won't be always the case, and also it will fail again if for some reason the client's decimal symbol changes after the initial setup. I haven't look yet in detail the QbSync.QbXml implementation, but I'd say that probably the classes defined on QbSync.QbXml.Objects may require more logic when setting the value of the properties than just assigning the value, as ItemNonInventoryRet.EditSequence setter does. I'll check the implementation closely to try to find/propose a solution... |
We generate some getters/setters for a lot of things in there. So we can most likely fix the problem, but before you venture there, do you have a way to find out which Culture the client is in? Is there a way to get it from a QbXml call? from the first request the client sends? PS. I'm on vacation right now, not allowed to code 🏒 |
I inspected the HTTP request and the body coming from WebConnector, and could not find anything that would indicate culture, only Country. Like @jsgoupil asks... how do you know what culture to use if not asking the user initially? Is there something I'm missing in the request? I would still think the approach would be to set the If deserialization is the only issue as you say (and serialization can stay decimal points), perhaps another solution would be to not worry about what the culture is, but to have parsing allow either comma or decimals. We would need to make sure WebConnector never sends commas for thousands place separators. If that was true, and this was possible, then we wouldn't need to worry about the cutlure, and we wouldn't need to pass anything into the deserialization process. I'll try to test if I can grab some time. |
@jgalvis-sw I enabled multi-currency mode in QB, and changed my USD from period decimal separator to comma, and requests are still coming from the WebConnector with period decimal separators. Seems like this might only be for display in QB. Do I have to change my system wide language to test this? |
@tofer Actually are the OS Regional settings what you have to change. The WebConnector always change the response coming from the SDK using the OS culture. @jsgoupil @tofer To answer your question: Yes, actually I'm able to identify the culture "dynamically". In my implementation I perform some validations using the |
Ah, thanks @jgalvis-sw. So if I am understanding correctly, you are setting a DataExt field, in one request, then reading it back in the next request to determine the formatting of the decimal place? This doesn't seem like something we can bake into the library easily. I just examined a request from WebConnector, and it for me at least I am not getting any thousands place separators in number values. What do you think of the option for allowing either commas or periods for decimal separators, and not worrying about the culture? Change
|
We could bake it in the library with a options.DetectCulture() which would create a step. It's a little much though, don't you have to create your DataExt first, then push a value to "something"... It's been a while for me since I worked on this. And, from your screenshot @jgalvis-sw , if you just change your decimal symbol, it doesn't change your culture from what I remember? So really just reading the country does not actually detect the comma, correct? So we would be stuck with making a dummy step. I'm quite surprised the QbXml PDF does not mention this, or at least someone complaining on their forum? |
@tofer about thousands place separators: you're right, in all tests I made I didn't see any thousand group separator, however I didn't test exhaustively all the amount/quantity fields that could be returned in a QBXML neither all the cultures supported by Quickbooks. @tofer @jsgoupil In my implementation I'm using the About the DataExt field, yes is like @jsgoupil said, you have to create the field first and then push the value, however I play with the fact that the WebConnector executes all the queries contained in a single Qbxml request sequentially...So that in the same QbXml request, with @jsgoupil About changing only the decimal symbol vs the whole culture: I still think that the cleaner solution is to have in count the culture, and -just speculating- if you think about it probably other fields, like |
I had already thought of this actually. If you notice in my code change suggestion, I forced the Regarding a possible issue with culture and I would agree about factoring in the culture as the cleaner solution, however in your method of checking you still don't actually know the culture, you are just guessing based on the country and how the numbers or formatted. |
@tofer You're right! Sorry I missed the Invariant culture. As there're no others parsing impacted by the culture and we haven't find yet an accurate method to identify the client culture, I think what you propose is enough to solve this issue! |
I would highly value not using a hack, before we jump into implementation, we should make sure we are on the same page. I'll have a look later when I'm allowed to use quickbooks as well. |
After investigation, I am not getting that we are on en-US or fr-CA. But I am able to see that more than FLOATTYPE is affected. On this screenshot, we can see that the data coming on the first request also affects PERCENTTYPE and AMTTYPE. And most likely PRICETTYPE would be affected. Unsure about QUANTYPE, but it most likely be affected (to be verified), so the fix could be in FLOATTYPE. I would not do a The solution that @jgalvis-sw proposed of creating a fake invoice and reading it is definitely not my favorite. Probably the most fullproof but quite the chatty messages with QuickBooks.
I think we would need to save the culture alongside the ticket/step. The other way to fix the problem is the idea @tofer proposed at the beginning and to get the Culture on the web connector connection. Since these two options are opt-in, I am up for any/both. But I don't have the time to implement it at the moment. |
My $0.02 is that doing culture detection via steps should not be the way to go: A) It's complicated Adding an option to specify culture on an account (or basically during Qwc download) seems fine with me, since the user can then actually select their culture. This may solve other user's issues, but doesn't solve for @jgalvis-sw . I know you don't like the comma replacement, but we could probably make that opt-in as well. It (or something similar for 'multi-culture leniency') is still my vote ;) |
Is Also, would creating a custom culture feel less hacky than doing a string replace? What about something like this in NOTE: Untested
|
@tofer that's hacky to me :( I met him once at a QuickBooks convention, let's see what he has to say on this. |
So William responded on the QuickBooks thread, and he doesn't have any recommendations. |
When the WebConnector's host OS is setup with a different culture (having a different decimal symbol) than the server running the QBSync.QbXml library, the values parsed in QbSync.QbXml.Objects.FLOATYPE from string to decimal are being parsed wrong. This is the case when QBSync.Qxml is running on en-US, where the decimal symbol is point (".") and the WebConnector is running on fr-CA, where the decimal symbol is comma (","). eg, an amount sent in the original QbXml by the WebConnector as "20,00", will be parsed to "2000.00".
Looking at the code, we can see that the private method Parse in QbSync.QbXml.Objects.FLOATYPE implementation, used to parse the values from string to decimal is using the Decimal.TryParse overload that receives only the string as parameter. This overload will use the current thread culture (in the case of a web app).
This issue could be solved using the Decimal.TryParse overload that receives also the number style and the culture as parameter. It means that the culture should be sent a) as parameter on every call to deserialize a FLOATYPE, or b) sent as parameter in the FLOATYPE constructor and use it in the Parse method.
This is a little example to illustrate the problem and the solution:
https://dotnetfiddle.net/V20rXq
This issue is probably also impacting the parsing from decimal to string, however, after some tests I've made with the WebConnector, looks like it is able to manage properly both decimal symbols regardless the host culture.
In my opinion, it is important that the culture will be set explicitly for each usage of the serialization logic, or at the app initialization (or both), to highlight the fact that the culture used to serialize/deserialze the QbXmls actually matters, and may impact the values of some properties.
The text was updated successfully, but these errors were encountered: