jsgoupil / quickbooks-sync

Sync Quickbooks Desktop
MIT License
87 stars 40 forks source link

Support QBXml 14. #49

Open jsgoupil opened 3 years ago

jsgoupil commented 3 years ago

The new version is out and the difference can be found here:

https://static.developer.intuit.com/resources/ReleaseNotes_QBXMLSDK_14_0.pdf

The main things we should fix is to add the QBXml 14 Schema. change the VERSION to 14. Update the Objects.

And potentially fix the issue they mention here

In a VehicleMileageQuery, if you specify time values (for example, 2002-06-05T10:21:10) in any of the date range filters, you get a statuscode error 3020 statusSeverity="Error" statusMessage="There was an error when converting the date value...” The reason for this is that Vehicle Mileage supports only Date values, not DateTime values, despite what the OSR says. The workaround is to use only date values, as follows: 2002-06-05.

rogerfar commented 1 year ago

Meanwile schema 16 has been released, would it be an idea to upgrade? I did a quick compare and it doesn't seem like a lot of breaking changes, just new fields.

jsgoupil commented 1 year ago

I understand, I think the concept here is that do we want to support older version as we go forward? probably not because the library is not "big enough" So I think we can say if you bring in QbXML 16 then it's a hard "dependency" on the version.

rogerfar commented 1 year ago

According to QB the qbXML spec is backwards compatible: https://developer.intuit.com/app/developer/qbdesktop/docs/get-started/sdk-compatibility-with-quickbooks-releases

I can't speak for other users, but all our customers, about 75, are using at least QB2022+, I'm not sure if there is a compelling reason to even support older versions of the SDK as older versions of QB would miss critical tax upgrades and stuff.

jsgoupil commented 1 year ago

You would be surprised! Some people are using it very much just to keep a book of in/outs. I have a good 25% of people still on 2019 for me. So the thing to do would be to update these XML, regenerate the Objects and add a QbXML override support.

jsgoupil commented 1 year ago

Are you able to share these XML? Somehow, I tried to download 2023 on NFR and it's just not working, the auth doesn't work.

rogerfar commented 1 year ago

Yes for sure, I had to pull them out the QB16 SDK too. QBSDK16 XML.zip

Let me know if you want me to share the complete 16 SDK.

jsgoupil commented 1 year ago

I'll work on this today. Do you have the path where you download this usually? or is it part of the QB2023?

rogerfar commented 1 year ago

I get it from here: https://developer.intuit.com/app/developer/qbdesktop/docs/get-started/download-and-install-the-sdk You will need an account, don't think you need a specific type of account.

This is a direct link to the latest version: https://developer.intuit.com/app/developer/logged-in-content/QBSDK160_x64.exe

jsgoupil commented 1 year ago

I started the development here. https://github.com/jsgoupil/quickbooks-sync/pull/65

I need to find a nice way to pass this: https://github.com/jsgoupil/quickbooks-sync/blob/qbxml16/src/WebConnector/Core/IWebConnectorHandler.cs#L53

To this: https://github.com/jsgoupil/quickbooks-sync/blob/master/src/WebConnector/Impl/StepQueryRequestBase.cs#L41

Ideas welcome.

anonmily commented 10 months ago

Since the VERSION field is static and public on QbXmlRequest at the moment, could we just pass it in directly?

public virtual async Task<string?> SendXMLAsync(IAuthenticatedTicket authenticatedTicket)
{
    var requestObject = await CreateRequestAsync(authenticatedTicket);
    if (requestObject != null)
    {
        if (await ExecuteRequestAsync(authenticatedTicket, requestObject))
        {
            var qbXmlRequest = new QbXmlRequest(QbXmlRequest.VERSION);
            qbXmlRequest.AddToSingle(requestObject);

            return qbXmlRequest.GetRequest();
        }
    }

    return null;
}

Edit: Oh wait. I just realized there is an empty constructor for QbXmlRequest that already grabs the default version from that static property. So do we even need to pass anything in? It seems like it would work just fine as is, unless I am missing something.

Or if it might potentially be changed depending on the environment, I wonder if it is possible to add the version information onto the ticket? Since the authenticated ticket is passed around, it might be possible to save the version information into the ticket then retrieve it for use in the step query requests?

public interface IAuthenticatedTicket
{
    /// <summary>
    /// Ticket exchanged with the WebConnector. It acts as a session identifier.
    /// </summary>
    string Ticket { get; set; }

    /// <summary>
    /// State indicating what to exchange with the Web Connector.
    /// </summary>
    string CurrentStep { get; set; }

    /// <summary>
    /// Simple boolean indicating if the ticket is authenticated.
    /// </summary>
    bool Authenticated { get; set; }

    /// <summary>
    /// Quickbooks version string
    /// </summary>
    Version QbVersion { get; set; }

}
public virtual async Task<string?> SendXMLAsync(IAuthenticatedTicket authenticatedTicket)
{
    var requestObject = await CreateRequestAsync(authenticatedTicket);
    if (requestObject != null)
    {
        if (await ExecuteRequestAsync(authenticatedTicket, requestObject))
        {
            var qbXmlRequest = new QbXmlRequest(authenticatedTicket.QbVersion);
            qbXmlRequest.AddToSingle(requestObject);

            return qbXmlRequest.GetRequest();
        }
    }

    return null;
}
jsgoupil commented 10 months ago

Being in the ticket makes sense but it's saved in the DB. It's not a bad idea I could pick up the work I had started next week.