Skip to content

Commit

Permalink
edit account form and route
Browse files Browse the repository at this point in the history
  • Loading branch information
Robert Gingras committed May 15, 2024
1 parent 0b1769c commit 14b386b
Show file tree
Hide file tree
Showing 2 changed files with 202 additions and 7 deletions.
64 changes: 63 additions & 1 deletion src/gnucash_web/book.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from flask import render_template, request, redirect, Blueprint
from flask import current_app as app
from piecash import Transaction, Split
from piecash import Transaction, Split, AccountType
from werkzeug.exceptions import BadRequest

from .auth import requires_auth, get_db_credentials
Expand Down Expand Up @@ -98,6 +98,7 @@ def show_account(account_name):
today=date.today(),
num_pages=num_pages,
page=page,
account_types=(t.value for t in AccountType if t != AccountType.root)
)


Expand Down Expand Up @@ -276,3 +277,64 @@ def del_transaction():
book.save()

return redirect(account_url(account))

@bp.route("/edit_account", methods=["POST"])
@requires_auth
def edit_account():
"""Edit an existing account.
All parameters are read from `request.form`.
:param guid: GUID of the account to edit
:param name: New name for the account
:param code: New code for the account
:param description: New description for the account
:param parent: The GUID of the new parent account
:param account_type: The name of the new account type
:param commodity: The mnemonic of the new commodity
:param commodity_scu: The smallest fraction for the commodity
:param placeholder: The placeholder state of the account
:param hidden: The hidden state of the account
"""
try:
guid = request.form["guid"]
name = request.form["name"]
code = request.form["code"]
description = request.form["description"]
parent = request.form["parent"]
account_type = request.form["type"]
commodity = request.form["commodity"]
commodity_scu = int(request.form["commodity_scu"])
placeholder = 1 if request.form.get("placeholder", "off") == "on" else 0
hidden = 1 if request.form.get("hidden", "off") == "on" else 0
except (InvalidOperation, ValueError) as e:
raise BadRequest(f"Invalid form parameter: {e}") from e

with open_book(
uri_conn=app.config.DB_URI(*get_db_credentials()),
readonly=False,
do_backup=False,
) as book:
account = get_account(book, guid=guid)
account.name = name
account.code = code
account.description = description
account.type = account_type
account.commodity = book.commodities.get(namespace='CURRENCY', mnemonic=commodity)
account.placeholder = placeholder
account.hidden = hidden

# workaround for piecash book.accounts not including root
account.parent = (
book.root_account
if parent == book.root_account.guid
else get_account(book, guid=parent)
)
account.commodity_scu = (
None # piecash use commodity default
if commodity_scu == -1
else commodity_scu
)
book.save()

return redirect(account_url(account))
145 changes: 139 additions & 6 deletions src/gnucash_web/templates/account.j2
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,18 @@

{% block content %}
{% if account.parent %}
<div id="total" class="my-3 list-group">
<div class="list-group-item">
<b>Total</b>
<span class="float-end">
{{ account.get_balance() | money(account.commodity) }}
</span>
<div class="container">
<div class="row">
<div class="me-2 border rounded p-2 col">
<b>Total</b>
<span class="float-end">
{{ account.get_balance() | money(account.commodity) }}
</span>
</div>
<button type="button" class="btn btn-outline-primary bi bi-pencil-fill col-auto"
data-bs-toggle="modal" data-bs-target="#account-edit"
title="Edit Account"
></button>
</div>
</div>
{% endif %}
Expand Down Expand Up @@ -118,6 +124,133 @@
{% endblock content %}

{% block modals %}
{% if account.parent %}
<div class="modal fade" id="account-edit">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Edit Account</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="edit_account" method="post" action="{{ url_for('book.edit_account') }}">
<input type="hidden" name="guid" value="{{ account.guid }}">
<div class="mb-2">
<label for="new_account_name" class="form-label text-body-secondary small">Account Name</label>
<input type="text" class="form-control"
name="name" id="new_account_name"
value="{{ account.name }}">
</div>
<div class="mb-2">
<label for="new_account_name" class="form-label text-body-secondary small">Account Code</label>
<input type="text" class="form-control"
name="code" id="new_account_code"
value="{{ account.code }}">
</div>
<div class="mb-2">
<label for="new_account_name" class="form-label text-body-secondary small">Description</label>
<input type="text" class="form-control"
name="description" id="new_account_desc"
value="{{ account.description }}">
</div>
<div class="mb-2">
<label for="new_account_parent" class="form-label text-body-secondary small">Parent Account</label>
<select name="parent" id="new_account_parent" class="form-select">
<option value="{{ book.root_account.guid }}">New top level account</option>
{% for p_account in book.root_account.children | sort(attribute='name') recursive %}
{% if p_account.guid != account.guid %}
<option value="{{ p_account.guid }}"
{% if p_account.guid == account.parent.guid %}
selected
{% endif %}
>
{{ p_account.fullname }}
</option>
{% if p_account.children %}
{{ loop(p_account.children) }}
{% endif %}
{% endif %}
{% endfor %}
</select>
</div>
<div class="mb-2">
<label for="new_account_type" class="form-label text-body-secondary small">Account Type</label>
<select name="type" id="new_account_type" class="form-select">
{% for account_type in account_types %}
<option value="{{ account_type }}"
{% if account_type == account.type %}
selected
{% endif %}
>
{{ account_type }}
</option>
{% endfor %}
</select>
</div>
<div class="mb-2">
<label for="new_account_commodity" class="form-label text-body-secondary small">Commodity</label>
<select name="commodity" id="new_account_commodity" class="form-select">
{% for commodity in book.commodities %}
<option value="{{ commodity.mnemonic }}"
{% if account.commodity == commodity %}
selected
{% endif %}
>
{{ commodity.mnemonic }}
</option>
{% endfor %}
</select>
</div>

<div class="mb-2">
<label for="new_account_commodity_scu" class="form-label text-body-secondary small">Smallest Fraction</label>
<select name="commodity_scu" id="new_account_commodity_scu" class="form-select">
<option value="-1"
{% if account.non_std_scu == 0 %}
selected
{% endif %}
>
Use Commodity Value
</option>
{% for n in range(10) %}
<option value="{{ 10 ** n }}"
{% if account.non_std_scu == 1 and account.commodity_scu == 10 ** n %}
selected
{% endif %}
>
1/{{10 ** n}}
</option>
{% endfor %}
</select>
</div>

<div class="form-check">
<input class="form-check-input" type="checkbox" name="placeholder" id="new_account_placeholder"
{% if account.placeholder == 1 %}
checked
{% endif %}
>
<label class="form-check-label" for="new_account_placeholder">Placeholder</label>
</div>

<div class="form-check">
<input class="form-check-input" type="checkbox" name="hidden" id="new_account_hidden"
{% if account.hidden == 1 %}
checked
{% endif %}
>
<label class="form-check-label" for="new_account_hidden">Hidden</label>
</div>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-primary" form="edit_account" type="submit">Save</button>
</div>
</div>
</div>
</div>
{% endif %}

{% if not account.placeholder and account.parent %}
<div class="modal fade" id="edit-transaction">
<div class="modal-dialog">
Expand Down

0 comments on commit 14b386b

Please sign in to comment.