expenses_manager/expenses_manager/expenses/templates/settings/budget_blocks.html

77 lines
3.6 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{% extends "expenses/base.html" %}
{% block title %}Reparto por bloques{% endblock %}
{% block content %}
<h1>Reparto por bloques</h1>
<p>Qué porcentaje de tus ingresos debería ir a cada bloque. Los bloques de gasto son los tipos que asignas a tus categorías; el ahorro son los traspasos a tus cuentas de ahorro.</p>
{# Arranca con el reparto guardado; el script de abajo lo recalcula al teclear. #}
<p id="budgetTotals" aria-live="polite">Asignado: {{ assigned|floatformat:"-2" }} %. Sin asignar: {{ unassigned|floatformat:"-2" }} %.</p>
{% if proposal %}
<p class="muted">
Junto a cada bloque tienes lo que fue de verdad del {{ proposal.date_from|date:"d/m/Y" }} al {{ proposal.date_to|date:"d/m/Y" }}, sobre tus ingresos de ese periodo.
{% if proposal.unclassified %}El {{ proposal.unclassified }} % se fue en gastos sin tipo, que no cuentan en ningún bloque.{% endif %}
</p>
{% else %}
<p class="muted">No hay ingresos en los últimos 12 meses completos, así que no se puede calcular una propuesta.</p>
{% endif %}
<form method="post" action="{% url 'budget_blocks' %}" class="app-form" id="budgetForm">
{% csrf_token %}
{% include "expenses/_form_fields.html" %}
<div class="form-actions">
<button type="submit" class="btn btn-primary">Guardar</button>
{% if proposal %}
<a class="btn btn-secondary" href="{% url 'budget_blocks' %}?propuesta=1">Usar valores calculados</a>
{% endif %}
<a class="btn btn-secondary" href="{% url 'settings_index' %}">Volver</a>
</div>
{% if proposal_total > 100 %}
<p class="form-errors">Los valores calculados suman un {{ proposal_total }} %: en ese periodo gastaste más de lo que ingresaste. Puedes cargarlos, pero tendrás que bajar algún bloque hasta que la suma no pase de 100 para poder guardar.</p>
{% endif %}
</form>
<script>
// Suma en vivo de los cinco bloques. Es solo comodidad: quien decide si
// se puede guardar es la validación del servidor.
(function () {
const form = document.getElementById('budgetForm');
const totals = document.getElementById('budgetTotals');
const names = [{% for field in form %}"{{ field.html_name }}",{% endfor %}];
function format(cents) {
return (cents / 100).toLocaleString('es-ES', { maximumFractionDigits: 2 });
}
function update() {
// En céntimos enteros y redondeados: sin el redondeo,
// 18,1 × 100 + 81,9 × 100 da 10000,000000000002 y avisaría
// de que pasa de 100.
let cents = 0;
names.forEach(function (name) {
const value = parseFloat(form.elements[name].value);
if (!isNaN(value)) {
cents += Math.round(value * 100);
}
});
if (cents > 10000) {
totals.textContent = 'Asignado: ' + format(cents) + ' %. Pasa de 100 por '
+ format(cents - 10000) + ' %: así no se podrá guardar.';
totals.className = 'form-errors';
} else {
totals.textContent = 'Asignado: ' + format(cents) + ' %. Sin asignar: '
+ format(10000 - cents) + ' %.';
totals.className = '';
}
}
form.addEventListener('input', update);
})();
</script>
{% endblock %}