110 lines
3 KiB
Python
Executable file
110 lines
3 KiB
Python
Executable file
#!/usr/bin/env python3
|
||
|
||
# tab2ledger
|
||
# Copyright © 2019 Midgard
|
||
#
|
||
# This program is free software: you can redistribute it and/or modify it under the terms of the
|
||
# GNU General Public License as published by the Free Software Foundation, either version 3 of the
|
||
# License, or (at your option) any later version.
|
||
#
|
||
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
# General Public License for more details.
|
||
#
|
||
# You should have received a copy of the GNU General Public License along with this program.
|
||
# If not, see <http://www.gnu.org/licenses/>.
|
||
|
||
import itertools
|
||
import sys
|
||
import os
|
||
import requests
|
||
|
||
|
||
ME = os.getenv("TAB_ME")
|
||
TOKEN = os.getenv("TAB_TOKEN")
|
||
BASE_URI = os.getenv("TAB_BASE_URI", default="https://tab.zeus.gent")
|
||
|
||
TAP_ACCOUNT = os.getenv("LEDGER_TAP_ACCOUNT", default="Expenses:Zeuskelder:Drinks and snacks")
|
||
FOOD_ACCOUNT = os.getenv("LEDGER_FOOD_ACCOUNT", default="Expenses:Zeuskelder:Food")
|
||
|
||
TAB2LEDGER_NAME = "tab2ledger"
|
||
TAB2LEDGER_VERSION = "1.0"
|
||
TAB2LEDGER_URL = "https://git.zeus.gent/midgard/tab2ledger"
|
||
USER_AGENT = os.getenv("TAB2LEDGER_USER_AGENT", default=f"{TAB2LEDGER_NAME} {TAB2LEDGER_VERSION} ({TAB2LEDGER_URL})")
|
||
|
||
|
||
def formatted_price(cents):
|
||
return f"€ {cents / 100}"
|
||
|
||
|
||
def balance_assertion(balance):
|
||
return \
|
||
f"= {formatted_price(balance)}" \
|
||
if balance is not None else ""
|
||
|
||
|
||
def formatted_transaction(transaction, me, balance_after=None):
|
||
issuer = transaction["issuer"]
|
||
debtor = transaction["debtor"]
|
||
date = transaction["time"][:10]
|
||
amount = formatted_price(transaction["amount"])
|
||
|
||
message = (
|
||
transaction["message"].replace("1 ", "").replace(" and ", " en ")
|
||
if issuer == "Tap" else
|
||
transaction["message"]
|
||
).strip()
|
||
|
||
header = f"{date} {message}"
|
||
|
||
assertion = balance_assertion(balance_after)
|
||
|
||
if debtor == me:
|
||
# If the issuer wasn't Tap, we assume the money we gave was for food – manual change to the
|
||
# output required if it wasn't
|
||
to_account = TAP_ACCOUNT if issuer == "Tap" else FOOD_ACCOUNT
|
||
|
||
to_line = f"{to_account} {amount}"
|
||
from_line = f"tab {assertion}"
|
||
|
||
else:
|
||
to_line = f"tab {amount} {assertion}"
|
||
from_line = f"; {debtor}"
|
||
|
||
|
||
return "\n".join([
|
||
header,
|
||
"\t" + to_line.rstrip(),
|
||
"\t" + from_line.rstrip()
|
||
])
|
||
|
||
|
||
def formatted_transactions(transactions, final_balance, me):
|
||
all_but_last = itertools.islice(transactions, len(transactions) - 1)
|
||
return [
|
||
*(formatted_transaction(t, me) for t in all_but_last),
|
||
formatted_transaction(transactions[-1], me, final_balance)
|
||
]
|
||
|
||
|
||
def main(me, token, file=sys.stdout):
|
||
def get(path):
|
||
return requests.get(
|
||
f"{BASE_URI}{path}",
|
||
headers={
|
||
"Accept": "application/json", "Authorization": f"Token token={token}",
|
||
"User-Agent": USER_AGENT
|
||
}
|
||
).json()
|
||
|
||
balance = get(f"/users/{me}")["balance"]
|
||
transactions = get(f"/users/{me}/transactions")
|
||
|
||
print(
|
||
"\n\n".join(formatted_transactions(transactions, balance, me)),
|
||
file=file
|
||
)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main(ME, TOKEN)
|