diff --git a/HISTORY.md b/HISTORY.md index 2aafa6f..cf9e425 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,15 @@ # История изменений ERP WaterSurf +## 2025-02-26 00:25 UTC – Единое отображение чисел с разделителями разрядов + +**Задача**: Везде, где выводятся числовые значения, показывать их с разделителем разрядов и запятой как десятичным разделителем. + +**Решение**: Добавлен шаблонный фильтр **ws_num** (documents/templatetags/document_filters.py): формат «1 851 635,50», неразрывный пробел между разрядами. Фильтр подключён во всех списках документов и на странице экономики заказа (суммы, маржа, проценты). + +**Изменения**: document_filters.py, шаблоны списков документов и customer_order_detail.html (load document_filters, вывод через |ws_num:2 или |ws_num:1). + +--- + ## 2025-02-26 00:15 UTC – Экономика заказа клиента: связи и отчёт **Задача**: Цепочка «Заказ клиента → Поступления денежных средств (несколько) → Заказ поставщику по заказу → Расход на оплату поставщику; плюс прочие расходы по заказу (логистика)». По заказу клиента видеть: сколько поступило, сколько потрачено, маржа, маржинальность, рентабельность. diff --git a/app/documents/templatetags/__init__.py b/app/documents/templatetags/__init__.py new file mode 100644 index 0000000..5c04f89 --- /dev/null +++ b/app/documents/templatetags/__init__.py @@ -0,0 +1 @@ +# Пакет тегов и фильтров для шаблонов документов diff --git a/app/documents/templatetags/document_filters.py b/app/documents/templatetags/document_filters.py new file mode 100644 index 0000000..aae0d60 --- /dev/null +++ b/app/documents/templatetags/document_filters.py @@ -0,0 +1,53 @@ +"""Фильтры для отображения чисел в шаблонах документов.""" +from django import template +from decimal import Decimal + +register = template.Library() + + +@register.filter +def ws_num(value, decimal_places=2): + """ + Форматирование числа с разделителем разрядов (неразрывный пробел) + и запятой как десятичным разделителем. + Пример: 1851635.5 -> "1 851 635,50" + """ + if value is None: + return "—" + try: + places = int(decimal_places) + except (TypeError, ValueError): + places = 2 + try: + if isinstance(value, (Decimal, float)): + n = float(value) + else: + n = float(value) + except (TypeError, ValueError): + return "—" + if places == 0: + s = f"{int(round(n))}" + else: + s = f"{n:.{decimal_places}f}" + if "." in s: + int_part, dec_part = s.split(".", 1) + else: + int_part, dec_part = s, "0" * places + # Разделитель тысяч — неразрывный пробел + if int_part.startswith("-"): + rest = int_part[1:] + formatted = "" + while len(rest) > 3: + formatted = "\u202f" + rest[-3:] + formatted + rest = rest[:-3] + int_part = "-" + rest + formatted if rest else "-" + formatted.lstrip("\u202f") + else: + formatted = "" + rest = int_part + while len(rest) > 3: + formatted = "\u202f" + rest[-3:] + formatted + rest = rest[:-3] + int_part = (rest + formatted) if rest else formatted.lstrip("\u202f") + if places == 0: + return int_part + return f"{int_part},{dec_part}" diff --git a/app/templates/documents/cash_expense_list.html b/app/templates/documents/cash_expense_list.html index 9f1344f..691b0a6 100644 --- a/app/templates/documents/cash_expense_list.html +++ b/app/templates/documents/cash_expense_list.html @@ -1,4 +1,5 @@ {% extends "base.html" %} +{% load document_filters %} {% block title %}Расходы денежных средств — ERP WaterSurf{% endblock %} {% block content %}
@@ -24,7 +25,7 @@ {{ obj.date }} {{ obj.number }} {{ obj.sender }} - {{ obj.amount }} + {{ obj.amount|ws_num:2 }} {{ obj.supplier_order|default:"—" }} Изменить diff --git a/app/templates/documents/cash_inflow_list.html b/app/templates/documents/cash_inflow_list.html index 7940b8a..592ff08 100644 --- a/app/templates/documents/cash_inflow_list.html +++ b/app/templates/documents/cash_inflow_list.html @@ -1,4 +1,5 @@ {% extends "base.html" %} +{% load document_filters %} {% block title %}Поступления денежных средств — ERP WaterSurf{% endblock %} {% block content %}
@@ -24,7 +25,7 @@ {{ obj.date }} {{ obj.number }} {{ obj.recipient }} - {{ obj.amount }} + {{ obj.amount|ws_num:2 }} {{ obj.customer_order|default:"—" }} Изменить diff --git a/app/templates/documents/cash_transfer_list.html b/app/templates/documents/cash_transfer_list.html index 5df216e..19144a9 100644 --- a/app/templates/documents/cash_transfer_list.html +++ b/app/templates/documents/cash_transfer_list.html @@ -1,4 +1,5 @@ {% extends "base.html" %} +{% load document_filters %} {% block title %}Перемещения денежных средств — ERP WaterSurf{% endblock %} {% block content %}
@@ -25,7 +26,7 @@ {{ obj.number }} {{ obj.sender }} {{ obj.recipient }} - {{ obj.amount }} + {{ obj.amount|ws_num:2 }} Изменить · diff --git a/app/templates/documents/customer_order_detail.html b/app/templates/documents/customer_order_detail.html index 10ba4b2..1e60515 100644 --- a/app/templates/documents/customer_order_detail.html +++ b/app/templates/documents/customer_order_detail.html @@ -1,4 +1,5 @@ {% extends "base.html" %} +{% load document_filters %} {% block title %}Заказ {{ object.number }} — ERP WaterSurf{% endblock %} {% block content %}
@@ -16,7 +17,7 @@

