Add a bunch of fixes, categories

- Go through and update database
This commit is contained in:
Sara Montecino 2022-10-31 00:57:57 -07:00
parent 9e544ec64a
commit d986461019
8 changed files with 135 additions and 34 deletions

7
.vscode/launch.json vendored
View File

@ -11,7 +11,12 @@
"program": "main.py",
"console": "integratedTerminal",
"justMyCode": true,
"args": ["C:\\Users\\saram\\Downloads\\Statement_072022_4653.pdf"]
"args": [
// "C:\\Users\\saram\\Downloads\\Statement_072022_4653.pdf",
// "C:\\Users\\saram\\Downloads\\Statement_082022_4653.pdf",
"C:\\Users\\saram\\Downloads\\Statement_092022_4653.pdf",
"C:\\Users\\saram\\Downloads\\Statement_102022_4653.pdf",
]
},
{
"name": "Create Database",

47
app.py
View File

@ -105,23 +105,40 @@ def transaction(uuid=None):
# Default if no method is hit
abort(400)
@app.route("/categories")
@app.route("/categories", methods=["GET", "POST"])
def categories():
try:
raw_categories = database.TransactionCategory.select()
categories = {}
for category in raw_categories:
if not category.parent:
categories[category.name] = []
if request.method == "GET":
try:
raw_categories = database.TransactionCategory.select()
categories = {}
for category in raw_categories:
if not category.parent:
categories[category.name] = []
for category in raw_categories:
if category.parent:
categories[category.parent.name].append(category.name)
for category in raw_categories:
if category.parent:
categories[category.parent.name].append(category.name)
return categories
except peewee.DoesNotExist:
abort(404)
except:
abort(500)
return categories
except peewee.DoesNotExist:
abort(404)
except:
abort(500)
if request.method == "POST":
body = request.get_json()
try:
if 'parent' in body:
parent = database.TransactionCategory.get(database.TransactionCategory.name == body['parent'])
database.TransactionCategory.create(name=body['name'], parent=parent)
else:
database.TransactionCategory.create(name=body['name'])
return ('', 200)
except peewee.DoesNotExist:
abort(404)
except:
abort(500)
# Should never get here.
abort(500)
app.run()

BIN
budget.db Executable file

Binary file not shown.

View File

@ -53,12 +53,15 @@ class Transactions(Regex):
date = result[0]
description = " ".join(result[1].split())
is_payment = '-' in result[2]
is_credit = '-' in result[2]
amount = float(result[3].replace(',', ''))
if is_payment:
print(f"Skipping payment: {amount}")
continue
if is_credit:
if "AUTOPAY" in description:
print(f"Skipping payment: {amount}")
continue
amount *= -1
transactions.append([date, description, amount])

View File

@ -41,6 +41,15 @@ def add_default_categories():
for child in children:
TransactionCategory.create(name=child, parent=parent_db)
def delete_transactions():
instance.connect()
# august_2022 = datetime.datetime(2022, 8, 18, 0)
# delete_query = Transaction.delete().where(Transaction.transaction_date > august_2022)
delete_query = Transaction.delete().where(Transaction.primary_key == 83)
delete_query.execute()
instance.close()
class BaseModel(Model):
class Meta:
database = instance

View File

@ -34,7 +34,7 @@ for f in args.files:
transaction_date=date,
description=description,
amount=amount,
source_filename=filename,
source_file=filename,
type=file_parser.source
)
database.instance.close()

View File

@ -100,6 +100,12 @@
<button id="modal_next" class="next">Submit</button>
</div>
</div>
<h2>Add category</h2>
<label for="category_parent">Parent: </label>
<select id="category_parent"></select>
<label for="category_name">Name: </label>
<input id="category_name">
<button id="category_add">Add</button>
<!-- Transaction Modal End -->
</body>
<script>
@ -142,6 +148,13 @@
},
};
const category =
{
name_input: document.getElementById('category_name'),
parent_select: document.getElementById('category_parent'),
add_button: document.getElementById('category_add'),
};
// Global variables.
const global_data =
{
@ -153,7 +166,8 @@
process_index: 0,
unprocessed_cnt: function()
{
return this.unprocessed_indices.length;
const diff = this.unprocessed_indices.length - 1 - this.process_index
return diff >= 0 ? diff : 0;
},
get_current: function()
{
@ -303,7 +317,7 @@
{
x_action.split.container.style.display = 'block';
const transaction = global_data.transaction.get_current();
x_action.split.amount.value = transaction.amount / 2;
x_action.split.type.onchange();
}
else
{
@ -315,11 +329,11 @@
{
const selected = x_action.split.type.value;
const transaction = global_data.transaction.get_current();
if (selected == "Splitwise")
if (selected == 2) // Splitwise
{
x_action.split.amount.value = transaction.amount / 2;
}
else
else if (selected == 3) //SpaceX
{
x_action.split.amount.value = transaction.amount;
}
@ -346,9 +360,43 @@
x_action.subcategory.appendChild(opt);
}
}
}
category.add_button.onclick = function()
{
const body = {};
body.name = category.name_input.value;
const selected = category.parent_select.value;
if (selected != "none" )
{
body.parent = selected;
}
const url = "/categories";
const handler =
{
success: function()
{
get_categories();
},
error: function()
{
alert("Failed to add category");
}
}
http_request(url, handler, "POST", body);
category.parent_select.value = "none";
category.name_input.value = "";
}
category.name_input.onkeypress = function(event) {
if (event.key === "Enter")
{
event.preventDefault();
category.add_button.click();
}
};
function reset_transaction_ui(close_modal=true)
{
// Reset all stateful inputs.
@ -359,11 +407,13 @@
x_action.split.container.style.display = 'none';
x_action.split.enabled.checked = false;
x_action.split.notes.value = "";
x_action.category.innerHTML = "";
x_action.subcategory.innerHTML = "";
x_action.subcategory.disabled = "true";
x_action.notes.value = "";
}
function update_transaction_ui(transaction)
{
// Reset old state.
@ -408,6 +458,7 @@
{
success: function(data) {
global_data.categories = data
update_category_ui();
},
error: function() {
console.error("Failed to get categories");
@ -416,6 +467,22 @@
http_request(request_url, handler);
}
function update_category_ui()
{
function add_opt(key)
{
const opt = document.createElement("option");
opt.value = key;
opt.innerText = key;
category.parent_select.appendChild(opt);
}
category.parent_select.innerHTML = "";
add_opt("none");
for (key in global_data.categories) add_opt(key);
}
function http_request(url, response_handler, method="GET", body=null)
{
let request = new XMLHttpRequest();

View File

@ -4,11 +4,11 @@ Every week, I need to:
2. Update SplitWise for shared purchases
# Tasks
## Parse capital one statement
x Given a PDF bank statement from capital one, extract the transaction date, description, and amount from each transaction
xStore the data in a SQL lite database
x Create database schema
x Automatically add capital one transactions to database
Add web page to categorize transactions
Add web page to add categories
xParse capital one statement
x Given a PDF bank statement from capital one, extract the transaction date, description, and amount from each transaction
xStore the data in a SQL lite database
x Create database schema
x Automatically add capital one transactions to database
xAdd web page to categorize transactions
xAdd web page to add categories
Visualize spend for each month