Script

Hey there, fellow demo environment creator! If you've ever found yourself in the delightful position of needing to whip up some demo environments, you know the struggle of conjuring up a hefty load of transactions for your users to play with. I recently faced this challenge while working on software that integrates with QuickBooks Online. Our sales team needed a slick demo showcasing how our system seamlessly interacts with QuickBooks Online, handling invoices like a pro.

Now, being the live demo enthusiasts that we are, we couldn't just settle for anything less than a fully functional system bustling with transactions ready for interaction. But fear not, my friends, for I have just the solution - a nifty Python script that taps into QuickBooks Online's web APIs to generate as many invoices as your heart desires.

Before you dive in, it's helpful to have a grasp of QuickBooks Online's APIs and APIs in general. If you're new to this realm, fear not! QuickBooks provides a handy Getting Started - Developer's Guide to get you up to speed. And trust me, it's not as daunting as it sounds. Plus, their API Explorer is a godsend for exploring each API in detail.

What You'll Need:

  1. A QuickBooks Online Sandbox (or Production) Company: Don't fret if you don't have one yet; signing up for a QBO Developer account grants you access to up to 10 sandbox companies, complete with test data.
  2. At Least One Item (Product/Service): My script randomly selects from a pool of 8 items to create invoice detail lines, injecting a touch of variety into your invoices.
  3. At Least One Customer ID: Grab this from your QBO environment.
  4. Your Company (Realm) ID: Essential for authentication purposes.
  5. An Authorization Access Token: Head over to the QBO OAuth Playground to snag yours. Just remember, these tokens have a one-hour lifespan, so keep that refresh button handy!

Once you've got all your ducks in a row, copy the code below into a .py file and let the magic unfold:


import json
import random
import requests

# List of items with their respective properties
items = [
    {
        "Name": "Box Tape (2.5in.-200ft)",
        "Description": "1 Box Tape, 2.5in., 200ft",
        "UnitPrice": 6.99,
        "Id": "28"
    },
    {
        "Name": "Corrugated Boxes (STD12Pk, 12x12x12)",
        "Description": "12 Pack of Standard Corrugated Boxes, L:12(in)xW:12(in.)xH:12(in.)",
        "UnitPrice": 29.99,
        "Id": "22"
    },
    {
        "Name": "Corrugated Boxes (STD3Pk, 12x12x12)",
        "Description": "3 Pack of Standard Corrugated Boxes, L:12(in)xW:12(in.)xH:12(in.)",
        "UnitPrice": 18.99,
        "Id": "21"
    },
    {
        "Name": "Premium Storage Box (LARGE, 36x36x36)",
        "Description": "1 Premium Storage Box, LARGE L:36(in)xW:36(in.)xH:36(in.)",
        "UnitPrice": 12.99,
        "Id": "27"
    },
    {
        "Name": "Premium Storage Box (MEDIUM, 24x24x24)",
        "Description": "1 Premium Storage Box, MEDIUM L:24(in)xW:24(in.)xH:24(in.)",
        "UnitPrice": 8.99,
        "Id": "25"
    },
    {
        "Name": "Premium Storage Box (SMALL, 12x12x12)",
        "Description": "1 Premium Storage Box, SMALL L:12(in)xW:12(in.)xH:12(in.)",
        "UnitPrice": 5.99,
        "Id": "26"
    },
    {
        "Name": "USPS Box (Priority T1, 10x12x3)",
        "Description": "1 USPS Priority Box, L:10(in)xW:12(in.)xH:3(in.)",
        "UnitPrice": 7.99,
        "Id": "23"
    },
    {
        "Name": "USPS Box (Priority T2, 9x12x1)",
        "Description": "1 USPS Priority Box, L:9(in)xW:12(in.)xH:1(in.)",
        "UnitPrice": 5.99,
        "Id": "24"
    }
]

# Set the COMPANY-REALM-ID and ACCESS-TOKEN variables
COMPANY_REALM_ID = "YOUR COMPANY REALM ID GOES HERE"
ACCESS_TOKEN = "YOUR ACCESS TOKEN GOES HERE"

# Base URL for the API endpoint
base_url = f"https://sandbox-quickbooks.api.intuit.com/v3/company/{COMPANY_REALM_ID}/invoice?minorversion=70"

# Iterate over each payload
for i in range(3):                    #Change range to change quantity of invoices created.
    doc_number = 103035 + i           #Change your starting invoice number
    num_lines = random.randint(1, 6)  #Change how many min. and max. invoice detail lines your want used.
    total_amount = 0
    lines = []
    
    # Generate line items for the payload
    for _ in range(num_lines):
        item = random.choice(items)
        qty = random.randint(10, 200) #Change the min. and max. of the Qty of Items to use.
        amount = round(qty * item["UnitPrice"], 2)
        total_amount += amount
        description = item.get("Description", item["Name"])
        line = {
            "Amount": amount,
            "Description": description,
            "DetailType": "SalesItemLineDetail",
            "SalesItemLineDetail": {
                "ItemRef": {
                    "value": item["Id"]
                },
                "TaxCodeRef": {
                    "value": "TAX"
                },
                "DiscountAmt": 0.00,
                "Qty": qty,
                "UnitPrice": item["UnitPrice"]
            }
        }
        lines.append(line)
    
    # Create the JSON payload
    json_payload = {
        "DocNumber": doc_number,
        "TxnDate": "2024-03-01",          #Set the Invoice Date you want.
        "DueDate": "2024-04-01",          #Set the Invoice Due Date you want.
        "PrintStatus": "NeedToPrint",
        "EmailStatus": "NotSet",
        "ApplyTaxAfterDiscount": False,
        "BillAddr": {"Id": "110"},        #You can exclude this if you want.
        "CustomerRef": {"value": "72"},   #Put your Customer ID here. ID's can be found by editing the Customer in QBO and looking at the URL for the ID.
        "ShipAddr": {"Id": "110"},        #You can exclude this if you want.
        "Line": lines
    }
    
    # Convert the payload to JSON format
    payload_json = json.dumps(json_payload)
    
    # Set up the headers
    headers = {
        "Authorization": f"Bearer {ACCESS_TOKEN}",
        "Content-Type": "application/json"
    }
    
    # Send the POST request
    response = requests.post(base_url, headers=headers, data=payload_json)
    
    # Check if the request was successful
    if response.status_code == 200:
        print(f"Payload {doc_number} sent successfully.")
    else:
        print(f"Error sending payload {doc_number}. Status code: {response.status_code}")


        

And voilà! You're all set to unleash a torrent of invoices upon your demo environment. Plus, if you're feeling adventurous, you can easily adapt this script for other QBO Web APIs by tweaking the JSON payloads.

I hope this little instructional blog has armed you with the tools you need to save time and impress your audience with dazzling demo environments. Happy coding! 🚀