2022-12-24 18:20:42 +11:00
{# DrCr: Web-based double-entry bookkeeping framework
2023-01-02 18:08:30 +11:00
Copyright (C) 2022–2023 Lee Yingtong Li (RunasSudo)
2022-12-24 18:20:42 +11:00
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see < https: / / www . gnu . org / licenses / > .
#}
{% extends 'base.html' %}
2023-01-29 19:12:28 +11:00
{% block title %}{{ 'Edit' if transaction and transaction.id else 'New' }} transaction{% endblock %}
2022-12-24 18:20:42 +11:00
{% block content %}
2023-01-29 19:12:28 +11:00
< h1 class = "h2 my-4" > {{ 'Edit' if transaction and transaction.id else 'New' }} transaction< / h1 >
2022-12-24 18:20:42 +11:00
< form method = "POST" >
< table class = "table" >
< thead >
< tr >
< th > Date< / th >
< th colspan = "2" > Description< / th >
< th > Dr< / th >
< th > Cr< / th >
< / tr >
< / thead >
< tbody >
< tr >
2022-12-24 20:41:33 +11:00
< td > < input type = "date" name = "dt" class = "form-control" value = "{{ transaction.dt.strftime('%Y-%m-%d') if transaction else '' }}" > < / td >
< td colspan = "2" > < input type = "text" name = "description" value = "{{ transaction.description if transaction else '' }}" class = "form-control" > < / td >
2022-12-24 18:20:42 +11:00
< td > < / td >
< td > < / td >
< / tr >
2022-12-24 20:41:33 +11:00
{% if transaction %}
{% for posting in transaction.postings %}
< tr >
< td > < / td >
< td > < / td >
< td >
< div class = "input-group" >
< select class = "form-select" name = "sign" style = "flex-grow:0;min-width:5em" onchange = "changeDrCr(this)" >
< option value = "dr" { % if posting . quantity > = 0 %} selected{% endif %}>Dr< / option >
< option value = "cr" { % if posting . quantity < 0 % } selected { % endif % } > Cr< / option >
< / select >
< input type = "text" name = "account" class = "form-control" value = "{{ posting.account }}" >
< a class = "btn btn-outline-primary" href = "#" onclick = "addPosting(this);return false;" > < i class = "bi bi-plus-circle-fill" > < / i > < / a >
< / div >
< / td >
{% if posting.quantity >= 0 %}
< td class = "amount-dr has-amount" >
< div class = "input-group" >
< div class = "input-group-text" > $< / div >
2022-12-24 21:02:49 +11:00
< input type = "text" name = "amount" value = "{{ posting.amount().quantity_string() }}" class = "form-control" oninput = "changeAmount(this)" >
2022-12-24 20:41:33 +11:00
< / div >
< / td >
< td class = "amount-cr" > < / td >
{% else %}
2023-01-04 10:56:37 +11:00
< td class = "amount-dr" > < / td >
2022-12-24 20:41:33 +11:00
< td class = "amount-cr has-amount" >
< div class = "input-group" >
< div class = "input-group-text" > $< / div >
2022-12-24 21:02:49 +11:00
< input type = "text" name = "amount" value = "{{ (posting.amount()|abs).quantity_string() }}" class = "form-control" oninput = "changeAmount(this)" >
2022-12-24 20:41:33 +11:00
< / div >
< / td >
{% endif %}
< / tr >
{% endfor %}
{% else %}
< tr >
< td > < / td >
< td > < / td >
< td >
< div class = "input-group" >
< select class = "form-select" name = "sign" style = "flex-grow:0;min-width:5em" onchange = "changeDrCr(this)" >
< option value = "dr" selected > Dr< / option >
< option value = "cr" > Cr< / option >
< / select >
< input type = "text" name = "account" class = "form-control" >
< a class = "btn btn-outline-primary" href = "#" onclick = "addPosting(this);return false;" > < i class = "bi bi-plus-circle-fill" > < / i > < / a >
< / div >
< / td >
< td class = "amount-dr has-amount" >
< div class = "input-group" >
< div class = "input-group-text" > $< / div >
2022-12-24 21:02:49 +11:00
< input type = "text" name = "amount" class = "form-control" oninput = "changeAmount(this)" >
2022-12-24 20:41:33 +11:00
< / div >
< / td >
< td class = "amount-cr" > < / td >
< / tr >
< tr >
< td > < / td >
< td > < / td >
< td >
< div class = "input-group" >
< select class = "form-select" name = "sign" style = "flex-grow:0;min-width:5em" onchange = "changeDrCr(this)" >
< option value = "dr" > Dr< / option >
< option value = "cr" selected > Cr< / option >
< / select >
< input type = "text" name = "account" class = "form-control" >
< a class = "btn btn-outline-primary" href = "#" onclick = "addPosting(this);return false;" > < i class = "bi bi-plus-circle-fill" > < / i > < / a >
< / div >
< / td >
< td class = "amount-dr" > < / td >
< td class = "amount-cr has-amount" >
< div class = "input-group" >
< div class = "input-group-text" > $< / div >
2022-12-24 21:02:49 +11:00
< input type = "text" name = "amount" class = "form-control" oninput = "changeAmount(this)" >
2022-12-24 20:41:33 +11:00
< / div >
< / td >
< / tr >
{% endif %}
2022-12-24 18:20:42 +11:00
< / tbody >
< / table >
2023-01-29 19:12:28 +11:00
< div class = "d-flex" >
{% if transaction and transaction.id %}
< button type = "submit" name = "action" value = "delete" class = "btn btn-outline-danger" onclick = "confirm('Are you sure you want to delete this transaction? This operation is irreversible.')" > Delete< / button >
{% endif %}
< button type = "submit" class = "btn btn-primary ms-auto" > Save< / button >
2022-12-24 18:20:42 +11:00
< / div >
< / form >
{% endblock %}
2022-12-24 20:13:11 +11:00
{% block scripts %}
< script >
function changeDrCr(el) {
let trPosting = el.parentNode.parentNode.parentNode;
let amountContent = trPosting.querySelector('.has-amount').innerHTML;
let amountValue = trPosting.querySelector('.has-amount input').value;
// Remove input boxes
for (let td of trPosting.querySelectorAll('.amount-dr, .amount-cr')) {
td.innerHTML = '';
td.classList.remove('has-amount');
}
// Add correct input box
let td = trPosting.querySelector(el.value === 'dr' ? '.amount-dr' : '.amount-cr');
td.innerHTML = amountContent;
td.classList.add('has-amount');
td.querySelector('input').value = amountValue;
}
function addPosting(el) {
let trPosting = el.parentNode.parentNode.parentNode;
let sign = trPosting.querySelector('select').value; // Use same sign as row clicked
2022-12-24 21:02:49 +11:00
let inputAmount = '< div class = "input-group" > < div class = "input-group-text" > $< / div > < input type = "text" name = "amount" class = "form-control" oninput = "changeAmount(this)" > < / div > ';
2022-12-24 20:13:11 +11:00
// Add new posting row
let trNew = document.createElement('tr');
trNew.innerHTML = '< tr > < td > < / td > < td > < / td > < td > < div class = "input-group" > < select class = "form-select" name = "sign" style = "flex-grow:0;min-width:5em" onchange = "changeDrCr(this)" > < option value = "dr" ' + ( sign = == ' dr ' ? ' selected ' : ' ' ) + ' > Dr< / option > < option value = "cr" ' + ( sign = == ' cr ' ? ' selected ' : ' ' ) + ' > Cr< / option > < / select > < input type = "text" name = "account" class = "form-control" > < a class = "btn btn-outline-primary" href = "#" onclick = "addPosting(this);return false;" > < i class = "bi bi-plus-circle-fill" > < / i > < / a > < / div > < / td > ' + (sign === 'dr' ? ('< td class = "amount-dr has-amount" > ' + inputAmount + '< / td > ') : '< td class = "amount-dr" > < / td > ') + (sign === 'cr' ? ('< td class = "amount-cr has-amount" > ' + inputAmount + '< / td > ') : '< td class = "amount-cr" > < / td > ') + '< / tr > ';
trPosting.after(trNew);
}
2022-12-24 21:02:49 +11:00
function changeAmount(el) {
let amountInputs = document.querySelectorAll('input[name="amount"]');
if (amountInputs.length === 2) {
// Get other input
let otherInput;
for (inp of amountInputs) {
if (inp !== el) {
otherInput = inp;
break;
}
}
// Update other input with amount
otherInput.value = el.value;
}
}
2022-12-24 20:13:11 +11:00
< / script >
{% endblock %}