Skip to content

Instantly share code, notes, and snippets.

@Sytten
Last active March 7, 2023 18:25
Show Gist options
  • Save Sytten/b53191204af0929d295be93303df0a90 to your computer and use it in GitHub Desktop.
Save Sytten/b53191204af0929d295be93303df0a90 to your computer and use it in GitHub Desktop.
WaveApps Accounting

Instructions

How to extract data from Wave Apps since their export functions really suck.

Receipts

  1. Go to Settings -> Data Export -> Export all receipts as a ZIP file
  2. Download and extract the zip sent by email
  3. Remove the receipts from other years
  4. Run for file in *.png; do convert ${file} ${file%.*}.pdf; done to convert all png to pdf
  5. Run rm *.png to delete all png

Expenses

  1. Open the network tab
  2. Go to Accounting -> Transactions
  3. Add the filters for the year and categories
  4. Get the Graphql Query and variables sent to the backend
  5. Go in Postman and paste it in the GraphQL editor
  6. Change the variable "first": 100 to something larger
  7. Set the Authorization header to the Bearer token sent with the network tab request
  8. Send and save the data to JSON
  9. Run the python script attached to produce a CSV
    • Paths will need to be adjusted
    • Sale taxes will need to be changed (unless you happen to live where I live)

NOTE: Their graphql API doesn't actually whitelist queries, but since it is not documented I prefer to use the persisted one (I imagine they use APQ) so I don't have to write it myself.

import json
import csv
FILE_IN = '/Users/Sytten/Desktop/transactions.json'
FILE_OUT = '/Users/Sytten/Desktop/transactions.csv'
def main():
transactions = []
with open(FILE_IN, 'r') as input:
data = json.load(input)
for transaction in data['data']['business']['transactions']['edges']:
t = transaction['node']
line = t['lineItems'][0]
total = float(t['amount'])
qst = 0
gst = 0
for tax in line['taxSummary']['taxLiabilities']:
if tax['salesTax']['name'] == 'QST':
qst = float(tax['amount'])
if tax['salesTax']['name'] == 'GST':
gst = float(tax['amount'])
vendor = 'unknown'
if line['vendor']:
vendor = line['vendor']['name']
transactions.append({
"date": t['date'],
"vendor": vendor,
"amount": total-qst-gst,
"gst": gst,
"qst": qst,
"total": total,
"currency": t['currency']['code'],
"category": line['label'],
"description": t['description'],
})
transactions = sorted(transactions, key=lambda t: t['total'], reverse=True)
with open(FILE_OUT, 'w') as output:
fieldnames = ['date', 'vendor', 'amount',
'gst', 'qst', 'total', 'currency', 'category', 'description']
writer = csv.DictWriter(output, fieldnames=fieldnames)
writer.writeheader()
for transaction in transactions:
transaction['amount'] = "%.2f" % transaction['amount']
transaction['gst'] = "%.2f" % transaction['gst']
transaction['qst'] = "%.2f" % transaction['qst']
transaction['total'] = "%.2f" % transaction['total']
writer.writerow(transaction)
if __name__ == "__main__":
main()
{
"operationName": "TransactionsListPage",
"variables": {
"businessId": "CHANGE ME",
"filters": {
"categoryIds": [
"CHANGEME"
],
"startDate": "2022-01-01",
"endDate": "2022-12-31"
},
"subtypes": [
"UNCATEGORIZED_INCOME",
"UNCATEGORIZED_EXPENSE",
"CASH_AND_BANK",
"CREDIT_CARD",
"LOANS",
"NON_RETAINED_EARNINGS",
"MONEY_IN_TRANSIT",
"DUE_TO_YOU_AND_OTHER_OWNERS",
"CUSTOMER_PREPAYMENTS_AND_CREDITS",
"INVENTORY",
"PROPERTY_PLANT_EQUIPMENT",
"VENDOR_PREPAYMENTS_AND_CREDITS",
"OTHER_CURRENT_ASSETS",
"OTHER_LONG_TERM_ASSETS",
"PAYABLE",
"OTHER_CURRENT_LIABILITY",
"OTHER_LONG_TERM_LIABILITY",
"PROPERTY_PLANT_EQUIPMENT"
],
"first": 500,
"sort": [
"DATE_DESC"
]
},
"extensions": {
"persistedQuery": {
"version": 1,
"sha256Hash": "fc4a7abf21e493c11a251565efd9881fe53998e340a3b1687a162020e722aed4"
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment