中小企業会計ソフトの分野で、日本ではfreeeやマネーフォワードが普及しているが
海外ではQuickbooksが広く普及している。
このQuickbooks内に外部からデータをRailsアプリ経由で追加することで入力作業を省き、業務効率を上げようという話になった。
前提としてQuickbooks Onlineではなく、Quickbooks DesktopというWindowsアプリを使う。Onlineを使用している方にはこの記事は不要。
Quickbooks Onlineだと、すごく充実したREST APIドキュメントが
あるので開発も簡単だが、Quickbooks Desktopでは「Quickbooks Web Connector(以降QBWC)」を使う。
色々と調べる中で、当たり前だが日本語の情報が壊滅的になかったので、将来の自分用に調べた内容をこの記事に残す。
QBWCの使い方
・QBWCは、QuickBooks Desktopがインストールされている端末にインストールする。
・APIはRESTではなく、SOAPという古いタイプのAPIで、XMLをやり取りすることでリクエストを行う。
以下のPDF内で、なぜQBWCは、シンプルなWeb APIではないのかについて説明があるが
一言でいうと、セキュリティを確保するため、不特定多数が使用するインターネット上からのアクセスを防ぎたいという意図があった模様。
※だったら、QuickBooks Onlineはどうなんだという疑問はあるが。
https://developer-static.intuit.com/qbSDK-current/doc/PDF/QBWC_proguide.pdf
・Railsとのやり取りの流れは以下
1)RailsでSOAP APIへのリクエスト(Job)を作成する
2)QBWC側からRailsにアクセスし、Jobがあればそれを実行する。
つまりRails側からJob実行のキューは送れない。Job実行のトリガーは必ずQBWCから。
・RailsでQBWCとやり取りするには、qbwcのgemを使用する。
github.com
Rails gem(qbwc)の使い方
・基本的な設定や使い方については上記の公式サイトを参照
・作成できるJobは「読込」と「書込」のどちらも可能
・Job作成にあたり、リクエスト用のHashを作成するのだが、それには以下のドキュメントを使用する。
しかし使いにくいし、説明不足感が否めない。
このドキュメントを使用し、リクエストHashを作成する上で大事な点は以下
・Railsで使用するフォーマットは「qbXML」。
・QBEditionsは使用するQuickBooks Desktopの国を設定すること。
・ドキュメントのXMLの「順番」は必ずそのとおりにすること。普通のHashで書くように、KEYの順番を入れ替えて作成すると「Parse Error」を返す。
・書込の際に「AMTTYPE」の値を送信する場合は、小数点第二位まで含んだ文字列を設定する必要がある。
※ ドキュメントにも書いてない。
✗: 123.4
○: 123.40
https://help.developer.intuit.com/s/question/0D50f00004rTfc6CAC/qbxml-amount-invalid-cant-convert
https://help.developer.intuit.com/s/question/0D5G000004Dk7HIKAZ/invoice-amount-error-3040-what-am-i-doing-wrong
・参照系のリクエストを送るときに、膨大なデータをリクエストするときは、一度にリクエストを送らず「Iterator」を使用したコードを作成すること。
自分は使用してはいないが、恐らく以下の記事を見ると、
最初のリクエストは以下のようにiteratorにStartを指定し
... :sales_order_query_rq => { {:xml_attributes => { 'iterator' => "Start" }} } ...
それ以降のリクエストでは、iteratorにContinueを指定し、最初のリクエストの返り値であると思われるIteratorIDを設定する模様。
... :sales_order_query_rq => { {:xml_attributes => { 'iterator' => "Continue", 'iterator_id' => iteratorID }} } ...
https://github.com/consolibyte/quickbooks-php/blob/master/docs/web_connector/example_web_connector_import.php#L214
https://github.com/Natejd04/QBWC_Test/blob/d23b42738eae05844e0e23375621fa48809ddb77/app/workers/z-customer_order_worker.rb
https://stackoverflow.com/questions/21757478/iteration-samples-in-quick-books-using-web-connector
未確認だが、使用する際に試したい。
・Mod系のAPI使用時に注意する点
例えば、Invoiceの内容を変更するInvoiceModを使用するとしよう。その時前回に送ったInvoiceのItemLine内容に、新しいItemLineを追加する必要があるとする。
InvoiceAddのAPIならば、InvoiceLineAddがあり名前の通りに、Itemを追加するだけでよいが
InvoiceModのAPIは、InvoiceLineModという変更前提のものしかない。。。それでどうするか。。。
「TxnLineIDを-1」に設定すれば良い。
言わずもがなドキュメントにはこの記載はない。
またこのInvoiceModを使用時には、以前登録したデータも追加しないと、前のデータを上書きするみたいな内容になるので注意。
https://help.developer.intuit.com/s/question/0D50f00005gIodbCAC/how-can-i-get-txnid-and-editsequence-by-same-inovice-date-invoice-on-qb-for-checking-whether-add-new-invoice-or-add-new-line-in-same-invoice-like-an-attachment-and-how-can-i-add-new-line-in-same-invoiceaspnet-c
https://stackoverflow.com/questions/32817070/how-to-modify-an-invoice-in-quickbooks-using-qbxml-and-qbsdk13
・処理が遅いとき・・・
Rails側からデータを送信したときに、リクエストをQBWC側で受け取るのは早いが、それからの処理がものすごい遅いことがあった。
レジストリをいじって、キャッシュやログ出力の抑制などを試したが、あまり効果がなく、色々試して最後に効果があったのが
できるだけ、リクエストに必要なパラメータは全て送ること。
試したのは、InvoiceAddのAPIに、InvoiceLineAddで50個のデータを追加して送るとなんと3分もかかっていた。
またアイテムを追加するたびにn²で遅くなって行く模様。。。
このとき追加した情報はItemRef, Quantity, Amountの3つ。
そしてここにSalesTaxCodeRefを"E"で追加したら、20秒で処理が終わった。
恐らく送れるパタメータはできるだけ送ったほうが、QuickBooks Desktop側での処理をしなくてもよい?のかもしれない。
Rails側のリクエスト用のサンプルコード
個人的には以下のサイトが役にたった。
Integrating QuickBooks Desktop With Rails Application | Nascenia
GitHub - flowlink/quickbooks_desktop_integration: Quickbooks Desktop Integration for FlowLink
GitHub - sirius2013/BuildCore: BuildCore
補足
・レジストリをいじるときに参考にした記事
https://accountants-community.intuit.com/questions/192000-any-resolution-for-issue-with-quickbooksdb22-or-newer-service-qbdbmgrn-exe-process-being-locked-to-512mb-of-ram
https://blog.quickbooksusers.com/quickbooks/why-quickbooks-is-sometimes-slow/
https://www.ablemods.com/blog/2013/02/21/how-to-improve-quickbooks-web-connector-speed/