Узнайте, как правильно рассчитать проценты за просрочку платежа в Польше с учётом изменения ставок. Практический код на Python и примеры.
Если вы выставляете счёт польскому бизнесу, а платят с опозданием, вам полагаются законные проценты. Простая формула проценты = сумма × ставка × дни / 365 часто неверна. Причина — ставка меняется за время долга, и расчёт нужно разбивать на периоды.
В Польше существуют две отдельные ставки законных процентов. Их путают чаще всего.
Odsetki ustawowe za opóźnienie (Гражданский кодекс) применяются к обычным обязательствам. Ставка привязана к референсной ставке Национального банка Польши (NBP) и меняется каждый раз, когда центробанк изменяет ставку, с даты решения.
Odsetki za opóźnienie w transakcjach handlowych применяются к коммерческим сделкам B2B. Эта ставка фиксируется на полугодие: на 1 января для первого полугодия и на 1 июля для второго. Она не меняется внутри полугодия, даже если NBP изменит ставку в марте.
Для одной и той же задержки в 200 дней первый режим может потребовать пять сегментов, а второй — ровно два. Выбор неправильного режима меняет не только число, но и саму структуру расчёта.
Как только вы принимаете, что ставка — это функция от времени, а не константа, расчёт превращается в свёртку по интервалам. Вот реализация на Python:
from datetime import date, timedelta
from typing import List, Tuple
def days_between(d1: date, d2: date) -> int:
"""Количество дней между датами (d2 - d1)."""
return (d2 - d1).days
def interest_for_periods(amount_grosze: int, periods: List[Tuple[date, date, float]]) -> int:
"""
Расчёт процентов по сегментам.
:param amount_grosze: сумма долга в грошах (целое число)
:param periods: список кортежей (from, to, rate_percent)
:return: сумма процентов в грошах
"""
total = 0
for from_date, to_date, rate_percent in periods:
days = days_between(from_date, to_date)
# Округление на каждом сегменте, работаем в целых грошах
total += round((amount_grosze * rate_percent * days) / (365 * 100))
return total
В этой небольшой функции три ключевых момента:
0.1 + 0.2 != 0.3, а проценты — это сумма многих малых слагаемых. Накопление в числах с плавающей точкой приводит к расхождению в один грош с расчётом бухгалтера контрагента, что превращает обсуждение оплаты в спор.Сама сегментация — это слияние окна задержки с временной шкалой ставок:
from datetime import date
from typing import List, Tuple
def split_by_rate_changes(
from_date: date,
to_date: date,
rate_table: List[Tuple[date, float]]
) -> List[Tuple[date, date, float]]:
"""
Разбивает интервал [from_date, to_date) на сегменты по изменениям ставок.
:param from_date: дата начала долга
:param to_date: дата окончания долга
:param rate_table: список кортежей (effective_from, rate_percent), отсортированных по дате
:return: список сегментов (from, to, rate_percent)
"""
# Сортируем таблицу ставок по дате вступления в силу
sorted_rates = sorted(rate_table, key=lambda x: x[0])
periods = []
for i, (eff_from, rate) in enumerate(sorted_rates):
start = eff_from
end = sorted_rates[i + 1][0] if i + 1 < len(sorted_rates) else to_date
# Обрезаем по окну задержки
seg_from = max(start, from_date)
seg_to = min(end, to_date)
if seg_from < seg_to:
periods.append((seg_from, seg_to, rate))
return periods
Для режима коммерческих сделок вы передаёте таблицу с двумя записями в год. Для режима Гражданского кодекса — каждое решение NBP. Одна и та же свёртка, разные входные данные. Разница режимов должна быть в данных, а не в логике управления.
Потому что ответ будет неверным, причём в легко заметную сторону. В цикле снижения ставок применение сегодняшней ставки ко всей задержке занижает сумму, которую вам должны. В цикле повышения — завышает, что ещё хуже: теперь ваше требование содержит цифру, которую должник может оспорить.
Прямо сейчас возьмите свой последний случай просрочки и проверьте, не используете ли вы одну ставку для всего периода. Если да — пересчитайте с учётом сегментации. Вы можете использовать приведённый код как основу для своего инструмента или обратиться к готовому решению.
Хочешь закрепить знания на практике?
Решай задачи на Algolit — интерактивная платформа для обучения
Начать бесплатно →