feat(fees): reminder status column — sent/read tracking
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions

New "Przypomnienie" column in yearly fee view shows:
- Empty: no reminder sent yet → button "Przypomnij"
- "✉ Wysłano 20.03": sent but not read → button "Ponów"
- "✓ Odczytano 20.03": sent and read → button "Ponów"
Status derived from last PrivateMessage with "przypomnienie o składce".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maciej Pienczyn 2026-03-20 08:48:52 +01:00
parent 49fcdbdfb5
commit 069280870f
2 changed files with 31 additions and 3 deletions

View File

@ -667,7 +667,8 @@ def admin_fees():
'status': fee.status if fee else 'brak'
})
else:
company_data = {'company': company, 'months': {}, 'monthly_rate': 0, 'has_data': False}
company_data = {'company': company, 'months': {}, 'monthly_rate': 0, 'has_data': False, 'reminder': None}
has_unpaid = False
for m in range(1, 13):
fee = fees.get((company.id, m))
company_data['months'][m] = fee
@ -675,6 +676,23 @@ def admin_fees():
company_data['has_data'] = True
if not company_data['monthly_rate']:
company_data['monthly_rate'] = int(fee.amount)
if fee.status in ('pending', 'partial', 'overdue'):
has_unpaid = True
# Find last reminder message for this company
if has_unpaid:
from database import PrivateMessage, UserCompany
manager = db.query(UserCompany).filter(UserCompany.company_id == company.id).first()
if manager:
last_reminder = db.query(PrivateMessage).filter(
PrivateMessage.recipient_id == manager.user_id,
PrivateMessage.subject.ilike('%przypomnienie o składce%'),
).order_by(PrivateMessage.created_at.desc()).first()
if last_reminder:
company_data['reminder'] = {
'sent_at': last_reminder.created_at,
'is_read': last_reminder.is_read,
'read_at': last_reminder.read_at,
}
companies_fees.append(company_data)
# Sort: companies with fee data first, then without

View File

@ -356,6 +356,7 @@
{% else %}
<th>Sty</th><th>Lut</th><th>Mar</th><th>Kwi</th><th>Maj</th><th>Cze</th>
<th>Lip</th><th>Sie</th><th>Wrz</th><th>Paz</th><th>Lis</th><th>Gru</th>
<th>Przypomnienie</th>
<th></th>
{% endif %}
</tr>
@ -365,7 +366,7 @@
{% for cf in companies_fees %}
{% if not month and not cf.has_data and not ns.separator_shown %}
{% set ns.separator_shown = true %}
<tr><td colspan="13" style="background: var(--border); padding: var(--spacing-xs); text-align: center; font-size: var(--font-size-sm); color: var(--text-secondary); font-weight: 600;">Firmy bez danych o składkach</td></tr>
<tr><td colspan="15" style="background: var(--border); padding: var(--spacing-xs); text-align: center; font-size: var(--font-size-sm); color: var(--text-secondary); font-weight: 600;">Firmy bez danych o składkach</td></tr>
{% endif %}
<tr{% if not month and not cf.has_data %} style="opacity: 0.5;"{% endif %}>
{% if month %}
@ -422,9 +423,18 @@
{% endif %}
</td>
{% endfor %}
<td style="font-size:11px;white-space:nowrap;">
{% if cf.reminder %}
{% if cf.reminder.is_read %}
<span style="color:var(--success);" title="Odczytano {{ cf.reminder.read_at.strftime('%d.%m %H:%M') if cf.reminder.read_at else '' }}">✓ Odczytano {{ cf.reminder.sent_at.strftime('%d.%m') }}</span>
{% else %}
<span style="color:var(--text-secondary);" title="Wysłano {{ cf.reminder.sent_at.strftime('%d.%m.%Y %H:%M') }}">✉ Wysłano {{ cf.reminder.sent_at.strftime('%d.%m') }}</span>
{% endif %}
{% endif %}
</td>
<td>
{% if cf.has_data and cf.months.values()|selectattr('status', 'in', ['pending', 'partial', 'overdue'])|list %}
<button class="btn btn-small" style="font-size:11px;padding:2px 8px;background:var(--warning);color:white;border:none;" onclick="openReminderModal({{ cf.company.id }}, '{{ cf.company.name|e }}', {{ year }})">Przypomnij</button>
<button class="btn btn-small" style="font-size:11px;padding:2px 8px;background:var(--warning);color:white;border:none;" onclick="openReminderModal({{ cf.company.id }}, '{{ cf.company.name|e }}', {{ year }})">{{ 'Ponów' if cf.reminder else 'Przypomnij' }}</button>
{% endif %}
</td>
{% endif %}