From 33c1e9eb9d8fa334f455e755af7ca7f84ffc377a Mon Sep 17 00:00:00 2001 From: Tony Grosinger Date: Fri, 22 Jul 2022 14:59:19 -0700 Subject: [PATCH] Preliminary version seemingly functional --- data/example.ledger | 2 +- src/db.py | 89 ++++++++++++++++++++++++++++++++++++++++++--- src/ledger.py | 2 +- src/main.py | 5 +++ 4 files changed, 90 insertions(+), 8 deletions(-) diff --git a/data/example.ledger b/data/example.ledger index c460f21..d516a47 100644 --- a/data/example.ledger +++ b/data/example.ledger @@ -29,7 +29,7 @@ ; commodity $ 2008/01/01 income - assets:bank:checking $1 + assets:bank:checking $1.45 income:salary 2008/06/01 gift diff --git a/src/db.py b/src/db.py index 5507fb6..607d9c8 100644 --- a/src/db.py +++ b/src/db.py @@ -1,7 +1,7 @@ import sqlite3 from typing import List -from ledger import Transaction +from ledger import Posting, Transaction class CursorContextManager: @@ -38,17 +38,53 @@ def create_tables(cursor: sqlite3.Cursor) -> None: """ CREATE TABLE transactions ( + id integer, date text, - check_num text, - note text, - account text, - amount real, + comment text, cleared integer, tags text ) """ ) + cursor.execute( + """ + CREATE TABLE postings + ( + transaction_id integer, + account text, + amount real, + cleared integer, + tags text, + comment text + ) + """ + ) + + +def get_posting_amount(posting: Posting) -> float: + # TODO: Is there a way to denote that these fields are required and avoid all the None checking? + + amount = posting.get("pamount") + if amount is None or len(amount) != 1: + print("Unexpected number of amounts in posting") + print(posting) + return 0 + + quantity = amount[0].get("aquantity") + if quantity is None: + print("Unexpected number of amounts in posting") + print(posting) + return 0 + + val = quantity.get("floatingPoint") + if val is None: + print("Unexpected number of amounts in posting") + print(posting) + return 0 + + return val + def write_transactions(cursor: sqlite3.Cursor, txs: List[Transaction]) -> None: """ @@ -56,4 +92,45 @@ def write_transactions(cursor: sqlite3.Cursor, txs: List[Transaction]) -> None: and then store it. """ - print(txs[0]) + for transaction in txs: + cursor.execute( + """ + INSERT INTO transactions + ( + id, date, comment, cleared, tags + ) VALUES ( + ?, ?, ?, ?, ? + ) + """, + [ + transaction.get("tindex"), + transaction.get("tdate"), + transaction.get("tcomment"), + transaction.get("tstatus"), + ",".join(transaction.get("ttags") or []), + ], + ) + + postings = transaction.get("tpostings") + if postings is None: + continue + + for posting in postings: + cursor.execute( + """ + INSERT INTO postings + ( + transaction_id, account, amount, cleared, tags, comment + ) VALUES ( + ?, ?, ?, ?, ?, ? + ) + """, + [ + transaction.get("tindex"), + posting.get("paccount"), + get_posting_amount(posting), + posting.get("pstatus"), + ",".join(posting.get("ptags") or []), + posting.get("pcomment"), + ], + ) diff --git a/src/ledger.py b/src/ledger.py index 614c693..1b08cd3 100644 --- a/src/ledger.py +++ b/src/ledger.py @@ -7,7 +7,7 @@ import typing class AmountQuantity(typing.TypedDict): decimalMantissa: int decimalPlaces: int - floatingPoint: int + floatingPoint: float class AmountStyle(typing.TypedDict): diff --git a/src/main.py b/src/main.py index 0a758eb..43066e1 100644 --- a/src/main.py +++ b/src/main.py @@ -1,3 +1,8 @@ +""" +Convert the provided ledger file into a SQLite database. +Configure input and output files with environment variables. +""" + import os import os.path import sys