2019-06-21 12:58:16 +02:00
|
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
2019-08-07 20:20:52 +02:00
|
|
|
|
# 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/>.
|
|
|
|
|
|
2019-06-21 12:58:16 +02:00
|
|
|
|
import itertools
|
|
|
|
|
import sys
|
|
|
|
|
import os
|
|
|
|
|
import requests
|
|
|
|
|
|
|
|
|
|
|
2019-06-21 13:06:51 +02:00
|
|
|
|
ME = os.getenv("TAB_ME")
|
|
|
|
|
TOKEN = os.getenv("TAB_TOKEN")
|
|
|
|
|
BASE_URI = os.getenv("TAB_BASE_URI", default="https://tab.zeus.gent")
|
2019-06-21 12:58:16 +02:00
|
|
|
|
|
2019-06-21 13:06:51 +02:00
|
|
|
|
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})")
|
2019-06-21 12:58:16 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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()
|
|
|
|
|
|
|
|
|
|
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
|
2021-08-31 23:08:59 +02:00
|
|
|
|
if issuer == "Tap":
|
|
|
|
|
to_account = TAP_ACCOUNT
|
|
|
|
|
message = f"Zeus WPI | {message}"
|
|
|
|
|
else:
|
|
|
|
|
to_account = FOOD_ACCOUNT
|
|
|
|
|
message = f"{issuer} | {message}"
|
2019-06-21 12:58:16 +02:00
|
|
|
|
|
|
|
|
|
to_line = f"{to_account} {amount}"
|
2019-06-25 01:03:30 +02:00
|
|
|
|
from_line = f"tab {assertion}"
|
2019-06-21 12:58:16 +02:00
|
|
|
|
|
|
|
|
|
else:
|
2021-08-31 23:08:59 +02:00
|
|
|
|
message = f"{debtor} | {message}"
|
2019-06-21 12:58:16 +02:00
|
|
|
|
to_line = f"tab {amount} {assertion}"
|
2021-08-31 23:08:59 +02:00
|
|
|
|
from_line = f";"
|
|
|
|
|
|
|
|
|
|
header = f"{date} {message}"
|
2019-06-21 12:58:16 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return "\n".join([
|
|
|
|
|
header,
|
2019-06-25 01:03:30 +02:00
|
|
|
|
"\t" + to_line.rstrip(),
|
|
|
|
|
"\t" + from_line.rstrip()
|
2019-06-21 12:58:16 +02:00
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
2019-06-21 16:10:39 +02:00
|
|
|
|
]
|
2019-06-21 12:58:16 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main(me, token, file=sys.stdout):
|
|
|
|
|
def get(path):
|
|
|
|
|
return requests.get(
|
2019-06-21 13:06:51 +02:00
|
|
|
|
f"{BASE_URI}{path}",
|
|
|
|
|
headers={
|
|
|
|
|
"Accept": "application/json", "Authorization": f"Token token={token}",
|
|
|
|
|
"User-Agent": USER_AGENT
|
|
|
|
|
}
|
2019-06-21 12:58:16 +02:00
|
|
|
|
).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)
|