Files
contabilitat/commands/pending-shared-expenses

108 lines
3.1 KiB
Plaintext
Raw Normal View History

2025-10-04 11:45:40 +02:00
#!/usr/bin/env python3
from beancount import loader
from beancount.query import query
from beancount.core.data import Transaction
from beancount.parser import printer
import argparse
from datetime import date, timedelta
from tabulate import tabulate
from collections import defaultdict
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 get_shared_expenses(entries, options, start_date, end_date):
expenses_query = f"""SELECT date, account, value(position) FROM
date >= {start_date} AND
date < {end_date.isoformat()}
WHERE account ~ \"Expenses:Lloguer\" OR account ~ \"Expenses:FacturesUtilitats\""""
rtypes, rrows = query.run_query(
entries, options, expenses_query)
expenses = []
for row in rrows:
if row.value_position.number > 0:
expenses.append(row)
return expenses
def get_paid_equities(entries, options, start_date, end_date):
expenses_query = f"""SELECT date, account, value(position) FROM
date >= {start_date} AND
date < {end_date.isoformat()}
WHERE account ~ \"Equity:LloguerMiquel\" OR account ~ \"Equity:FacturesUtilitatsMiquel\""""
rtypes, rrows = query.run_query(
entries, options, expenses_query)
return rrows
def find_matching_expense(expense, equities):
for equity in equities:
if equity.value_position == expense.value_position:
return True
return False
def find_missing_shared_expenses(expenses, equities):
missing_shared_expenses = []
for expense in expenses:
if not find_matching_expense(expense, equities):
missing_shared_expenses.append(expense)
return missing_shared_expenses
def print_report(missing_shared_expenses, start_date):
print("Missing shared expenses")
print(f"From {start_date}")
print(missing_shared_expenses)
report = {
"Date": [],
"Account": [],
"Amount": []
}
for expense in missing_shared_expenses:
report["Date"].append(expense.date)
report["Account"].append(expense.account)
report["Amount"].append(expense.value_position)
print(tabulate(report))
def main():
parser = argparse.ArgumentParser(
description='Find pending shared expenses (checks last 12 months)')
args = parser.parse_args()
# Calculate date range: 1 year ago to today
end_date = date.today()
start_date = end_date - timedelta(days=365)
print(f"Checking period: {start_date.isoformat()} to {
end_date.isoformat()}")
filename = "ledger/main.beancount"
entries, errors, options = loader.load_file(filename)
if errors:
printer.print_errors(errors)
return
expenses = get_shared_expenses(entries, options, start_date, end_date)
equities = get_paid_equities(entries, options, start_date, end_date)
missing_shared_expenses = find_missing_shared_expenses(expenses, equities)
print_report(missing_shared_expenses, start_date)
if __name__ == "__main__":
main()