Организация: {{ object.organization }}

Клиент: {{ object.client }}

Вид заказа: {{ object.order_kind }}

-

Стоимость заказа: {{ object.total_amount|floatformat:2 }}

+

Стоимость заказа: {{ object.total_amount|ws_num:2 }}

@@ -25,31 +26,31 @@ Поступило от клиента (всего поступлений по заказу) - {{ economics.total_inflows|floatformat:2 }} + {{ economics.total_inflows|ws_num:2 }} Расходы: оплата поставщикам (по заказам поставщику по этому заказу) - −{{ economics.expenses_via_supplier|floatformat:2 }} + −{{ economics.expenses_via_supplier|ws_num:2 }} Расходы: прочие по заказу (логистика и т.п.) - −{{ economics.expenses_direct|floatformat:2 }} + −{{ economics.expenses_direct|ws_num:2 }} Всего расходов - −{{ economics.total_expenses|floatformat:2 }} + −{{ economics.total_expenses|ws_num:2 }} Маржа (поступления − расходы) - {{ economics.margin|floatformat:2 }} + {{ economics.margin|ws_num:2 }} Маржинальность (маржа / поступления) - {% if economics.margin_pct is not None %}{{ economics.margin_pct|floatformat:1 }}%{% else %}—{% endif %} + {% if economics.margin_pct is not None %}{{ economics.margin_pct|ws_num:1 }}%{% else %}—{% endif %} Рентабельность (маржа / расходы) - {% if economics.profitability_pct is not None %}{{ economics.profitability_pct|floatformat:1 }}%{% else %}—{% endif %} + {% if economics.profitability_pct is not None %}{{ economics.profitability_pct|ws_num:1 }}%{% else %}—{% endif %} @@ -75,7 +76,7 @@ {{ inv.date }} {{ inv.number }} {{ inv.recipient }} - {{ inv.amount|floatformat:2 }} + {{ inv.amount|ws_num:2 }} Изменить {% endfor %} @@ -108,7 +109,7 @@ {{ so.date }} {{ so.number }} {{ so.supplier }} - {{ so.total_amount|floatformat:2 }} + {{ so.total_amount|ws_num:2 }} Изменить {% endfor %} @@ -141,7 +142,7 @@ {{ ex.date }} {{ ex.number }} {{ ex.sender }} - {{ ex.amount|floatformat:2 }} + {{ ex.amount|ws_num:2 }} Изменить {% endfor %} diff --git a/app/templates/documents/customer_order_list.html b/app/templates/documents/customer_order_list.html index b922996..084d2c6 100644 --- a/app/templates/documents/customer_order_list.html +++ b/app/templates/documents/customer_order_list.html @@ -1,4 +1,5 @@ {% extends "base.html" %} +{% load document_filters %} {% block title %}Заказы клиентов — ERP WaterSurf{% endblock %} {% block content %}
@@ -27,7 +28,7 @@ {{ obj.order_kind }} {{ obj.organization }} {{ obj.client }} - {{ obj.total_amount }} + {{ obj.total_amount|ws_num:2 }} Изменить · diff --git a/app/templates/documents/supplier_order_list.html b/app/templates/documents/supplier_order_list.html index 6f9eaea..d6aaeea 100644 --- a/app/templates/documents/supplier_order_list.html +++ b/app/templates/documents/supplier_order_list.html @@ -1,4 +1,5 @@ {% extends "base.html" %} +{% load document_filters %} {% block title %}Заказы поставщику — ERP WaterSurf{% endblock %} {% block content %}
@@ -26,8 +27,8 @@ {{ obj.number }} {{ obj.organization }} {{ obj.supplier }} - {{ obj.total_in_currency }} - {{ obj.total_amount }} + {{ obj.total_in_currency|ws_num:2 }} + {{ obj.total_amount|ws_num:2 }} Изменить ·