cash flow statement report

This commit is contained in:
Roger Oriol
2023-12-27 00:03:54 +01:00
parent 3fb7ec5d7d
commit c1e103010d
3 changed files with 156 additions and 54 deletions

View File

@@ -1,2 +1,150 @@
#!/usr/bin/env bash
echo "TO DO"
#!/usr/bin/env python3
from beancount import loader
from beancount.query import query
from beancount.parser import printer
import argparse
from tabulate import tabulate
from decimal import Decimal
from beancount.core.amount import Amount, sub, mul
from datetime import date
from dateutil.relativedelta import relativedelta
class bcolors:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKCYAN = '\033[96m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
def draw_line():
print('─' * 30)
def get_income_val(obj, key):
if key in obj:
amount = obj[key].get_only_position().units
amount = mul(amount, Decimal(-1.0))
return amount.to_string()
else:
return None
def get_expense_val(obj, key):
if key in obj:
amount = obj[key].get_only_position().units
return amount.to_string()
else:
return None
def print_expenses_table(expenses):
table = []
for key, expense in expenses.items():
parts = key.split(":", 1)
table.append([parts[1], get_expense_val(expenses, key)])
print(tabulate(table))
def get_total_inflows(income):
sum = 0
for account, balance in income.items():
sum = balance if sum == 0 else sum + balance
if sum != 0 and sum.get_only_position() != None:
result = sum.get_only_position().units
return Amount(Decimal(round(result.number, 2) * Decimal(-1.0)), result.currency)
else:
return Amount(Decimal(0), "EUR")
def get_total_outflows(expenses):
sum = 0
for account, balance in expenses.items():
sum = balance if sum == 0 else sum + balance
if sum != 0 and sum.get_only_position() != None:
result = sum.get_only_position().units
return Amount(Decimal(round(result.number, 2)), result.currency)
else:
return Amount(Decimal(0), "EUR")
def print_report(start_date, period, income, expenses):
print(f"{bcolors.BOLD}Cash Flow Statement (period={period}, start_date={start_date}){bcolors.ENDC}")
draw_line()
print(f"{bcolors.BOLD}Inflows{bcolors.ENDC}")
print(f"\t{bcolors.BOLD}Income{bcolors.ENDC}")
print(tabulate([
["Salari", get_income_val(income,"Income:Work:Zurich:Salari")],
["Tickets Restaurant", get_income_val(income,"Income:Work:Zurich:TicketsRestaurant")],
["Targeta Transport", get_income_val(income,"Income:Work:Zurich:TargetaTransport")],
["Seguro Mèdic", get_income_val(income,"Income:Work:Zurich:SeguroMedic")],
["Gimnàs", get_income_val(income,"Income:Work:Zurich:Gimnas")]
]))
print(f"\t{bcolors.BOLD}Income from Investment{bcolors.ENDC}")
print(tabulate([
["Capital Gains", get_income_val(income,"Income:Invest:R4:CapitalGains")],
["Dividends", get_income_val(income,"Income:Invest:R4:Dividends")],
["Rentabilitat Estalvis", get_income_val(income,"Income:Savings:Caixabank:RentabilitatEstalvis")]
]))
print(f"\t{bcolors.BOLD}Other Inflows{bcolors.ENDC}")
print(tabulate([
["Transferències", get_income_val(income,"Income:Other:Caixabank:Transferencia")],
["Bizum", get_income_val(income,"Income:Other:Caixabank:Bizum")],
["Devolucions", get_income_val(income,"Income:Other:Devolucions")]
]))
print(tabulate([
["Total Inflows", f"{bcolors.BOLD}{get_total_inflows(income).to_string()}{bcolors.ENDC}"]
]))
draw_line()
print(f"{bcolors.BOLD}Outflows{bcolors.ENDC}")
print_expenses_table(expenses)
print(tabulate([
["Total Outflows", f"{bcolors.BOLD}{get_total_outflows(expenses).to_string()}{bcolors.ENDC}"]
]))
draw_line()
net_cash_flow = sub(get_total_inflows(income), get_total_outflows(expenses))
print(tabulate([
["NET CASH FLOW", f"{bcolors.BOLD}{bcolors.OKGREEN if net_cash_flow.number >= 0 else bcolors.FAIL}{net_cash_flow.to_string()}{bcolors.ENDC}"]
]))
def get_income(entries, options, period, start_date):
period_delta = relativedelta(months=1) if period == "monthly" else relativedelta(years=1)
end_date = date.fromisoformat(start_date) + period_delta
income_query = f"SELECT account, sum(position) FROM OPEN ON {start_date} CLOSE ON {end_date.isoformat()} WHERE account ~ \"Income\""
rtypes, rrows = query.run_query(
entries, options, income_query)
income = {}
for row in rrows:
income[row.account] = row.sum_position
return income
def get_expenses(entries, options, period, start_date):
period_delta = relativedelta(months=1) if period == "monthly" else relativedelta(years=1)
end_date = date.fromisoformat(start_date) + period_delta
expenses_query = f"SELECT account, sum(position) FROM OPEN ON {start_date} CLOSE ON {end_date.isoformat()} WHERE account ~ \"Expenses\""
rtypes, rrows = query.run_query(
entries, options, expenses_query)
expenses = {}
for row in rrows:
expenses[row.account] = row.sum_position
return expenses
def main():
parser = argparse.ArgumentParser(description='Generate cash flow report')
parser.add_argument('start_date', metavar='start_date', type=str, nargs=1,
help='Start date (end date will be one month after if monthly report or one year after if yearly report)')
parser.add_argument('-p', metavar='period', type=str, choices=["monthly", "yearly"], default="monthly", required=False,
help='Period (monthly or yearly)')
args = parser.parse_args()
start_date = args.start_date[0]
period = args.p
filename = "ledger/main.beancount"
entries, errors, options = loader.load_file(filename)
if errors:
printer.print_errors(errors)
income = get_income(entries, options, period, start_date)
expenses = get_expenses(entries, options, period, start_date)
print_report(start_date, period, income, expenses)
main()

