Skip to content

Commit f4e7661

Browse files
committed
Fix issue with invoice sharable link
1 parent 6943dec commit f4e7661

File tree

8 files changed

+268
-113
lines changed

8 files changed

+268
-113
lines changed

Pipfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pytest-cov = "*"
1111

1212
[packages]
1313
urllib3 = ">=2.1.0"
14-
intuit-oauth = "==1.2.5"
14+
intuit-oauth = "==1.2.6"
1515
requests = ">=2.31.0"
1616
requests_oauthlib = ">=1.3.1"
1717
setuptools = "*"

Pipfile.lock

Lines changed: 208 additions & 95 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -252,15 +252,23 @@ One example is `include=allowduplicatedocnum` on the Purchase object. You can ad
252252

253253
purchase.save(qb=self.qb_client, params={'include': 'allowduplicatedocnum'})
254254

255-
Other operations
255+
Sharable Invoice Link
256256
----------------
257-
Add Sharable link for an invoice sent to external customers (minorversion must be set to 36 or greater):
257+
To add a sharable link for an invoice, make sure the AllowOnlineCreditCardPayment is set to True and BillEmail is set to a invalid email address:
258258

259-
invoice.invoice_link = true
259+
invoice.AllowOnlineCreditCardPayment = True
260+
invoice.BillEmail = EmailAddress()
261+
invoice.BillEmail.Address = '[email protected]'
260262

263+
When you query the invoice include the following params (minorversion must be set to 36 or greater):
261264

262-
Void an invoice:
265+
invoice = Invoice.get(id, qb=self.qb_client, params={'include': 'invoiceLink'})
263266

267+
268+
Void an invoice
269+
----------------
270+
Call `void` on any invoice with an Id:
271+
264272
invoice = Invoice()
265273
invoice.Id = 7
266274
invoice.void(qb=client)

quickbooks/client.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,6 @@ def make_request(self, request_type, url, request_body=None, content_type='appli
155155
if request_id:
156156
params['requestid'] = request_id
157157

158-
if self.invoice_link:
159-
params['include'] = 'invoiceLink'
160-
161158
if not request_body:
162159
request_body = {}
163160

@@ -242,9 +239,9 @@ def process_request(self, request_type, url, headers="", params="", data=""):
242239
return self.session.request(
243240
request_type, url, headers=headers, params=params, data=data)
244241

245-
def get_single_object(self, qbbo, pk):
242+
def get_single_object(self, qbbo, pk, params=None):
246243
url = "{0}/company/{1}/{2}/{3}/".format(self.api_url, self.company_id, qbbo.lower(), pk)
247-
result = self.get(url, {})
244+
result = self.get(url, {}, params=params)
248245

249246
return result
250247

quickbooks/mixins.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,11 @@ class ReadMixin(object):
9494
qbo_json_object_name = ""
9595

9696
@classmethod
97-
def get(cls, id, qb=None):
97+
def get(cls, id, qb=None, params=None):
9898
if not qb:
9999
qb = QuickBooks()
100100

101-
json_data = qb.get_single_object(cls.qbo_object_name, pk=id)
101+
json_data = qb.get_single_object(cls.qbo_object_name, pk=id, params=params)
102102

103103
if cls.qbo_json_object_name != '':
104104
return cls.from_json(json_data[cls.qbo_json_object_name])

tests/integration/test_base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def setUp(self):
1717
)
1818

1919
self.qb_client = QuickBooks(
20-
minorversion=69,
20+
minorversion=73,
2121
auth_client=self.auth_client,
2222
refresh_token=os.environ.get('REFRESH_TOKEN'),
2323
company_id=os.environ.get('COMPANY_ID'),

tests/integration/test_invoice.py

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1+
from datetime import datetime
2+
13
from quickbooks.objects.base import CustomerMemo
24
from quickbooks.objects.customer import Customer
35
from quickbooks.objects.detailline import SalesItemLine, SalesItemLineDetail
46
from quickbooks.objects.invoice import Invoice
57
from quickbooks.objects.item import Item
8+
from quickbooks.objects.base import EmailAddress
69
from tests.integration.test_base import QuickbooksTestCase
710
import uuid
811

9-
class InvoiceTest(QuickbooksTestCase):
10-
def create_invoice(self, customer, request_id=None):
11-
invoice = Invoice()
1212

13+
class InvoiceTest(QuickbooksTestCase):
14+
def create_invoice_line(self):
1315
line = SalesItemLine()
1416
line.LineNum = 1
1517
line.Description = "description"
@@ -18,7 +20,11 @@ def create_invoice(self, customer, request_id=None):
1820
item = Item.all(max_results=1, qb=self.qb_client)[0]
1921

2022
line.SalesItemLineDetail.ItemRef = item.to_ref()
21-
invoice.Line.append(line)
23+
return line
24+
25+
def create_invoice(self, customer, request_id=None):
26+
invoice = Invoice()
27+
invoice.Line.append(self.create_invoice_line())
2228

2329
invoice.CustomerRef = customer.to_ref()
2430

@@ -86,3 +92,35 @@ def test_void(self):
8692
self.assertEqual(query_invoice.Balance, 0.0)
8793
self.assertEqual(query_invoice.TotalAmt, 0.0)
8894
self.assertIn('Voided', query_invoice.PrivateNote)
95+
96+
def test_invoice_link(self):
97+
# Sharable link for the invoice sent to external customers.
98+
# The link is generated only for invoices with online payment enabled and having a valid customer email address.
99+
# Include query param `include=invoiceLink` to get the link back on query response.
100+
101+
# Create test customer
102+
customer_name = datetime.now().strftime('%d%H%M%S')
103+
customer = Customer()
104+
customer.DisplayName = customer_name
105+
customer.save(qb=self.qb_client)
106+
107+
# Create an invoice with sharable link flags set
108+
invoice = Invoice()
109+
invoice.CustomerRef = customer.to_ref()
110+
111+
# BillEmail must be set for Sharable link to work!
112+
invoice.BillEmail = EmailAddress()
113+
invoice.BillEmail.Address = '[email protected]'
114+
115+
invoice.PrivateNote = 'This is a test invoice'
116+
invoice.DueDate = '2024-12-31'
117+
invoice.AllowOnlineCreditCardPayment = True
118+
invoice.AllowOnlineACHPayment = True
119+
invoice.Line.append(self.create_invoice_line())
120+
invoice.save(qb=self.qb_client)
121+
122+
# You must set the params when doing a query for the invoice
123+
query_invoice = Invoice.get(invoice.Id, qb=self.qb_client, params={'include': 'invoiceLink'})
124+
125+
self.assertIsNotNone(query_invoice.InvoiceLink)
126+
self.assertIn('https', query_invoice.InvoiceLink)

tests/unit/objects/test_invoice.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ def test_to_ref(self):
5151
self.assertEqual(ref.name, 1) # should be DocNumber
5252
self.assertEqual(ref.value, 2) # should be Id
5353

54-
5554
class DeliveryInfoTests(unittest.TestCase):
5655
def test_init(self):
5756
info = DeliveryInfo()

0 commit comments

Comments
 (0)