mirror of
https://github.com/eitchtee/WYGIWYH.git
synced 2026-11-13 12:23:44 +01:00
Credit cards often have paid transactions dated after the invoice being closed, which made reconciliation against all paid transactions wrong. The reconciliation panel now lets you balance against all paid transactions (previous behavior), paid transactions up to a date, or paid transactions up to a reference month. The adjustment transaction is dated at the cutoff so later reconciliations with the same or a later cutoff include it. An invalid cutoff blocks the reconciliation instead of silently falling back.
113 lines
5.4 KiB
HTML
113 lines
5.4 KiB
HTML
{% extends 'extends/offcanvas.html' %}
|
|
{% load currency_display %}
|
|
{% load i18n %}
|
|
{% load crispy_forms_tags %}
|
|
|
|
{% block title %}{% translate 'Account Reconciliation' %}{% endblock %}
|
|
|
|
{% block body %}
|
|
<form hx-post="{% url 'account_reconciliation' %}">
|
|
{% csrf_token %}
|
|
{{ form.management_form }}
|
|
{# Picking a cutoff shows its field and re-fetches only the accounts list, with balances computed against it #}
|
|
<div class="mb-3"
|
|
hx-get="{% url 'account_reconciliation' %}"
|
|
hx-trigger="change"
|
|
hx-target="#reconciliation-accounts"
|
|
hx-select="#balanceAccordionFlush"
|
|
hx-include="this"
|
|
_="on change
|
|
set mode to (the first <input[name='cutoff-mode']:checked/> in me).value
|
|
for wrapper in <[data-cutoff-mode]/> in me
|
|
if wrapper's @data-cutoff-mode is mode
|
|
remove .hidden from wrapper
|
|
else
|
|
add .hidden to wrapper
|
|
end
|
|
end">
|
|
<div class="join w-full mb-3" role="group" aria-label="{{ cutoff.mode.label }}">
|
|
{% for value, label in cutoff.fields.mode.choices %}
|
|
<input type="radio"
|
|
class="join-item btn btn-primary btn-outline w-1/3"
|
|
name="{{ cutoff.mode.html_name }}"
|
|
id="{{ cutoff.mode.html_name }}_{{ forloop.counter }}"
|
|
value="{{ value }}"
|
|
aria-label="{{ label }}"
|
|
{% if value == cutoff.selected_mode %}checked{% endif %}>
|
|
{% endfor %}
|
|
</div>
|
|
<div data-cutoff-mode="date" {% if cutoff.selected_mode != "date" %}class="hidden"{% endif %}>
|
|
{{ cutoff.date|as_crispy_field }}
|
|
</div>
|
|
<div data-cutoff-mode="month" {% if cutoff.selected_mode != "month" %}class="hidden"{% endif %}>
|
|
{{ cutoff.month|as_crispy_field }}
|
|
</div>
|
|
</div>
|
|
{# Swapped rows bring fresh selects; the offcanvas only initializes TomSelect on first load #}
|
|
<div id="reconciliation-accounts"
|
|
_="on htmx:afterSettle
|
|
for x in <select/> in me
|
|
if not x.tomselect
|
|
remove .select from x
|
|
js(x) TomSelect(x) end
|
|
end
|
|
end">
|
|
<div class="join join-vertical w-full" id="balanceAccordionFlush">
|
|
{% for form in form.forms %}
|
|
<c-ui.components.collapse>
|
|
<c-slot name="title">
|
|
{% if form.account_group %}<span class="badge badge-primary badge-outline me-2">{{ form.account_group.name }}</span>{% endif %}{{ form.account_name }}
|
|
</c-slot>
|
|
<c-slot name="content">
|
|
<div class="fieldset">
|
|
<span class="fieldset-legend">{% translate 'Current balance' %}</span>
|
|
<div data-amount="{{ form.current_balance|floatformat:"-40u" }}"
|
|
data-decimal-places="{{ form.currency_decimal_places }}"
|
|
id="amount-{{ forloop.counter0 }}" class="text-base">
|
|
<c-amount.display
|
|
:amount="form.current_balance"
|
|
:prefix="form.currency_prefix"
|
|
:suffix="form.currency_suffix"
|
|
:decimal_places="form.currency_decimal_places"
|
|
color="auto"></c-amount.display>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
{% crispy form %}
|
|
</div>
|
|
<div class="fieldset">
|
|
<span class="fieldset-legend">{% translate 'Difference' %}</span>
|
|
<div class="text-base"
|
|
_="on input from #id_form-{{ forloop.counter0 }}-new_balance
|
|
set original_amount to parseFloat('{{ form.current_balance|floatformat:"-40u" }}')
|
|
then set prefix to '{{ form.currency_prefix }}'
|
|
then set suffix to '{{ form.currency_suffix }}'
|
|
then set decimal_places to {{ form.currency_decimal_places }}
|
|
then call parseLocaleNumber(#id_form-{{ forloop.counter0 }}-new_balance.value)
|
|
then set new_amount to result
|
|
then set diff to (Math.round((new_amount - original_amount) * Math.pow(10, decimal_places))) / Math.pow(10, decimal_places)
|
|
then set format_new_amount to
|
|
Intl.NumberFormat(
|
|
undefined,
|
|
{
|
|
minimumFractionDigits: decimal_places,
|
|
maximumFractionDigits: decimal_places,
|
|
roundingMode: 'trunc'
|
|
}
|
|
).format(diff)
|
|
then set formatted_string to `${prefix}${format_new_amount}${suffix}`
|
|
then put formatted_string into me if diff else put '-' into me">-</div>
|
|
</div>
|
|
</c-slot>
|
|
</c-ui.components.collapse>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
<div class="mt-3">
|
|
<div>
|
|
<input type="submit" name="submit" value="{% translate 'Reconcile balances' %}" class="btn btn-primary w-full" id="submit-id-submit">
|
|
</div>
|
|
</div>
|
|
</form>
|
|
{% endblock %}
|