Closed johnnydisco closed 6 years ago
Hello @johnnydisco There is simple example how to create single-line Invoice with only required fields.
from quickbooks.objects import (Invoice,
SalesItemLineDetail,
SalesItemLine)
customer_ref = Ref()
customer_ref.value = 123
customer_ref.name = 'Ivan Petrov'
customer_ref.type = 'Customer'
# or customer_ref = Customer.get(123, qb=client).to_ref()
line_detail = SalesItemLineDetail()
line_detail.UnitPrice = 100 # in dollars
line_detail.Qty = 1 # quantity can be decimal
line = SalesItemLine()
line.Amount = 100 # in dollars
line.SalesItemLineDetail = line_detail
invoice = Invoice()
invoice.CustomerRef = customer_ref
invoice.Line = [line]
client = QuickBooks(...)
invoice.save(qb=client)
I was able to follow this and get an invoice created but then I try to send the invoice via email using the following:
invoice.save(qb=qb_client)
invoice.send_invoice("john@doe.com")
I get this error
AttributeError: 'Invoice' object has no attribute 'api_url'
Looking in invoice.py
def send_invoice(self, send_to=None):
url = self.api_url + "/company/{0}/invoice/{1}/send".format(self.company_id, self.Id)
results = self.make_request("POST", url)
return results
It seems like it's looking for client properties in the invoice object. What am I missing?
I took a look at the tests and see they use invoice.send() instead of invoice.send_invoice() I tried this like so:
invoice = Invoice()
invoice.Id = 291
invoice.send(qb=qb_client)
...and I get the following error:
Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1997, in __call__
return self.wsgi_app(environ, start_response)
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1985, in wsgi_app
response = self.handle_exception(e)
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1540, in handle_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.6/site-packages/flask/_compat.py", line 33, in reraise
raise value
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.6/site-packages/flask/_compat.py", line 33, in reraise
raise value
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/web/app.py", line 259, in bt_sub_hook
invoice.send(qb=qb_client)
File "/web/3rdparty/quickbooks/quickbooks/mixins.py", line 108, in send
results = qb.misc_operation(end_point)
TypeError: misc_operation() missing 1 required positional argument: 'request_body'
Anyone following this thread? This is a show stopper.
I think I see the problem. I will work on a fix and release an update later this week.
Not sure if this helps but I pulled commit 3611022 and tried again. Here's the call and the corresponding error
invoice.send("trey@phish.com",qb=qb_client)
Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1997, in __call__
return self.wsgi_app(environ, start_response)
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1985, in wsgi_app
response = self.handle_exception(e)
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1540, in handle_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.6/site-packages/flask/_compat.py", line 33, in reraise
raise value
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.6/site-packages/flask/_compat.py", line 33, in reraise
raise value
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/web/app.py", line 289, in bt_sub_hook
invoice.send("larry@morroni.com",qb=qb_client)
File "/web/3rdparty/quickbooks/quickbooks/mixins.py", line 112, in send
results = qb.misc_operation(end_point, content_type="application/octet-stream")
File "/web/3rdparty/quickbooks/quickbooks/client.py", line 298, in misc_operation
results = self.make_request("GET", url, request_body, content_type)
File "/web/3rdparty/quickbooks/quickbooks/client.py", line 204, in make_request
raise AuthorizationException("Application authentication failed", detail=req.text)
quickbooks.exceptions.AuthorizationException: QB Auth Exception: Application authentication failed
Can you check and make sure that your qb_client is set up properly. "Application authentication failed" typically means that you don't have something set up correctly.
Yes I agree that's what it sounds like but the invoice.save() works without issue as do a number of other operations that require authentication.
Not sure this helps but looks like this is what we are getting back
{"warnings":null,"intuitObject":null,"fault":{"error":[{"message":"message=ApplicationAuthenticationFailed; errorCode=003200; statusCode=401","detail":"SignatureBaseString: GET&https%3A%2F%2Fsandbox-quickbooks.api.intuit.com%2Fv3%2Fcompany%2F123145844963419%2Finvoice%2F352%2Fsend&oauth_consumer_key%3DqyprdLiUxYMs4EBskkejFji8cHbIic%26oauth_nonce%3D9ddc85e91e848d030b8ba0ed76bdd57b646c60bf%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1522344247%26oauth_token%3Dqyprdj79RtfIkBSkCgJZKdViu9hYCJlY2DH9vhNuGH292KNV%26oauth_version%3D1.0%26sendTo%3Dtrey%2540phish.com","code":"3200","element":null}],"type":"AUTHENTICATION"},"report":null,"queryResponse":null,"batchItemResponse":[],"attachableResponse":[],"syncErrorResponse":null,"requestId":null,"time":1522344133155,"status":null,"cdcresponse":[]}
I pulled from master today and it's now using a POST instead of GET. Here's how I call it:
invoice.send(qb=qb_client,send_to="trey@phish.com")
And resulting error
{"warnings":null,"intuitObject":null,"fault":{"error":[{"message":"message=ApplicationAuthenticationFailed; errorCode=003200; statusCode=401","detail":"SignatureBaseString: POST&https%3A%2F%2Fsandbox-quickbooks.api.intuit.com%2Fv3%2Fcompany%2F123145844963419%2FInvoice%2F357%2Fsend&oauth_consumer_key%3DqyprdLiUxYMs4EBskkejFji8cHbIic%26oauth_nonce%3D58c2db036d2849105135b1cf4f745b90f915ff99%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1522345028%26oauth_token%3Dqyprdj79RtfIkBSkCgJZKdViu9hYCJlY2DH9vhNuGH292KNV%26oauth_version%3D1.0%26sendTo%3Dtrey%2540phish.com","code":"3200","element":null}],"type":"AUTHENTICATION"},"report":null,"queryResponse":null,"batchItemResponse":[],"attachableResponse":[],"syncErrorResponse":null,"requestId":null,"time":1522344912931,"status":null,"cdcresponse":[]}
Has anyone here had success sending an invoice through the QB Rest API? I tried using Postman and it also failed. I've posted about this on Intuit's developer forum here: https://help.developer.intuit.com/s/question/0D50f00005OLgujCAD/unsupported-operation-error-while-attempting-to-send-invoice-through-quickbooks-rest-api?t=1524511489114
Looking to discuss with others that may have also experienced this.
Thanks,
Larry
For anyone following along at home, this turned out to be an issue with the content type. The content type for when you make a send email request needs to be application/octet-stream. I had to modify client.py and mixin.py. I'm not sure if this project is taking merge requests so I'm not making one unless I hear back.
client.py (added content_type parameter)
def misc_operation(self, end_point, request_body, content_type='application/json'):
url = self.api_url + "/company/{0}/{1}".format(self.company_id, end_point)
results = self.make_request("POST", url, request_body, content_type)
return results
mixins.py (set the object name to lowercase since the URL is case sensitive, also passed the octet-stream content type)
class SendMixin(object):
def send(self, qb=None, send_to=None):
if not qb:
qb = QuickBooks()
end_point = "{0}/{1}/send".format(self.qbo_object_name.lower(), self.Id)
if send_to:
end_point = "{0}?sendTo={1}".format(end_point, send_to)
results = qb.misc_operation(end_point, None,'application/octet-stream')
return results
Hopefully this helps someone else. Larry
I have updated the client as you suggested.
invoice.send('aaaaaa@gmail.com'). 'str' object has no attribute 'misc_operation'. any solutions for this one??!
invoice.send('aaaaaa@gmail.com'). 'str' object has no attribute 'misc_operation'. any solutions for this one??!
try to use invoice.send(qb=qb_client, send_to="aaaaaa@gmail.com")
I’ve successfully linked and created a QBO customer but I can’t work out what I need to do to create an invoice.
Can anyone explain invoice = Invoice() please and what fields I need to create it? I can’t work out the Line or how to select a customer for it.