如何通过QuickBooks API获取完整的按产品/服务明细销售报告
问题
我用Python代码尝试获取QuickBooks的「按产品/服务明细销售」报告数据时遇到几个问题:
- 官方文档里的报告实体是
SalesByProduct,但实际调用的端点是ItemSales,这让我很困惑。 - 需要修改代码,获取报告的所有默认指标:
- 产品/服务
- 日期
- 交易类型
- 编号
- 客户名称
- 备注/描述
- 数量
- 单价
- 金额
- 余额
- 当前代码只返回96条数据,但UI里显示有2315行,想知道报表API是否有分页机制,该怎么实现。
- 我在UI里查看报告时没有设置任何分组,要看到行级数据是不是不该设置
summarize_column_by属性?
当前代码如下:
def fetch_sales_by_product(access_token): url = f'https://quickbooks.api.intuit.com/v3/company/11111111111/reports/ItemSales' headers = { 'Authorization': f'Bearer {access_token}', 'Accept': 'application/json' } params = { 'start_date': '2021-01-01', 'end_date': '2024-04-01', 'summarize_column_by': 'ProductsAndServices' } all_data = [] counter = 1 while True: response = requests.get(url, headers=headers, params=params) print(f"{response.status_code=}") if response.status_code != 200: raise Exception(f"Failed to fetch report: {response.text}" ) data = response.json() all_data.extend(data['Rows']['Row']) counter += 1 return all_data
解决方案
端点澄清
QuickBooks UI中的「按产品/服务明细销售」报告,对应API的端点就是ItemSales。文档中提到的SalesByProduct是报告实体的名称,实际调用时使用ItemSales是正确的,无需困惑。
获取全部指标的参数调整
- 移除
summarize_column_by参数:既然不需要分组查看行级数据,这个参数会按产品/服务聚合数据,必须删掉才能拿到明细行。 - 指定
columns参数:明确列出需要的所有指标对应的API列名,确保返回完整数据:
列名与需求指标的对应关系:columns=Item,Date,TransactionType,DocNumber,Customer,Description,Quantity,Rate,Amount,Balance- Item → 产品/服务
- Date → 日期
- TransactionType → 交易类型
- DocNumber → 编号
- Customer → 客户名称
- Description → 备注/描述
- Quantity → 数量
- Rate → 单价
- Amount → 金额
- Balance → 余额
分页实现
报表API默认分页返回数据,每次返回条数有限。实现分页只需:
- 在请求参数中加入
page,初始值为1,每次循环递增。 - 当返回的
Rows.Row为空,或者已获取的数据量达到响应中的totalCount时,终止循环。
修改后的完整代码
import requests def fetch_sales_by_product(access_token): company_id = '11111111111' url = f'https://quickbooks.api.intuit.com/v3/company/{company_id}/reports/ItemSales' headers = { 'Authorization': f'Bearer {access_token}', 'Accept': 'application/json' } all_data = [] page = 1 while True: params = { 'start_date': '2021-01-01', 'end_date': '2024-04-01', 'columns': 'Item,Date,TransactionType,DocNumber,Customer,Description,Quantity,Rate,Amount,Balance', 'page': page } response = requests.get(url, headers=headers, params=params) print(f"{response.status_code=}, 当前页码: {page}") if response.status_code != 200: raise Exception(f"获取报告失败: {response.text}" ) data = response.json() rows = data.get('Rows', {}).get('Row', []) if not rows: break all_data.extend(rows) # 按总条数判断是否结束分页 total_count = data.get('totalCount', 0) if len(all_data) >= total_count: break page += 1 return all_data
内容的提问来源于stack exchange,提问作者mongotop
相关产品推荐
相关产品推荐