View File

@@ -32,6 +32,7 @@
1970-01-01 open Income:Savings:Caixabank:RentabilitatEstalvis EUR
1970-01-01 open Income:Invest:R4:Dividends EUR
1970-01-01 open Income:Invest:R4:CapitalGains EUR
1970-01-01 open Income:Other:Devolucions EUR
1970-01-01 open Expenses:R4:Comissions EUR
1970-01-01 open Expenses:Taxes:IRPF EUR

View File

@@ -26,7 +26,6 @@
Assets:Invest:R4:MSFT 4 MSFT {341.8 USD}
Equity:Opening-Balances:USD
<<<<<<< HEAD
2024-01-01 balance Assets:Liquid:Caixabank:Corrent 18903.80 EUR
2024-01-01 balance Assets:Liquid:Caixabank:Estalvi 12666.49 EUR
2024-01-01 balance Assets:Liquid:R4:EUR 44.04 EUR
@@ -38,55 +37,29 @@
2024-01-01 balance Assets:Invest:R4:PLTR 10 PLTR
2024-01-01 balance Assets:Invest:R4:MSFT 4 MSFT
2024-01-01 balance Assets:Benefits:Edenred:TicketsRestaurant 0 EUR
2024-01-01 balance Assets:Benefits:Edenred:TarjetaTransport 0 EUR
2024-01-01 balance Assets:Benefits:Edenred:TargetaTransport 0 EUR
2024-01-01 balance Assets:PersonalProperty:VivendaPrincipal 0 EUR
2024-01-01 balance Assets:PersonalProperty:Cotxe 10000 EUR
2024-01-01 balance Assets:PersonalProperty:JoiesArtCollecionables 1250 EUR
2024-01-01 balance Assets:PersonalProperty:MetallsPreciosos 0 EUR
2024-01-01 balance Assets:PersonalProperty:AltresPropietats 0 EUR
2024-01-01 balance Assets:Debt:DeutesPerCobrar 0 EUR
=======
2024-01-01 balance Assets:Liquid:Caixabank:Corrent 18903.80 EUR
2024-01-01 balance Assets:Liquid:Caixabank:Estalvi 12666.49 EUR
2024-01-01 balance Assets:Liquid:R4:EUR 44.04 EUR
2024-01-01 balance Assets:Invest:R4:Amundi:MSCIWRLD 86.005 AMNDMSCIWRLD
2024-01-01 balance Assets:Invest:R4:Vanguard:EMMK 14.99 VANEMMK
2024-01-01 balance Assets:Invest:R4:Fidelity:GLTECH 344.47 FIGLTECH
2024-01-01 balance Assets:Invest:R4:Amundi:SUSTINC 11.295 AMNDSUSINC
2024-01-01 balance Assets:Invest:R4:BNP:DISTECH 0.359 BNPDISTECH
2024-01-01 balance Assets:Invest:R4:PLTR 10 PLTR
2024-01-01 balance Assets:Invest:R4:MSFT 4 MSFT
2024-01-01 balance Assets:Benefits:Edenred:TicketsRestaurant 0 EUR
2024-01-01 balance Assets:Benefits:Edenred:TargetaTransport 0 EUR
2024-01-01 balance Assets:PersonalProperty:VivendaPrincipal 0 EUR
2024-01-01 balance Assets:PersonalProperty:Cotxe 10000 EUR
2024-01-01 balance Assets:PersonalProperty:JoiesArtCollecionables 1250 EUR
2024-01-01 balance Assets:PersonalProperty:MetallsPreciosos 0 EUR
2024-01-01 balance Assets:PersonalProperty:AltresPropietats 0 EUR
2024-01-01 balance Assets:Debt:DeutesPerCobrar 0 EUR
>>>>>>> ac34f2f (balance sheet report)
2024-01-01 * "Zurich" "Cuota gimnàs Andjoy"
amortize_months: 12
;amortize_months: 12
Expenses:Gimnàs 508.80 EUR
Income:Work:Zurich:Gimnas
2024-01-01 * "Zurich" "Cuota seguro salut Cigna Salud OPT (solo cobertura extra hospitalaria)"
amortize_months: 12
;amortize_months: 12
Expenses:Medic 414.60 EUR
Income:Work:Zurich:SeguroMedic
2024-01-01 * "Zurich" "Targeta Transport"
<<<<<<< HEAD
Assets:Benefits:Edenred:TarjetaTransport 40 EUR
Income:Work:Zurich:TarjetaTransport
=======
Assets:Benefits:Edenred:TargetaTransport 40 EUR
Assets:Benefits:Edenred:TargetaTransport 40 EUR
Income:Work:Zurich:TargetaTransport
>>>>>>> ac34f2f (balance sheet report)
2024-01-01 * "Zurich" "Targeta Restaurant"
Assets:Benefits:Edenred:TicketsRestaurant 209 EUR
Income:Work:Zurich:TicketsRestaurant
<<<<<<< HEAD
2024-02-01 balance Assets:Liquid:Caixabank:Corrent 18903.80 EUR
2024-02-01 balance Assets:Liquid:Caixabank:Estalvi 12666.49 EUR
;2024-02-01 balance Assets:Liquid:R4:EUR 44.04 EUR
@@ -98,30 +71,10 @@
2024-02-01 balance Assets:Invest:R4:PLTR 10 PLTR
;2024-02-01 balance Assets:Invest:R4:MSFT 4 MSFT
2024-02-01 balance Assets:Benefits:Edenred:TicketsRestaurant 209 EUR
2024-02-01 balance Assets:Benefits:Edenred:TarjetaTransport 40 EUR
2024-02-01 balance Assets:Benefits:Edenred:TargetaTransport 40 EUR
2024-02-01 balance Assets:PersonalProperty:VivendaPrincipal 0 EUR
2024-02-01 balance Assets:PersonalProperty:Cotxe 10000 EUR
2024-02-01 balance Assets:PersonalProperty:JoiesArtCollecionables 1250 EUR
2024-02-01 balance Assets:PersonalProperty:MetallsPreciosos 0 EUR
2024-02-01 balance Assets:PersonalProperty:AltresPropietats 0 EUR
2024-02-01 balance Assets:Debt:DeutesPerCobrar 0 EUR
=======
2024-02-01 balance Assets:Liquid:Caixabank:Corrent 18903.80 EUR
2024-02-01 balance Assets:Liquid:Caixabank:Estalvi 12666.49 EUR
2024-02-01 balance Assets:Liquid:R4:EUR 44.04 EUR
2024-02-01 balance Assets:Invest:R4:Amundi:MSCIWRLD 86.005 AMNDMSCIWRLD
2024-02-01 balance Assets:Invest:R4:Vanguard:EMMK 14.99 VANEMMK
2024-02-01 balance Assets:Invest:R4:Fidelity:GLTECH 344.47 FIGLTECH
2024-02-01 balance Assets:Invest:R4:Amundi:SUSTINC 11.295 AMNDSUSINC
2024-02-01 balance Assets:Invest:R4:BNP:DISTECH 0.359 BNPDISTECH
2024-02-01 balance Assets:Invest:R4:PLTR 10 PLTR
2024-02-01 balance Assets:Invest:R4:MSFT 4 MSFT
2024-02-01 balance Assets:Benefits:Edenred:TicketsRestaurant 209 EUR
2024-02-01 balance Assets:Benefits:Edenred:TargetaTransport 40 EUR
2024-02-01 balance Assets:PersonalProperty:VivendaPrincipal 0 EUR
2024-02-01 balance Assets:PersonalProperty:Cotxe 10000 EUR
2024-02-01 balance Assets:PersonalProperty:JoiesArtCollecionables 1250 EUR
2024-02-01 balance Assets:PersonalProperty:MetallsPreciosos 0 EUR
2024-02-01 balance Assets:PersonalProperty:AltresPropietats 0 EUR
2024-02-01 balance Assets:Debt:DeutesPerCobrar 0 EUR
>>>>>>> ac34f2f (balance sheet report)